diff options
| -rw-r--r-- | target/linux/generic-2.6/config-2.6.23 | 4 | ||||
| -rw-r--r-- | target/linux/generic-2.6/patches-2.6.23/100-netfilter_layer7_2.15.patch (renamed from target/linux/generic-2.6/patches-2.6.23/100-netfilter_layer7_2.9.patch) | 1446 | ||||
| -rw-r--r-- | target/linux/generic-2.6/patches-2.6.23/101-netfilter_layer7_pktmatch.patch | 109 | ||||
| -rw-r--r-- | target/linux/generic-2.6/patches-2.6.23/110-ipp2p_0.8.1rc1.patch | 36 | 
4 files changed, 757 insertions, 838 deletions
diff --git a/target/linux/generic-2.6/config-2.6.23 b/target/linux/generic-2.6/config-2.6.23 index 8f104b1d3..1287b320f 100644 --- a/target/linux/generic-2.6/config-2.6.23 +++ b/target/linux/generic-2.6/config-2.6.23 @@ -568,8 +568,8 @@ CONFIG_IP_NF_MATCH_ECN=m  CONFIG_IP_NF_MATCH_HASHLIMIT=m  CONFIG_IP_NF_MATCH_IPP2P=m  CONFIG_IP_NF_MATCH_IPRANGE=m -CONFIG_IP_NF_MATCH_LAYER7=m -# CONFIG_IP_NF_MATCH_LAYER7_DEBUG is not set +CONFIG_NETFILTER_XT_MATCH_LAYER7=m +# CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG is not set  CONFIG_IP_NF_MATCH_OWNER=m  CONFIG_IP_NF_MATCH_RECENT=m  CONFIG_IP_NF_MATCH_SET=m diff --git a/target/linux/generic-2.6/patches-2.6.23/100-netfilter_layer7_2.9.patch b/target/linux/generic-2.6/patches-2.6.23/100-netfilter_layer7_2.15.patch index 707e728a7..6c6fd5de9 100644 --- a/target/linux/generic-2.6/patches-2.6.23/100-netfilter_layer7_2.9.patch +++ b/target/linux/generic-2.6/patches-2.6.23/100-netfilter_layer7_2.15.patch @@ -1,668 +1,70 @@ -Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_layer7.h -=================================================================== ---- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_layer7.h	2007-09-21 16:23:59.000000000 +0800 -@@ -0,0 +1,26 @@ -+/* -+  By Matthew Strait <quadong@users.sf.net>, Dec 2003. -+  http://l7-filter.sf.net -+ -+  This program is free software; you can redistribute it and/or -+  modify it under the terms of the GNU General Public License -+  as published by the Free Software Foundation; either version -+  2 of the License, or (at your option) any later version. -+  http://www.gnu.org/licenses/gpl.txt -+*/ -+ -+#ifndef _IPT_LAYER7_H -+#define _IPT_LAYER7_H +--- linux-2.6.23.1/include/linux/netfilter/xt_layer7.h	1969-12-31 18:00:00.000000000 -0600 ++++ linux-2.6.23.1-layer7/include/linux/netfilter/xt_layer7.h	2007-11-02 21:19:46.000000000 -0500 +@@ -0,0 +1,13 @@ ++#ifndef _XT_LAYER7_H ++#define _XT_LAYER7_H  +  +#define MAX_PATTERN_LEN 8192  +#define MAX_PROTOCOL_LEN 256  + -+typedef char *(*proc_ipt_search) (char *, char, char *); -+ -+struct ipt_layer7_info { ++struct xt_layer7_info {  +    char protocol[MAX_PROTOCOL_LEN]; -+    char invert:1;  +    char pattern[MAX_PATTERN_LEN]; ++    u_int8_t invert;  +};  + -+#endif /* _IPT_LAYER7_H */ -Index: linux-2.6.23-rc6/net/netfilter/nf_conntrack_core.c -=================================================================== ---- linux-2.6.23-rc6.orig/net/netfilter/nf_conntrack_core.c	2007-09-21 16:23:54.000000000 +0800 -+++ linux-2.6.23-rc6/net/netfilter/nf_conntrack_core.c	2007-09-21 16:23:59.000000000 +0800 -@@ -207,6 +207,13 @@ - 	 * too. */ - 	nf_ct_remove_expectations(ct); ++#endif /* _XT_LAYER7_H */ +--- linux-2.6.23.1/include/net/netfilter/nf_conntrack.h	2007-10-12 11:43:44.000000000 -0500 ++++ linux-2.6.23.1-layer7/include/net/netfilter/nf_conntrack.h	2007-11-02 21:19:46.000000000 -0500 +@@ -127,6 +127,22 @@ struct nf_conn + 	u_int32_t secmark; + #endif -+	#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE) -+	if(ct->layer7.app_proto) -+		kfree(ct->layer7.app_proto); -+	if(ct->layer7.app_data) -+		kfree(ct->layer7.app_data); -+	#endif ++#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \ ++    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) ++	struct { ++		/* ++		 * e.g. "http". NULL before decision. "unknown" after decision ++		 * if no match. ++		 */ ++		char *app_proto; ++		/* ++		 * application layer data so far. NULL after match decision. ++		 */ ++		char *app_data; ++		unsigned int app_data_len; ++	} layer7; ++#endif  + - 	/* We overload first tuple to link into unconfirmed list. */ - 	if (!nf_ct_is_confirmed(ct)) { - 		BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode)); -Index: linux-2.6.23-rc6/net/netfilter/nf_conntrack_standalone.c -=================================================================== ---- linux-2.6.23-rc6.orig/net/netfilter/nf_conntrack_standalone.c	2007-09-21 16:23:54.000000000 +0800 -+++ linux-2.6.23-rc6/net/netfilter/nf_conntrack_standalone.c	2007-09-21 16:23:59.000000000 +0800 -@@ -179,6 +179,12 @@ + 	/* Storage reserved for other modules: */ + 	union nf_conntrack_proto proto; +  +--- linux-2.6.23.1/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c	2007-10-12 11:43:44.000000000 -0500 ++++ linux-2.6.23.1-layer7/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c	2007-11-07 06:58:31.000000000 -0600 +@@ -158,6 +158,12 @@ static int ct_seq_show(struct seq_file *   		return -ENOSPC;   #endif -+#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE) -+	if(conntrack->layer7.app_proto) -+		if (seq_printf(s, "l7proto=%s ",conntrack->layer7.app_proto)) -+			return 1; ++#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) ++        if(ct->layer7.app_proto) ++                if(seq_printf(s, "l7proto=%s ", ct->layer7.app_proto)) ++                        return -ENOSPC;  +#endif  + - 	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use))) + 	if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))   		return -ENOSPC; -Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_layer7.c -=================================================================== ---- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/ipt_layer7.c	2007-09-21 16:23:59.000000000 +0800 -@@ -0,0 +1,583 @@ -+/* -+  Kernel module to match application layer (OSI layer 7) data in connections. -+ -+  http://l7-filter.sf.net -+ -+  By Matthew Strait and Ethan Sommer, 2003-2006. -+ -+  This program is free software; you can redistribute it and/or -+  modify it under the terms of the GNU General Public License -+  as published by the Free Software Foundation; either version -+  2 of the License, or (at your option) any later version. -+  http://www.gnu.org/licenses/gpl.txt -+ -+  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be> -+  and cls_layer7.c (C) 2003 Matthew Strait, Ethan Sommer, Justin Levandoski -+ -+  Jan Engelhardt, 2007-03-11: Arrange to compile with nf_conntrack -+*/ -+ -+#include <linux/module.h> -+#include <linux/skbuff.h> -+#include <linux/proc_fs.h> -+#include <linux/ctype.h> -+#include <net/ip.h> -+#include <net/tcp.h> -+#include <net/netfilter/nf_conntrack.h> -+#include <net/netfilter/nf_nat_rule.h> -+#include <linux/spinlock.h> -+ -+#include "regexp/regexp.c" -+ -+#include <linux/netfilter_ipv4/ipt_layer7.h> -+#include <linux/netfilter_ipv4/ip_tables.h> -+ -+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("iptables application layer match module"); -+MODULE_VERSION("2.0"); -+ -+static int maxdatalen = 2048; // this is the default -+module_param(maxdatalen, int, 0444); -+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); -+ -+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG -+	#define DPRINTK(format,args...) printk(format,##args) -+#else -+	#define DPRINTK(format,args...) -+#endif -+ -+#define TOTAL_PACKETS master_conntrack->counters[IP_CT_DIR_ORIGINAL].packets + \ -+		      master_conntrack->counters[IP_CT_DIR_REPLY].packets -+ -+/* Number of packets whose data we look at. -+This can be modified through /proc/net/layer7_numpackets */ -+static int num_packets = 10; -+ -+static struct pattern_cache { -+	char * regex_string; -+	regexp * pattern; -+	struct pattern_cache * next; -+} * first_pattern_cache = NULL; -+ -+/* I'm new to locking.  Here are my assumptions: -+ -+- No one will write to /proc/net/layer7_numpackets over and over very fast; -+  if they did, nothing awful would happen. -+ -+- This code will never be processing the same packet twice at the same time, -+  because iptables rules are traversed in order. -+ -+- It doesn't matter if two packets from different connections are in here at -+  the same time, because they don't share any data. -+ -+- It _does_ matter if two packets from the same connection (or one from a -+  master and one from its child) are here at the same time.  In this case, -+  we have to protect the conntracks and the list of compiled patterns. -+*/ -+DEFINE_RWLOCK(ct_lock); -+DEFINE_SPINLOCK(list_lock); -+ -+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG -+/* Converts an unfriendly string into a friendly one by -+replacing unprintables with periods and all whitespace with " ". */ -+static char * friendly_print(unsigned char * s) -+{ -+	char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); -+	int i; -+ -+	if(!f) { -+		if (net_ratelimit()) -+			printk(KERN_ERR "layer7: out of memory in friendly_print, bailing.\n"); -+		return NULL; -+	} -+ -+	for(i = 0; i < strlen(s); i++){ -+		if(isprint(s[i]) && s[i] < 128)	f[i] = s[i]; -+		else if(isspace(s[i]))		f[i] = ' '; -+		else 				f[i] = '.'; -+	} -+	f[i] = '\0'; -+	return f; -+} -+ -+static char dec2hex(int i) -+{ -+	switch (i) { -+		case 0 ... 9: -+			return (char)(i + '0'); -+			break; -+		case 10 ... 15: -+			return (char)(i - 10 + 'a'); -+			break; -+		default: -+			if (net_ratelimit()) -+				printk("Problem in dec2hex\n"); -+			return '\0'; -+	} -+} -+ -+static char * hex_print(unsigned char * s) -+{ -+	char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); -+	int i; -+ -+	if(!g) { -+	       if (net_ratelimit()) -+			printk(KERN_ERR "layer7: out of memory in hex_print, bailing.\n"); -+	       return NULL; -+	} -+ -+	for(i = 0; i < strlen(s); i++) { -+		g[i*3    ] = dec2hex(s[i]/16); -+		g[i*3 + 1] = dec2hex(s[i]%16); -+		g[i*3 + 2] = ' '; -+	} -+	g[i*3] = '\0'; -+ -+	return g; -+} -+#endif // DEBUG -+ -+/* Use instead of regcomp.  As we expect to be seeing the same regexps over and -+over again, it make sense to cache the results. */ -+static regexp * compile_and_cache(char * regex_string, char * protocol) -+{ -+	struct pattern_cache * node               = first_pattern_cache; -+	struct pattern_cache * last_pattern_cache = first_pattern_cache; -+	struct pattern_cache * tmp; -+	unsigned int len; -+ -+	while (node != NULL) { -+		if (!strcmp(node->regex_string, regex_string)) -+		return node->pattern; -+ -+		last_pattern_cache = node;/* points at the last non-NULL node */ -+		node = node->next; -+	} -+ -+	/* If we reach the end of the list, then we have not yet cached -+	   the pattern for this regex. Let's do that now. -+	   Be paranoid about running out of memory to avoid list corruption. */ -+	tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); -+ -+	if(!tmp) { -+		if (net_ratelimit()) -+			printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n"); -+		return NULL; -+	} -+ -+	tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); -+	tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC); -+	tmp->next = NULL; -+ -+	if(!tmp->regex_string || !tmp->pattern) { -+		if (net_ratelimit()) -+			printk(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n"); -+		kfree(tmp->regex_string); -+		kfree(tmp->pattern); -+		kfree(tmp); -+		return NULL; -+	} -+ -+	/* Ok.  The new node is all ready now. */ -+	node = tmp; -+ -+	if(first_pattern_cache == NULL) /* list is empty */ -+		first_pattern_cache = node; /* make node the beginning */ -+	else -+		last_pattern_cache->next = node; /* attach node to the end */ -+ -+	/* copy the string and compile the regex */ -+	len = strlen(regex_string); -+	DPRINTK("About to compile this: \"%s\"\n", regex_string); -+	node->pattern = regcomp(regex_string, &len); -+	if ( !node->pattern ) { -+		if (net_ratelimit()) -+			printk(KERN_ERR "layer7: Error compiling regexp \"%s\" (%s)\n", regex_string, protocol); -+		/* pattern is now cached as NULL, so we won't try again. */ -+	} -+ -+	strcpy(node->regex_string, regex_string); -+	return node->pattern; -+} -+ -+static int can_handle(const struct sk_buff *skb) -+{ -+	if(!ip_hdr(skb)) /* not IP */ -+		return 0; -+	if(ip_hdr(skb)->protocol != IPPROTO_TCP && -+	   ip_hdr(skb)->protocol != IPPROTO_UDP && -+	   ip_hdr(skb)->protocol != IPPROTO_ICMP) -+		return 0; -+	return 1; -+} -+ -+/* Returns offset the into the skb->data that the application data starts */ -+static int app_data_offset(const struct sk_buff *skb) -+{ -+	/* In case we are ported somewhere (ebtables?) where ip_hdr(skb) -+	isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ -+	int ip_hl = 4*ip_hdr(skb)->ihl; -+ -+	if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { -+		/* 12 == offset into TCP header for the header length field. -+		Can't get this with skb->h.th->doff because the tcphdr -+		struct doesn't get set when routing (this is confirmed to be -+		true in Netfilter as well as QoS.) */ -+		int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); -+ -+		return ip_hl + tcp_hl; -+	} else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) { -+		return ip_hl + 8; /* UDP header is always 8 bytes */ -+	} else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { -+		return ip_hl + 8; /* ICMP header is 8 bytes */ -+	} else { -+		if (net_ratelimit()) -+			printk(KERN_ERR "layer7: tried to handle unknown protocol!\n"); -+		return ip_hl + 8; /* something reasonable */ -+	} -+} -+ -+/* handles whether there's a match when we aren't appending data anymore */ -+static int match_no_append(struct nf_conn * conntrack, struct nf_conn * master_conntrack, -+			enum ip_conntrack_info ctinfo, enum ip_conntrack_info master_ctinfo, -+			struct ipt_layer7_info * info) -+{ -+	/* If we're in here, throw the app data away */ -+	write_lock(&ct_lock); -+	if(master_conntrack->layer7.app_data != NULL) { -+ -+	#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG -+		if(!master_conntrack->layer7.app_proto) { -+			char * f = friendly_print(master_conntrack->layer7.app_data); -+			char * g = hex_print(master_conntrack->layer7.app_data); -+			DPRINTK("\nl7-filter gave up after %d bytes (%d packets):\n%s\n", -+				strlen(f), TOTAL_PACKETS, f); -+			kfree(f); -+			DPRINTK("In hex: %s\n", g); -+			kfree(g); -+		} -+	#endif -+ -+		kfree(master_conntrack->layer7.app_data); -+		master_conntrack->layer7.app_data = NULL; /* don't free again */ -+	} -+	write_unlock(&ct_lock); -+ -+	if(master_conntrack->layer7.app_proto){ -+		/* Here child connections set their .app_proto (for /proc/net/ip_conntrack) */ -+		write_lock(&ct_lock); -+		if(!conntrack->layer7.app_proto) { -+			conntrack->layer7.app_proto = kmalloc(strlen(master_conntrack->layer7.app_proto)+1, GFP_ATOMIC); -+			if(!conntrack->layer7.app_proto){ -+				if (net_ratelimit()) -+					printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n"); -+				write_unlock(&ct_lock); -+				return 1; -+			} -+			strcpy(conntrack->layer7.app_proto, master_conntrack->layer7.app_proto); -+		} -+		write_unlock(&ct_lock); -+ -+		return (!strcmp(master_conntrack->layer7.app_proto, info->protocol)); -+	} -+	else { -+		/* If not classified, set to "unknown" to distinguish from -+		connections that are still being tested. */ -+		write_lock(&ct_lock); -+		master_conntrack->layer7.app_proto = kmalloc(strlen("unknown")+1, GFP_ATOMIC); -+		if(!master_conntrack->layer7.app_proto){ -+			if (net_ratelimit()) -+				printk(KERN_ERR "layer7: out of memory in match_no_append, bailing.\n"); -+			write_unlock(&ct_lock); -+			return 1; -+		} -+		strcpy(master_conntrack->layer7.app_proto, "unknown"); -+		write_unlock(&ct_lock); -+		return 0; -+	} -+} -+ -+/* add the new app data to the conntrack.  Return number of bytes added. */ -+static int add_data(struct nf_conn * master_conntrack, -+			char * app_data, int appdatalen) -+{ -+	int length = 0, i; -+	int oldlength = master_conntrack->layer7.app_data_len; -+ -+	// This is a fix for a race condition by Deti Fliegl. However, I'm not -+	// clear on whether the race condition exists or whether this really -+	// fixes it.  I might just be being dense... Anyway, if it's not really -+	// a fix, all it does is waste a very small amount of time. -+	if(!master_conntrack->layer7.app_data) return 0; -+ -+	/* Strip nulls. Make everything lower case (our regex lib doesn't -+	do case insensitivity).  Add it to the end of the current data. */ -+	for(i = 0; i < maxdatalen-oldlength-1 && -+		   i < appdatalen; i++) { -+		if(app_data[i] != '\0') { -+			master_conntrack->layer7.app_data[length+oldlength] = -+				/* the kernel version of tolower mungs 'upper ascii' */ -+				isascii(app_data[i])? tolower(app_data[i]) : app_data[i]; -+			length++; -+		} -+	} -+ -+	master_conntrack->layer7.app_data[length+oldlength] = '\0'; -+	master_conntrack->layer7.app_data_len = length + oldlength; -+ -+	return length; -+} -+ -+/* Returns true on match and false otherwise.  */ -+static bool match(const struct sk_buff *skbin, -+	const struct net_device *in, const struct net_device *out, -+	const struct xt_match *match, const void *matchinfo, -+	int offset, unsigned int protoff, bool *hotdrop) -+{ -+	/* sidestep const without getting a compiler warning... */ -+	struct sk_buff * skb = (struct sk_buff *)skbin; -+ -+	struct ipt_layer7_info * info = (struct ipt_layer7_info *)matchinfo; -+	enum ip_conntrack_info master_ctinfo, ctinfo; -+	struct nf_conn *master_conntrack; -+	struct nf_conn *conntrack; -+	unsigned char * app_data; -+	unsigned int pattern_result, appdatalen; -+	regexp * comppattern; -+ -+	if(!can_handle(skb)){ -+		DPRINTK("layer7: This is some protocol I can't handle.\n"); -+		return info->invert; -+	} -+ -+	/* Treat parent & all its children together as one connection, except -+	for the purpose of setting conntrack->layer7.app_proto in the actual -+	connection. This makes /proc/net/ip_conntrack more satisfying. */ -+	if(((conntrack = nf_ct_get((struct sk_buff *)skb, &ctinfo)) == NULL) || -+	   ((master_conntrack = nf_ct_get((struct sk_buff *)skb, &master_ctinfo)) == NULL)) { -+		return info->invert; -+	} -+ -+	/* Try to get a master conntrack (and its master etc) for FTP, etc. */ -+	while (master_ct(master_conntrack) != NULL) -+		master_conntrack = master_ct(master_conntrack); -+ -+	/* if we've classified it or seen too many packets */ -+	if(TOTAL_PACKETS > num_packets || -+	   master_conntrack->layer7.app_proto) { -+ -+		pattern_result = match_no_append(conntrack, master_conntrack, ctinfo, master_ctinfo, info); -+ -+		/* skb->cb[0] == seen. Don't do things twice if there are multiple l7 -+		rules. I'm not sure that using cb for this purpose is correct, even though -+		it says "put your private variables there". But it doesn't look like it -+		is being used for anything else in the skbs that make it here. */ -+		skb->cb[0] = 1; /* marking it seen here is probably irrelevant, but consistant */ -+ -+		return (pattern_result ^ info->invert); -+	} -+ -+	if(skb_is_nonlinear(skb)){ -+		if(skb_linearize(skb) != 0){ -+			if (net_ratelimit()) -+				printk(KERN_ERR "layer7: failed to linearize packet, bailing.\n"); -+			return info->invert; -+		} -+	} -+ -+	/* now that the skb is linearized, it's safe to set these. */ -+	app_data = skb->data + app_data_offset(skb); -+	appdatalen = skb->tail - app_data; -+ -+	spin_lock_bh(&list_lock); -+	/* the return value gets checked later, when we're ready to use it */ -+	comppattern = compile_and_cache(info->pattern, info->protocol); -+	spin_unlock_bh(&list_lock); -+ -+	/* On the first packet of a connection, allocate space for app data */ -+	write_lock(&ct_lock); -+	if(TOTAL_PACKETS == 1 && !skb->cb[0] && !master_conntrack->layer7.app_data) { -+		master_conntrack->layer7.app_data = kmalloc(maxdatalen, GFP_ATOMIC); -+		if(!master_conntrack->layer7.app_data){ -+			if (net_ratelimit()) -+				printk(KERN_ERR "layer7: out of memory in match, bailing.\n"); -+			write_unlock(&ct_lock); -+			return info->invert; -+		} -+ -+		master_conntrack->layer7.app_data[0] = '\0'; -+	} -+	write_unlock(&ct_lock); -+ -+	/* Can be here, but unallocated, if numpackets is increased near -+	the beginning of a connection */ -+	if(master_conntrack->layer7.app_data == NULL) -+		return (info->invert); /* unmatched */ -+ -+	if(!skb->cb[0]){ -+		int newbytes; -+		write_lock(&ct_lock); -+		newbytes = add_data(master_conntrack, app_data, appdatalen); -+		write_unlock(&ct_lock); -+ -+		if(newbytes == 0) { /* didn't add any data */ -+			skb->cb[0] = 1; -+			/* Didn't match before, not going to match now */ -+			return info->invert; -+		} -+	} -+ -+	/* If looking for "unknown", then never match.  "Unknown" means that -+	we've given up; we're still trying with these packets. */ -+	read_lock(&ct_lock); -+	if(!strcmp(info->protocol, "unknown")) { -+		pattern_result = 0; -+	/* If looking for "unset", then always match. "Unset" means that we -+	haven't yet classified the connection. */ -+	} else if(!strcmp(info->protocol, "unset")) { -+		pattern_result = 2; -+		DPRINTK("layer7: matched unset: not yet classified (%d/%d packets)\n", TOTAL_PACKETS, num_packets); -+	/* If the regexp failed to compile, don't bother running it */ -+	} else if(comppattern && regexec(comppattern, master_conntrack->layer7.app_data)) { -+		DPRINTK("layer7: matched %s\n", info->protocol); -+		pattern_result = 1; -+	} else pattern_result = 0; -+	read_unlock(&ct_lock); -+ -+	if(pattern_result == 1) { -+		write_lock(&ct_lock); -+		master_conntrack->layer7.app_proto = kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); -+		if(!master_conntrack->layer7.app_proto){ -+			if (net_ratelimit()) -+				printk(KERN_ERR "layer7: out of memory in match, bailing.\n"); -+			write_unlock(&ct_lock); -+			return (pattern_result ^ info->invert); -+		} -+		strcpy(master_conntrack->layer7.app_proto, info->protocol); -+		write_unlock(&ct_lock); -+	} else if(pattern_result > 1) { /* cleanup from "unset" */ -+		pattern_result = 1; -+	} -+ -+	/* mark the packet seen */ -+	skb->cb[0] = 1; -+ -+	return (pattern_result ^ info->invert); -+} -+ -+static struct xt_match layer7_match = { -+	.name = "layer7", -+	.match = &match, -+	.matchsize  = sizeof(struct ipt_layer7_info), -+	.family = AF_INET, -+	.me = THIS_MODULE -+}; -+ -+/* taken from drivers/video/modedb.c */ -+static int my_atoi(const char *s) -+{ -+	int val = 0; -+ -+	for (;; s++) { -+		switch (*s) { -+			case '0'...'9': -+			val = 10*val+(*s-'0'); -+			break; -+		default: -+			return val; -+		} -+	} -+} -+ -+/* write out num_packets to userland. */ -+static int layer7_read_proc(char* page, char ** start, off_t off, int count, -+		     int* eof, void * data) -+{ -+	if(num_packets > 99 && net_ratelimit()) -+		printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); -+ -+	page[0] = num_packets/10 + '0'; -+	page[1] = num_packets%10 + '0'; -+	page[2] = '\n'; -+	page[3] = '\0'; -+ -+	*eof=1; -+ -+	return 3; -+} -+ -+/* Read in num_packets from userland */ -+static int layer7_write_proc(struct file* file, const char* buffer, -+		      unsigned long count, void *data) -+{ -+	char * foo = kmalloc(count, GFP_ATOMIC); -+ -+	if(!foo){ -+		if (net_ratelimit()) -+			printk(KERN_ERR "layer7: out of memory, bailing. num_packets unchanged.\n"); -+		return count; -+	} -+ -+	if(copy_from_user(foo, buffer, count)) { -+		return -EFAULT; -+	} -+ -+ -+	num_packets = my_atoi(foo); -+	kfree (foo); -+ -+	/* This has an arbitrary limit to make the math easier. I'm lazy. -+	But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ -+	if(num_packets > 99) { -+		printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); -+		num_packets = 99; -+	} else if(num_packets < 1) { -+		printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); -+		num_packets = 1; -+	} -+ -+	return count; -+} -+ -+/* register the proc file */ -+static void layer7_init_proc(void) -+{ -+	struct proc_dir_entry* entry; -+	entry = create_proc_entry("layer7_numpackets", 0644, proc_net); -+	entry->read_proc = layer7_read_proc; -+	entry->write_proc = layer7_write_proc; -+} -+ -+static void layer7_cleanup_proc(void) -+{ -+	remove_proc_entry("layer7_numpackets", proc_net); -+} -+ -+static int __init ipt_layer7_init(void) -+{ -+	need_conntrack(); -+ -+	layer7_init_proc(); -+	if(maxdatalen < 1) { -+		printk(KERN_WARNING "layer7: maxdatalen can't be < 1, using 1\n"); -+		maxdatalen = 1; -+	} -+	/* This is not a hard limit.  It's just here to prevent people from -+	bringing their slow machines to a grinding halt. */ -+	else if(maxdatalen > 65536) { -+		printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, using 65536\n"); -+		maxdatalen = 65536; -+	} -+	return xt_register_match(&layer7_match); -+} -+ -+static void __exit ipt_layer7_fini(void) -+{ -+	layer7_cleanup_proc(); -+	xt_unregister_match(&layer7_match); -+} -+ -+module_init(ipt_layer7_init); -+module_exit(ipt_layer7_fini); -Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig -=================================================================== ---- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Kconfig	2007-09-21 16:23:54.000000000 +0800 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig	2007-09-21 16:23:59.000000000 +0800 -@@ -63,6 +63,24 @@ +--- linux-2.6.23.1/net/netfilter/Kconfig	2007-10-12 11:43:44.000000000 -0500 ++++ linux-2.6.23.1-layer7/net/netfilter/Kconfig	2007-11-02 21:19:46.000000000 -0500 +@@ -633,6 +633,27 @@ config NETFILTER_XT_MATCH_STATE   	  To compile it as a module, choose M here.  If unsure, say N. -+config IP_NF_MATCH_LAYER7 -+	tristate "Layer 7 match support (EXPERIMENTAL)" -+	depends on IP_NF_IPTABLES && NF_CT_ACCT && NF_CONNTRACK && EXPERIMENTAL ++config NETFILTER_XT_MATCH_LAYER7 ++	tristate '"layer7" match support' ++	depends on NETFILTER_XTABLES ++	depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK) ++       depends on NF_CT_ACCT  +	help  +	  Say Y if you want to be able to classify connections (and their  +	  packets) based on regular expression matching of their application @@ -672,32 +74,61 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig  +  +	  To compile it as a module, choose M here.  If unsure, say N.  + -+config IP_NF_MATCH_LAYER7_DEBUG -+	bool "Layer 7 debugging output" -+	depends on IP_NF_MATCH_LAYER7 -+	help -+	  Say Y to get lots of debugging output. -+ - config IP_NF_MATCH_TOS - 	tristate "TOS match support" - 	depends on IP_NF_IPTABLES -Index: linux-2.6.23-rc6/net/ipv4/netfilter/Makefile -=================================================================== ---- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Makefile	2007-09-21 16:23:54.000000000 +0800 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/Makefile	2007-09-21 16:23:59.000000000 +0800 -@@ -50,6 +50,8 @@ - obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o - obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o ++config NETFILTER_XT_MATCH_LAYER7_DEBUG ++        bool 'Layer 7 debugging output' ++        depends on NETFILTER_XT_MATCH_LAYER7 ++        help ++          Say Y to get lots of debugging output. ++ ++ + config NETFILTER_XT_MATCH_STATISTIC + 	tristate '"statistic" match support' + 	depends on NETFILTER_XTABLES +--- linux-2.6.23.1/net/netfilter/Makefile	2007-10-12 11:43:44.000000000 -0500 ++++ linux-2.6.23.1-layer7/net/netfilter/Makefile	2007-11-02 21:19:46.000000000 -0500 +@@ -71,6 +71,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) + + obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o + obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o + obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o ++obj-$(CONFIG_NETFILTER_XT_MATCH_LAYER7) += xt_layer7.o + obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o + obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o + obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o +--- linux-2.6.23.1/net/netfilter/nf_conntrack_core.c	2007-10-12 11:43:44.000000000 -0500 ++++ linux-2.6.23.1-layer7/net/netfilter/nf_conntrack_core.c	2007-11-02 21:19:46.000000000 -0500 +@@ -207,6 +207,14 @@ destroy_conntrack(struct nf_conntrack *n + 	 * too. */ + 	nf_ct_remove_expectations(ct); +  ++	#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) ++	if(ct->layer7.app_proto) ++		kfree(ct->layer7.app_proto); ++	if(ct->layer7.app_data) ++	kfree(ct->layer7.app_data); ++	#endif ++ ++ + 	/* We overload first tuple to link into unconfirmed list. */ + 	if (!nf_ct_is_confirmed(ct)) { + 		BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode)); +--- linux-2.6.23.1/net/netfilter/nf_conntrack_standalone.c	2007-10-12 11:43:44.000000000 -0500 ++++ linux-2.6.23.1-layer7/net/netfilter/nf_conntrack_standalone.c	2007-11-07 06:59:13.000000000 -0600 +@@ -179,7 +179,12 @@ static int ct_seq_show(struct seq_file * + 		return -ENOSPC; + #endif +  +-	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use))) ++#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) ++	if(conntrack->layer7.app_proto) ++		if(seq_printf(s, "l7proto=%s ", conntrack->layer7.app_proto)) ++			return -ENOSPC; ++#endif ++	if (seq_printf(s, "asdfuse=%u\n", atomic_read(&conntrack->ct_general.use))) + 		return -ENOSPC; -+obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o -+ - # targets - obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o - obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o -Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.c -=================================================================== ---- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.c	2007-09-21 16:23:59.000000000 +0800 + 	return 0; +--- linux-2.6.23.1/net/netfilter/regexp/regexp.c	1969-12-31 18:00:00.000000000 -0600 ++++ linux-2.6.23.1-layer7/net/netfilter/regexp/regexp.c	2007-11-02 21:19:46.000000000 -0500  @@ -0,0 +1,1197 @@  +/*  + * regcomp and regexec -- regsub and regerror are elsewhere @@ -935,7 +366,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.c  +	register int len;  +	int flags;  +	struct match_globals g; -+ ++	  +	/* commented out by ethan  +	   extern char *malloc();  +	*/ @@ -1062,7 +493,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.c  +	}  +  +	/* Make a closing node, and hook it on the end. */ -+	ender = regnode(g, (paren) ? CLOSE+parno : END); ++	ender = regnode(g, (paren) ? CLOSE+parno : END);	  +	regtail(g, ret, ender);  +  +	/* Hook the tails of the branches to the closing node. */ @@ -1896,10 +1327,8 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.c  +#endif  +  + -Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.h -=================================================================== ---- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.h	2007-09-21 16:23:59.000000000 +0800 +--- linux-2.6.23.1/net/netfilter/regexp/regexp.h	1969-12-31 18:00:00.000000000 -0600 ++++ linux-2.6.23.1-layer7/net/netfilter/regexp/regexp.h	2007-11-02 21:19:46.000000000 -0500  @@ -0,0 +1,41 @@  +/*  + * Definitions etc. for regexp(3) routines. @@ -1942,20 +1371,16 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regexp.h  +void regerror(char *s);  +  +#endif -Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regmagic.h -=================================================================== ---- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regmagic.h	2007-09-21 16:23:59.000000000 +0800 +--- linux-2.6.23.1/net/netfilter/regexp/regmagic.h	1969-12-31 18:00:00.000000000 -0600 ++++ linux-2.6.23.1-layer7/net/netfilter/regexp/regmagic.h	2007-11-02 21:19:46.000000000 -0500  @@ -0,0 +1,5 @@  +/*  + * The first byte of the regexp internal "program" is actually this magic  + * number; the start node begins in the second byte.  + */  +#define	MAGIC	0234 -Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regsub.c -=================================================================== ---- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regsub.c	2007-09-21 16:23:59.000000000 +0800 +--- linux-2.6.23.1/net/netfilter/regexp/regsub.c	1969-12-31 18:00:00.000000000 -0600 ++++ linux-2.6.23.1-layer7/net/netfilter/regexp/regsub.c	2007-11-02 21:19:46.000000000 -0500  @@ -0,0 +1,95 @@  +/*  + * regsub @@ -2013,7 +1438,7 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regsub.c  +	register char c;  +	register int no;  +	register int len; -+ ++	  +	/* Not necessary and gcc doesn't like it -MLS */  +	/*extern char *strncpy();*/  + @@ -2052,29 +1477,632 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/regexp/regsub.c  +	}  +	*dst++ = '\0';  +} -Index: linux-2.6.23-rc6/include/net/netfilter/nf_conntrack.h -=================================================================== ---- linux-2.6.23-rc6.orig/include/net/netfilter/nf_conntrack.h	2007-09-21 16:23:54.000000000 +0800 -+++ linux-2.6.23-rc6/include/net/netfilter/nf_conntrack.h	2007-09-21 16:23:59.000000000 +0800 -@@ -127,6 +127,21 @@ - 	u_int32_t secmark; - #endif -  -+#if defined(CONFIG_IP_NF_MATCH_LAYER7) || defined(CONFIG_IP_NF_MATCH_LAYER7_MODULE) -+	struct { -+		/* -+		 * e.g. "http". NULL before decision. "unknown" after decision -+		 * if no match. -+		 */ -+		char *app_proto; -+		/* -+		 * application layer data so far. NULL after match decision. -+		 */ -+		char *app_data; -+		unsigned int app_data_len; -+	} layer7; +--- linux-2.6.23.1/net/netfilter/xt_layer7.c	1969-12-31 18:00:00.000000000 -0600 ++++ linux-2.6.23.1-layer7/net/netfilter/xt_layer7.c	2007-11-02 21:19:46.000000000 -0500 +@@ -0,0 +1,626 @@ ++/* ++  Kernel module to match application layer (OSI layer 7) data in connections. ++ ++  http://l7-filter.sf.net ++ ++  (C) 2003, 2004, 2005, 2006, 2007 Matthew Strait and Ethan Sommer. ++ ++  This program is free software; you can redistribute it and/or ++  modify it under the terms of the GNU General Public License ++  as published by the Free Software Foundation; either version ++  2 of the License, or (at your option) any later version. ++  http://www.gnu.org/licenses/gpl.txt ++ ++  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>, ++  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait, ++  Ethan Sommer, Justin Levandoski. ++*/ ++ ++#include <linux/spinlock.h> ++#include <net/ip.h> ++#include <net/tcp.h> ++#include <linux/module.h> ++#include <linux/skbuff.h> ++#include <linux/netfilter.h> ++#include <net/netfilter/nf_conntrack.h> ++#include <net/netfilter/nf_conntrack_core.h> ++#include <linux/netfilter/x_tables.h> ++#include <linux/netfilter/xt_layer7.h> ++#include <linux/ctype.h> ++#include <linux/proc_fs.h> ++ ++#include "regexp/regexp.c" ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); ++MODULE_DESCRIPTION("iptables application layer match module"); ++MODULE_ALIAS("ipt_layer7"); ++MODULE_VERSION("2.0"); ++ ++static int maxdatalen = 2048; // this is the default ++module_param(maxdatalen, int, 0444); ++MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); ++#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG ++	#define DPRINTK(format,args...) printk(format,##args) ++#else ++	#define DPRINTK(format,args...)  +#endif  + - 	/* Storage reserved for other modules: */ - 	union nf_conntrack_proto proto; -  ++#define TOTAL_PACKETS master_conntrack->counters[IP_CT_DIR_ORIGINAL].packets + \ ++		      master_conntrack->counters[IP_CT_DIR_REPLY].packets ++ ++/* Number of packets whose data we look at. ++This can be modified through /proc/net/layer7_numpackets */ ++static int num_packets = 10; ++ ++static struct pattern_cache { ++	char * regex_string; ++	regexp * pattern; ++	struct pattern_cache * next; ++} * first_pattern_cache = NULL; ++ ++DEFINE_SPINLOCK(l7_lock); ++ ++#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG ++/* Converts an unfriendly string into a friendly one by ++replacing unprintables with periods and all whitespace with " ". */ ++static char * friendly_print(unsigned char * s) ++{ ++	char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); ++	int i; ++ ++	if(!f) { ++		if (net_ratelimit()) ++			printk(KERN_ERR "layer7: out of memory in " ++					"friendly_print, bailing.\n"); ++		return NULL; ++	} ++ ++	for(i = 0; i < strlen(s); i++){ ++		if(isprint(s[i]) && s[i] < 128)	f[i] = s[i]; ++		else if(isspace(s[i]))		f[i] = ' '; ++		else 				f[i] = '.'; ++	} ++	f[i] = '\0'; ++	return f; ++} ++ ++static char dec2hex(int i) ++{ ++	switch (i) { ++		case 0 ... 9: ++			return (i + '0'); ++			break; ++		case 10 ... 15: ++			return (i - 10 + 'a'); ++			break; ++		default: ++			if (net_ratelimit()) ++				printk("layer7: Problem in dec2hex\n"); ++			return '\0'; ++	} ++} ++ ++static char * hex_print(unsigned char * s) ++{ ++	char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); ++	int i; ++ ++	if(!g) { ++	       if (net_ratelimit()) ++			printk(KERN_ERR "layer7: out of memory in hex_print, " ++					"bailing.\n"); ++	       return NULL; ++	} ++ ++	for(i = 0; i < strlen(s); i++) { ++		g[i*3    ] = dec2hex(s[i]/16); ++		g[i*3 + 1] = dec2hex(s[i]%16); ++		g[i*3 + 2] = ' '; ++	} ++	g[i*3] = '\0'; ++ ++	return g; ++} ++#endif // DEBUG ++ ++/* Use instead of regcomp.  As we expect to be seeing the same regexps over and ++over again, it make sense to cache the results. */ ++static regexp * compile_and_cache(const char * regex_string,  ++                                  const char * protocol) ++{ ++	struct pattern_cache * node               = first_pattern_cache; ++	struct pattern_cache * last_pattern_cache = first_pattern_cache; ++	struct pattern_cache * tmp; ++	unsigned int len; ++ ++	while (node != NULL) { ++		if (!strcmp(node->regex_string, regex_string)) ++		return node->pattern; ++ ++		last_pattern_cache = node;/* points at the last non-NULL node */ ++		node = node->next; ++	} ++ ++	/* If we reach the end of the list, then we have not yet cached ++	   the pattern for this regex. Let's do that now. ++	   Be paranoid about running out of memory to avoid list corruption. */ ++	tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); ++ ++	if(!tmp) { ++		if (net_ratelimit()) ++			printk(KERN_ERR "layer7: out of memory in " ++					"compile_and_cache, bailing.\n"); ++		return NULL; ++	} ++ ++	tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); ++	tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC); ++	tmp->next = NULL; ++ ++	if(!tmp->regex_string || !tmp->pattern) { ++		if (net_ratelimit()) ++			printk(KERN_ERR "layer7: out of memory in " ++					"compile_and_cache, bailing.\n"); ++		kfree(tmp->regex_string); ++		kfree(tmp->pattern); ++		kfree(tmp); ++		return NULL; ++	} ++ ++	/* Ok.  The new node is all ready now. */ ++	node = tmp; ++ ++	if(first_pattern_cache == NULL) /* list is empty */ ++		first_pattern_cache = node; /* make node the beginning */ ++	else ++		last_pattern_cache->next = node; /* attach node to the end */ ++ ++	/* copy the string and compile the regex */ ++	len = strlen(regex_string); ++	DPRINTK("About to compile this: \"%s\"\n", regex_string); ++	node->pattern = regcomp((char *)regex_string, &len); ++	if ( !node->pattern ) { ++		if (net_ratelimit()) ++			printk(KERN_ERR "layer7: Error compiling regexp " ++					"\"%s\" (%s)\n",  ++					regex_string, protocol); ++		/* pattern is now cached as NULL, so we won't try again. */ ++	} ++ ++	strcpy(node->regex_string, regex_string); ++	return node->pattern; ++} ++ ++static int can_handle(const struct sk_buff *skb) ++{ ++	if(!ip_hdr(skb)) /* not IP */ ++		return 0; ++	if(ip_hdr(skb)->protocol != IPPROTO_TCP && ++	   ip_hdr(skb)->protocol != IPPROTO_UDP && ++	   ip_hdr(skb)->protocol != IPPROTO_ICMP) ++		return 0; ++	return 1; ++} ++ ++/* Returns offset the into the skb->data that the application data starts */ ++static int app_data_offset(const struct sk_buff *skb) ++{ ++	/* In case we are ported somewhere (ebtables?) where ip_hdr(skb) ++	isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ ++	int ip_hl = 4*ip_hdr(skb)->ihl; ++ ++	if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { ++		/* 12 == offset into TCP header for the header length field. ++		Can't get this with skb->h.th->doff because the tcphdr ++		struct doesn't get set when routing (this is confirmed to be ++		true in Netfilter as well as QoS.) */ ++		int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); ++ ++		return ip_hl + tcp_hl; ++	} else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) { ++		return ip_hl + 8; /* UDP header is always 8 bytes */ ++	} else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { ++		return ip_hl + 8; /* ICMP header is 8 bytes */ ++	} else { ++		if (net_ratelimit()) ++			printk(KERN_ERR "layer7: tried to handle unknown " ++					"protocol!\n"); ++		return ip_hl + 8; /* something reasonable */ ++	} ++} ++ ++/* handles whether there's a match when we aren't appending data anymore */ ++static int match_no_append(struct nf_conn * conntrack,  ++                           struct nf_conn * master_conntrack,  ++                           enum ip_conntrack_info ctinfo, ++                           enum ip_conntrack_info master_ctinfo, ++                           const struct xt_layer7_info * info) ++{ ++	/* If we're in here, throw the app data away */ ++	if(master_conntrack->layer7.app_data != NULL) { ++ ++	#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG ++		if(!master_conntrack->layer7.app_proto) { ++			char * f =  ++			  friendly_print(master_conntrack->layer7.app_data); ++			char * g =  ++			  hex_print(master_conntrack->layer7.app_data); ++			DPRINTK("\nl7-filter gave up after %d bytes " ++				"(%d packets):\n%s\n", ++				strlen(f), TOTAL_PACKETS, f); ++			kfree(f); ++			DPRINTK("In hex: %s\n", g); ++			kfree(g); ++		} ++	#endif ++ ++		kfree(master_conntrack->layer7.app_data); ++		master_conntrack->layer7.app_data = NULL; /* don't free again */ ++	} ++ ++	if(master_conntrack->layer7.app_proto){ ++		/* Here child connections set their .app_proto (for /proc) */ ++		if(!conntrack->layer7.app_proto) { ++			conntrack->layer7.app_proto =  ++			  kmalloc(strlen(master_conntrack->layer7.app_proto)+1,  ++			    GFP_ATOMIC); ++			if(!conntrack->layer7.app_proto){ ++				if (net_ratelimit()) ++					printk(KERN_ERR "layer7: out of memory " ++							"in match_no_append, " ++							"bailing.\n"); ++				return 1; ++			} ++			strcpy(conntrack->layer7.app_proto,  ++				master_conntrack->layer7.app_proto); ++		} ++ ++		return (!strcmp(master_conntrack->layer7.app_proto,  ++				info->protocol)); ++	} ++	else { ++		/* If not classified, set to "unknown" to distinguish from ++		connections that are still being tested. */ ++		master_conntrack->layer7.app_proto =  ++			kmalloc(strlen("unknown")+1, GFP_ATOMIC); ++		if(!master_conntrack->layer7.app_proto){ ++			if (net_ratelimit()) ++				printk(KERN_ERR "layer7: out of memory in " ++						"match_no_append, bailing.\n"); ++			return 1; ++		} ++		strcpy(master_conntrack->layer7.app_proto, "unknown"); ++		return 0; ++	} ++} ++ ++/* add the new app data to the conntrack.  Return number of bytes added. */ ++static int add_data(struct nf_conn * master_conntrack, ++                    char * app_data, int appdatalen) ++{ ++	int length = 0, i; ++	int oldlength = master_conntrack->layer7.app_data_len; ++ ++	/* This is a fix for a race condition by Deti Fliegl. However, I'm not  ++	   clear on whether the race condition exists or whether this really  ++	   fixes it.  I might just be being dense... Anyway, if it's not really  ++	   a fix, all it does is waste a very small amount of time. */ ++	if(!master_conntrack->layer7.app_data) return 0; ++ ++	/* Strip nulls. Make everything lower case (our regex lib doesn't ++	do case insensitivity).  Add it to the end of the current data. */ ++	for(i = 0; i < maxdatalen-oldlength-1 && ++		   i < appdatalen; i++) { ++		if(app_data[i] != '\0') { ++			/* the kernel version of tolower mungs 'upper ascii' */ ++			master_conntrack->layer7.app_data[length+oldlength] = ++				isascii(app_data[i])?  ++					tolower(app_data[i]) : app_data[i]; ++			length++; ++		} ++	} ++ ++	master_conntrack->layer7.app_data[length+oldlength] = '\0'; ++	master_conntrack->layer7.app_data_len = length + oldlength; ++ ++	return length; ++} ++ ++/* taken from drivers/video/modedb.c */ ++static int my_atoi(const char *s) ++{ ++	int val = 0; ++ ++	for (;; s++) { ++		switch (*s) { ++			case '0'...'9': ++			val = 10*val+(*s-'0'); ++			break; ++		default: ++			return val; ++		} ++	} ++} ++ ++/* write out num_packets to userland. */ ++static int layer7_read_proc(char* page, char ** start, off_t off, int count, ++                            int* eof, void * data) ++{ ++	if(num_packets > 99 && net_ratelimit()) ++		printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); ++ ++	page[0] = num_packets/10 + '0'; ++	page[1] = num_packets%10 + '0'; ++	page[2] = '\n'; ++	page[3] = '\0'; ++ ++	*eof=1; ++ ++	return 3; ++} ++ ++/* Read in num_packets from userland */ ++static int layer7_write_proc(struct file* file, const char* buffer, ++                             unsigned long count, void *data) ++{ ++	char * foo = kmalloc(count, GFP_ATOMIC); ++ ++	if(!foo){ ++		if (net_ratelimit()) ++			printk(KERN_ERR "layer7: out of memory, bailing. " ++					"num_packets unchanged.\n"); ++		return count; ++	} ++ ++	if(copy_from_user(foo, buffer, count)) { ++		return -EFAULT; ++	} ++ ++ ++	num_packets = my_atoi(foo); ++	kfree (foo); ++ ++	/* This has an arbitrary limit to make the math easier. I'm lazy. ++	But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ ++	if(num_packets > 99) { ++		printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); ++		num_packets = 99; ++	} else if(num_packets < 1) { ++		printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); ++		num_packets = 1; ++	} ++ ++	return count; ++} ++ ++static int ++match(const struct sk_buff *skbin, ++      const struct net_device *in, ++      const struct net_device *out, ++      const struct xt_match *match, ++      const void *matchinfo, ++      int offset, ++      unsigned int protoff, ++      int *hotdrop) ++{ ++	/* sidestep const without getting a compiler warning... */ ++	struct sk_buff * skb = (struct sk_buff *)skbin;  ++ ++	const struct xt_layer7_info * info = matchinfo; ++	enum ip_conntrack_info master_ctinfo, ctinfo; ++	struct nf_conn *master_conntrack, *conntrack; ++	unsigned char * app_data; ++	unsigned int pattern_result, appdatalen; ++	regexp * comppattern; ++ ++	/* Be paranoid/incompetent - lock the entire match function. */ ++	spin_lock_bh(&l7_lock); ++ ++	if(!can_handle(skb)){ ++		DPRINTK("layer7: This is some protocol I can't handle.\n"); ++		spin_unlock_bh(&l7_lock); ++		return info->invert; ++	} ++ ++	/* Treat parent & all its children together as one connection, except ++	for the purpose of setting conntrack->layer7.app_proto in the actual ++	connection. This makes /proc/net/ip_conntrack more satisfying. */ ++	if(!(conntrack = nf_ct_get(skb, &ctinfo)) || ++	   !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ ++		DPRINTK("layer7: couldn't get conntrack.\n"); ++		spin_unlock_bh(&l7_lock); ++		return info->invert; ++	} ++ ++	/* Try to get a master conntrack (and its master etc) for FTP, etc. */ ++	while (master_ct(master_conntrack) != NULL) ++		master_conntrack = master_ct(master_conntrack); ++ ++	/* if we've classified it or seen too many packets */ ++	if(TOTAL_PACKETS > num_packets || ++	   master_conntrack->layer7.app_proto) { ++ ++		pattern_result = match_no_append(conntrack, master_conntrack,  ++						 ctinfo, master_ctinfo, info); ++ ++		/* skb->cb[0] == seen. Don't do things twice if there are  ++		multiple l7 rules. I'm not sure that using cb for this purpose  ++		is correct, even though it says "put your private variables  ++		there". But it doesn't look like it is being used for anything ++		else in the skbs that make it here. */ ++		skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ ++ ++		spin_unlock_bh(&l7_lock); ++		return (pattern_result ^ info->invert); ++	} ++ ++	if(skb_is_nonlinear(skb)){ ++		if(skb_linearize(skb) != 0){ ++			if (net_ratelimit()) ++				printk(KERN_ERR "layer7: failed to linearize " ++						"packet, bailing.\n"); ++			spin_unlock_bh(&l7_lock); ++			return info->invert; ++		} ++	} ++ ++	/* now that the skb is linearized, it's safe to set these. */ ++	app_data = skb->data + app_data_offset(skb); ++	appdatalen = skb_tail_pointer(skb) - app_data; ++ ++	/* the return value gets checked later, when we're ready to use it */ ++	comppattern = compile_and_cache(info->pattern, info->protocol); ++ ++	/* On the first packet of a connection, allocate space for app data */ ++	if(TOTAL_PACKETS == 1 && !skb->cb[0] &&  ++	   !master_conntrack->layer7.app_data){ ++		master_conntrack->layer7.app_data =  ++			kmalloc(maxdatalen, GFP_ATOMIC); ++		if(!master_conntrack->layer7.app_data){ ++			if (net_ratelimit()) ++				printk(KERN_ERR "layer7: out of memory in " ++						"match, bailing.\n"); ++			spin_unlock_bh(&l7_lock); ++			return info->invert; ++		} ++ ++		master_conntrack->layer7.app_data[0] = '\0'; ++	} ++ ++	/* Can be here, but unallocated, if numpackets is increased near ++	the beginning of a connection */ ++	if(master_conntrack->layer7.app_data == NULL){ ++		spin_unlock_bh(&l7_lock); ++		return (info->invert); /* unmatched */ ++	} ++ ++	if(!skb->cb[0]){ ++		int newbytes; ++		newbytes = add_data(master_conntrack, app_data, appdatalen); ++ ++		if(newbytes == 0) { /* didn't add any data */ ++			skb->cb[0] = 1; ++			/* Didn't match before, not going to match now */ ++			spin_unlock_bh(&l7_lock); ++			return info->invert; ++		} ++	} ++ ++	/* If looking for "unknown", then never match.  "Unknown" means that ++	we've given up; we're still trying with these packets. */ ++	if(!strcmp(info->protocol, "unknown")) { ++		pattern_result = 0; ++	/* If looking for "unset", then always match. "Unset" means that we ++	haven't yet classified the connection. */ ++	} else if(!strcmp(info->protocol, "unset")) { ++		pattern_result = 2; ++		DPRINTK("layer7: matched unset: not yet classified " ++			"(%d/%d packets)\n", TOTAL_PACKETS, num_packets); ++	/* If the regexp failed to compile, don't bother running it */ ++	} else if(comppattern &&  ++		  regexec(comppattern, master_conntrack->layer7.app_data)){ ++		DPRINTK("layer7: matched %s\n", info->protocol); ++		pattern_result = 1; ++	} else pattern_result = 0; ++ ++	if(pattern_result == 1) { ++		master_conntrack->layer7.app_proto =  ++			kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); ++		if(!master_conntrack->layer7.app_proto){ ++			if (net_ratelimit()) ++				printk(KERN_ERR "layer7: out of memory in " ++						"match, bailing.\n"); ++			spin_unlock_bh(&l7_lock); ++			return (pattern_result ^ info->invert); ++		} ++		strcpy(master_conntrack->layer7.app_proto, info->protocol); ++	} else if(pattern_result > 1) { /* cleanup from "unset" */ ++		pattern_result = 1; ++	} ++ ++	/* mark the packet seen */ ++	skb->cb[0] = 1; ++ ++	spin_unlock_bh(&l7_lock); ++	return (pattern_result ^ info->invert); ++} ++ ++static int check(const char *tablename, ++		 const void *inf, ++		 const struct xt_match *match, ++		 void *matchinfo, ++		 unsigned int hook_mask) ++ ++{ ++	// load nf_conntrack_ipv4 ++        if (nf_ct_l3proto_try_module_get(match->family) < 0) { ++                printk(KERN_WARNING "can't load conntrack support for " ++                                    "proto=%d\n", match->family); ++                return 0; ++        } ++	return 1; ++} ++ ++static void ++destroy(const struct xt_match *match, void *matchinfo) ++{ ++	nf_ct_l3proto_module_put(match->family); ++} ++ ++static struct xt_match xt_layer7_match[] = { ++{ ++	.name		= "layer7", ++	.family		= AF_INET, ++	.checkentry	= check, ++	.match		= match, ++	.destroy	= destroy, ++	.matchsize	= sizeof(struct xt_layer7_info), ++	.me		= THIS_MODULE ++} ++}; ++ ++static void layer7_cleanup_proc(void) ++{ ++	remove_proc_entry("layer7_numpackets", proc_net); ++} ++ ++/* register the proc file */ ++static void layer7_init_proc(void) ++{ ++	struct proc_dir_entry* entry; ++	entry = create_proc_entry("layer7_numpackets", 0644, proc_net); ++	entry->read_proc = layer7_read_proc; ++	entry->write_proc = layer7_write_proc; ++} ++ ++static int __init xt_layer7_init(void) ++{ ++	need_conntrack(); ++ ++	layer7_init_proc(); ++	if(maxdatalen < 1) { ++		printk(KERN_WARNING "layer7: maxdatalen can't be < 1, " ++			"using 1\n"); ++		maxdatalen = 1; ++	} ++	/* This is not a hard limit.  It's just here to prevent people from ++	bringing their slow machines to a grinding halt. */ ++	else if(maxdatalen > 65536) { ++		printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, " ++			"using 65536\n"); ++		maxdatalen = 65536; ++	} ++	return xt_register_matches(xt_layer7_match, ++				   ARRAY_SIZE(xt_layer7_match)); ++} ++ ++static void __exit xt_layer7_fini(void) ++{ ++	layer7_cleanup_proc(); ++	xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match)); ++} ++ ++module_init(xt_layer7_init); ++module_exit(xt_layer7_fini); ++ diff --git a/target/linux/generic-2.6/patches-2.6.23/101-netfilter_layer7_pktmatch.patch b/target/linux/generic-2.6/patches-2.6.23/101-netfilter_layer7_pktmatch.patch deleted file mode 100644 index 8e8395cb5..000000000 --- a/target/linux/generic-2.6/patches-2.6.23/101-netfilter_layer7_pktmatch.patch +++ /dev/null @@ -1,109 +0,0 @@ -Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_layer7.h -=================================================================== ---- linux-2.6.23-rc6.orig/include/linux/netfilter_ipv4/ipt_layer7.h	2007-09-21 16:23:59.000000000 +0800 -+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_layer7.h	2007-09-21 16:24:00.000000000 +0800 -@@ -21,6 +21,7 @@ -     char protocol[MAX_PROTOCOL_LEN]; -     char invert:1; -     char pattern[MAX_PATTERN_LEN]; -+    char pkt; - }; -  - #endif /* _IPT_LAYER7_H */ -Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_layer7.c -=================================================================== ---- linux-2.6.23-rc6.orig/net/ipv4/netfilter/ipt_layer7.c	2007-09-21 16:23:59.000000000 +0800 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/ipt_layer7.c	2007-09-21 16:24:00.000000000 +0800 -@@ -300,33 +300,34 @@ - } -  - /* add the new app data to the conntrack.  Return number of bytes added. */ --static int add_data(struct nf_conn * master_conntrack, --			char * app_data, int appdatalen) -+static int add_datastr(char *target, int offset, char *app_data, int len) - { - 	int length = 0, i; --	int oldlength = master_conntrack->layer7.app_data_len; -- --	// This is a fix for a race condition by Deti Fliegl. However, I'm not --	// clear on whether the race condition exists or whether this really --	// fixes it.  I might just be being dense... Anyway, if it's not really --	// a fix, all it does is waste a very small amount of time. --	if(!master_conntrack->layer7.app_data) return 0; -+	if(!target) return 0; -  - 	/* Strip nulls. Make everything lower case (our regex lib doesn't - 	do case insensitivity).  Add it to the end of the current data. */ --	for(i = 0; i < maxdatalen-oldlength-1 && --		   i < appdatalen; i++) { -+	for(i = 0; i < maxdatalen-offset-1 && i < len; i++) { - 		if(app_data[i] != '\0') { --			master_conntrack->layer7.app_data[length+oldlength] = -+			target[length+offset] = - 				/* the kernel version of tolower mungs 'upper ascii' */ - 				isascii(app_data[i])? tolower(app_data[i]) : app_data[i]; - 			length++; - 		} - 	} -+	target[length+offset] = '\0'; -+ -+	return length; -+} -  --	master_conntrack->layer7.app_data[length+oldlength] = '\0'; --	master_conntrack->layer7.app_data_len = length + oldlength; -+/* add the new app data to the conntrack.  Return number of bytes added. */ -+static int add_data(struct nf_conn * master_conntrack, -+			char * app_data, int appdatalen) -+{ -+	int length; -  -+	length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen); -+	master_conntrack->layer7.app_data_len += length; - 	return length; - } -  -@@ -343,7 +344,7 @@ - 	enum ip_conntrack_info master_ctinfo, ctinfo; - 	struct nf_conn *master_conntrack; - 	struct nf_conn *conntrack; --	unsigned char * app_data; -+	unsigned char *app_data, *tmp_data; - 	unsigned int pattern_result, appdatalen; - 	regexp * comppattern; -  -@@ -365,8 +366,8 @@ - 		master_conntrack = master_ct(master_conntrack); -  - 	/* if we've classified it or seen too many packets */ --	if(TOTAL_PACKETS > num_packets || --	   master_conntrack->layer7.app_proto) { -+	if(!info->pkt && (TOTAL_PACKETS > num_packets || -+		master_conntrack->layer7.app_proto)) { -  - 		pattern_result = match_no_append(conntrack, master_conntrack, ctinfo, master_ctinfo, info); -  -@@ -396,6 +397,23 @@ - 	comppattern = compile_and_cache(info->pattern, info->protocol); - 	spin_unlock_bh(&list_lock); -  -+	if (info->pkt) { -+		tmp_data = kmalloc(maxdatalen, GFP_ATOMIC); -+		if(!tmp_data){ -+			if (net_ratelimit()) -+				printk(KERN_ERR "layer7: out of memory in match, bailing.\n"); -+			return info->invert; -+		} -+ -+		tmp_data[0] = '\0'; -+		add_datastr(tmp_data, 0, app_data, appdatalen); -+		pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0); -+		kfree(tmp_data); -+		tmp_data = NULL; -+ -+		return (pattern_result ^ info->invert); -+	} -+ - 	/* On the first packet of a connection, allocate space for app data */ - 	write_lock(&ct_lock); - 	if(TOTAL_PACKETS == 1 && !skb->cb[0] && !master_conntrack->layer7.app_data) { diff --git a/target/linux/generic-2.6/patches-2.6.23/110-ipp2p_0.8.1rc1.patch b/target/linux/generic-2.6/patches-2.6.23/110-ipp2p_0.8.1rc1.patch index dfccbe048..b86d49481 100644 --- a/target/linux/generic-2.6/patches-2.6.23/110-ipp2p_0.8.1rc1.patch +++ b/target/linux/generic-2.6/patches-2.6.23/110-ipp2p_0.8.1rc1.patch @@ -1,7 +1,7 @@ -Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_ipp2p.h +Index: linux-2.6.23.1/include/linux/netfilter_ipv4/ipt_ipp2p.h  ===================================================================  --- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_ipp2p.h	2007-09-21 16:24:00.000000000 +0800 ++++ linux-2.6.23.1/include/linux/netfilter_ipv4/ipt_ipp2p.h	2007-11-19 18:22:19.000000000 -0600  @@ -0,0 +1,31 @@  +#ifndef __IPT_IPP2P_H  +#define __IPT_IPP2P_H @@ -34,10 +34,10 @@ Index: linux-2.6.23-rc6/include/linux/netfilter_ipv4/ipt_ipp2p.h  +#define IPP2P_MUTE		(1 << 14)  +#define IPP2P_WASTE		(1 << 15)  +#define IPP2P_XDCC		(1 << 16) -Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_ipp2p.c +Index: linux-2.6.23.1/net/ipv4/netfilter/ipt_ipp2p.c  ===================================================================  --- /dev/null	1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/ipt_ipp2p.c	2007-09-21 16:24:00.000000000 +0800 ++++ linux-2.6.23.1/net/ipv4/netfilter/ipt_ipp2p.c	2007-11-19 18:22:19.000000000 -0600  @@ -0,0 +1,856 @@  +#if defined(MODVERSIONS)  +#include <linux/modversions.h> @@ -895,13 +895,13 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/ipt_ipp2p.c  +module_exit(fini);  +  + -Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig +Index: linux-2.6.23.1/net/ipv4/netfilter/Kconfig  =================================================================== ---- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Kconfig	2007-09-21 16:23:59.000000000 +0800 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig	2007-09-21 16:24:00.000000000 +0800 -@@ -81,6 +81,12 @@ - 	help - 	  Say Y to get lots of debugging output. +--- linux-2.6.23.1.orig/net/ipv4/netfilter/Kconfig	2007-11-19 18:21:55.000000000 -0600 ++++ linux-2.6.23.1/net/ipv4/netfilter/Kconfig	2007-11-19 18:22:19.000000000 -0600 +@@ -63,6 +63,12 @@ +  + 	  To compile it as a module, choose M here.  If unsure, say N.  +config IP_NF_MATCH_IPP2P  +	tristate "IPP2P" @@ -912,16 +912,16 @@ Index: linux-2.6.23-rc6/net/ipv4/netfilter/Kconfig   config IP_NF_MATCH_TOS   	tristate "TOS match support"   	depends on IP_NF_IPTABLES -Index: linux-2.6.23-rc6/net/ipv4/netfilter/Makefile +Index: linux-2.6.23.1/net/ipv4/netfilter/Makefile  =================================================================== ---- linux-2.6.23-rc6.orig/net/ipv4/netfilter/Makefile	2007-09-21 16:23:59.000000000 +0800 -+++ linux-2.6.23-rc6/net/ipv4/netfilter/Makefile	2007-09-21 16:24:00.000000000 +0800 -@@ -49,7 +49,7 @@ - obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o +--- linux-2.6.23.1.orig/net/ipv4/netfilter/Makefile	2007-11-19 18:21:55.000000000 -0600 ++++ linux-2.6.23.1/net/ipv4/netfilter/Makefile	2007-11-19 18:23:45.000000000 -0600 +@@ -50,6 +50,8 @@   obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o   obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o -- -+obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o - obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o ++obj-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p.o ++   # targets + obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o + obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o  | 
