diff options
| author | wbx <wbx@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2005-12-16 13:38:40 +0000 | 
|---|---|---|
| committer | wbx <wbx@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2005-12-16 13:38:40 +0000 | 
| commit | a8b38a53a783ad0c61090b5451970bb5cfe1d010 (patch) | |
| tree | 3be9110bb269051108bcbd357c732ca70ad1c051 | |
| parent | 5a4c6e5f7dce21683aa0fff2e6a06da49e976b00 (diff) | |
fix one of the iptables 1.3.4 compile errors on 2.4, backport of ipt_string from 2.6, need runtime testing
git-svn-id: svn://svn.openwrt.org/openwrt/trunk/openwrt@2699 3c298f89-4303-0410-b956-a3cf2f4a3e73
| -rw-r--r-- | target/linux/linux-2.4/patches/generic/609-netfilter_string.patch | 529 | 
1 files changed, 306 insertions, 223 deletions
| diff --git a/target/linux/linux-2.4/patches/generic/609-netfilter_string.patch b/target/linux/linux-2.4/patches/generic/609-netfilter_string.patch index 18f9f97be..c8e1a2d2d 100644 --- a/target/linux/linux-2.4/patches/generic/609-netfilter_string.patch +++ b/target/linux/linux-2.4/patches/generic/609-netfilter_string.patch @@ -1,265 +1,348 @@ ---- 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 @@ +diff -Nur linux-2.4.32/include/linux/netfilter_ipv4/ipt_string.h linux-2.4.32.patch/include/linux/netfilter_ipv4/ipt_string.h +--- linux-2.4.32/include/linux/netfilter_ipv4/ipt_string.h	1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.4.32.patch/include/linux/netfilter_ipv4/ipt_string.h	2005-12-16 00:40:19.082509250 +0100 +@@ -0,0 +1,18 @@ ++#ifndef _IPT_STRING_H ++#define _IPT_STRING_H ++ ++#define IPT_STRING_MAX_PATTERN_SIZE 128 ++#define IPT_STRING_MAX_ALGO_NAME_SIZE 16 ++ ++struct ipt_string_info ++{ ++	u_int16_t from_offset; ++	u_int16_t to_offset; ++	char	  algo[IPT_STRING_MAX_ALGO_NAME_SIZE]; ++	char 	  pattern[IPT_STRING_MAX_PATTERN_SIZE]; ++	u_int8_t  patlen; ++	u_int8_t  invert; ++	struct ts_config __attribute__((aligned(8))) *config; ++}; ++ ++#endif /*_IPT_STRING_H*/ +diff -Nur linux-2.4.32/include/linux/textsearch.h linux-2.4.32.patch/include/linux/textsearch.h +--- linux-2.4.32/include/linux/textsearch.h	1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.4.32.patch/include/linux/textsearch.h	2005-12-16 11:15:34.838073000 +0100 +@@ -0,0 +1,205 @@ ++#ifndef __LINUX_TEXTSEARCH_H ++#define __LINUX_TEXTSEARCH_H ++ ++#ifdef __KERNEL__ ++ ++#include <linux/types.h> ++#include <linux/list.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++ ++#ifdef __CHECKER__ ++#define __bitwise__ __attribute__((bitwise)) ++#else ++#define __bitwise__ ++#endif ++#ifdef __CHECK_ENDIAN__ ++#define __bitwise __bitwise__ ++#else ++#define __bitwise ++#endif ++ ++typedef __u16 __bitwise __le16; ++typedef __u16 __bitwise __be16; ++typedef __u32 __bitwise __le32; ++typedef __u32 __bitwise __be32; ++#if defined(__GNUC__) && !defined(__STRICT_ANSI__) ++typedef __u64 __bitwise __le64; ++typedef __u64 __bitwise __be64; ++#endif ++ ++#ifdef __KERNEL__ ++typedef unsigned __bitwise__ gfp_t; ++#endif ++ ++struct ts_config; ++ ++/** ++ * TS_AUTOLOAD - Automatically load textsearch modules when needed ++ */ ++#define TS_AUTOLOAD	1 ++ ++/** ++ * struct ts_state - search state ++ * @offset: offset for next match ++ * @cb: control buffer, for persistant variables of get_next_block() ++ */ ++struct ts_state ++{ ++	unsigned int		offset; ++	char			cb[40]; ++}; ++ ++/** ++ * struct ts_ops - search module operations ++ * @name: name of search algorithm ++ * @init: initialization function to prepare a search ++ * @find: find the next occurrence of the pattern ++ * @destroy: destroy algorithm specific parts of a search configuration ++ * @get_pattern: return head of pattern ++ * @get_pattern_len: return length of pattern ++ * @owner: module reference to algorithm ++ */ ++struct ts_ops ++{ ++	const char		*name; ++	struct ts_config *	(*init)(const void *, unsigned int, gfp_t); ++	unsigned int		(*find)(struct ts_config *, ++					struct ts_state *); ++	void			(*destroy)(struct ts_config *); ++	void *			(*get_pattern)(struct ts_config *); ++	unsigned int		(*get_pattern_len)(struct ts_config *); ++	struct module		*owner; ++	struct list_head	list; ++}; ++ ++/** ++ * struct ts_config - search configuration ++ * @ops: operations of chosen algorithm ++ * @get_next_block: callback to fetch the next block to search in ++ * @finish: callback to finalize a search ++ */ ++struct ts_config ++{ ++	struct ts_ops		*ops; ++ ++	/** ++	 * get_next_block - fetch next block of data ++	 * @consumed: number of bytes consumed by the caller ++	 * @dst: destination buffer ++	 * @conf: search configuration ++	 * @state: search state ++	 * ++	 * Called repeatedly until 0 is returned. Must assign the ++	 * head of the next block of data to &*dst and return the length ++	 * of the block or 0 if at the end. consumed == 0 indicates ++	 * a new search. May store/read persistant values in state->cb. ++	 */ ++	unsigned int		(*get_next_block)(unsigned int consumed, ++						  const u8 **dst, ++						  struct ts_config *conf, ++						  struct ts_state *state); ++ ++	/** ++	 * finish - finalize/clean a series of get_next_block() calls ++	 * @conf: search configuration ++	 * @state: search state ++	 * ++	 * Called after the last use of get_next_block(), may be used ++	 * to cleanup any leftovers. ++	 */ ++	void			(*finish)(struct ts_config *conf, ++					  struct ts_state *state); ++}; ++ ++/** ++ * textsearch_next - continue searching for a pattern ++ * @conf: search configuration ++ * @state: search state ++ * ++ * Continues a search looking for more occurrences of the pattern. ++ * textsearch_find() must be called to find the first occurrence ++ * in order to reset the state. ++ * ++ * Returns the position of the next occurrence of the pattern or ++ * UINT_MAX if not match was found. ++ */  ++static inline unsigned int textsearch_next(struct ts_config *conf, ++					   struct ts_state *state) ++{ ++	unsigned int ret = conf->ops->find(conf, state); ++ ++	if (conf->finish) ++		conf->finish(conf, state); ++ ++	return ret; ++} ++ ++/** ++ * textsearch_find - start searching for a pattern ++ * @conf: search configuration ++ * @state: search state ++ * ++ * Returns the position of first occurrence of the pattern or ++ * UINT_MAX if no match was found. ++ */  ++static inline unsigned int textsearch_find(struct ts_config *conf, ++					   struct ts_state *state) ++{ ++	state->offset = 0; ++	return textsearch_next(conf, state); ++} ++ ++/** ++ * textsearch_get_pattern - return head of the pattern ++ * @conf: search configuration ++ */ ++static inline void *textsearch_get_pattern(struct ts_config *conf) ++{ ++	return conf->ops->get_pattern(conf); ++} ++ ++/** ++ * textsearch_get_pattern_len - return length of the pattern ++ * @conf: search configuration ++ */ ++static inline unsigned int textsearch_get_pattern_len(struct ts_config *conf) ++{ ++	return conf->ops->get_pattern_len(conf); ++} ++ ++extern int textsearch_register(struct ts_ops *); ++extern int textsearch_unregister(struct ts_ops *); ++extern struct ts_config *textsearch_prepare(const char *, const void *, ++					    unsigned int, gfp_t, int); ++extern void textsearch_destroy(struct ts_config *conf); ++extern unsigned int textsearch_find_continuous(struct ts_config *, ++					       struct ts_state *, ++					       const void *, unsigned int); ++ ++ ++#define TS_PRIV_ALIGNTO	8 ++#define TS_PRIV_ALIGN(len) (((len) + TS_PRIV_ALIGNTO-1) & ~(TS_PRIV_ALIGNTO-1)) ++ ++static inline struct ts_config *alloc_ts_config(size_t payload, ++						gfp_t gfp_mask) ++{ ++	struct ts_config *conf; ++ ++	conf = kmalloc(TS_PRIV_ALIGN(sizeof(*conf)) + payload, gfp_mask); ++	if (conf == NULL) ++		return -ENOMEM; ++ ++	memset(conf, 0, TS_PRIV_ALIGN(sizeof(*conf)) + payload); ++	return conf; ++} ++ ++static inline void *ts_config_priv(struct ts_config *conf) ++{ ++	return ((u8 *) conf + TS_PRIV_ALIGN(sizeof(struct ts_config))); ++} ++ ++#endif /* __KERNEL__ */ ++ ++#endif +diff -Nur linux-2.4.32/net/ipv4/netfilter/Config.in linux-2.4.32.patch/net/ipv4/netfilter/Config.in +--- linux-2.4.32/net/ipv4/netfilter/Config.in	2005-01-19 15:10:13.000000000 +0100 ++++ linux-2.4.32.patch/net/ipv4/netfilter/Config.in	2005-12-16 00:41:43.023755250 +0100 +@@ -42,6 +42,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> +   fi + # The targets +diff -Nur linux-2.4.32/net/ipv4/netfilter/ipt_string.c linux-2.4.32.patch/net/ipv4/netfilter/ipt_string.c +--- linux-2.4.32/net/ipv4/netfilter/ipt_string.c	1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.4.32.patch/net/ipv4/netfilter/ipt_string.c	2005-12-16 00:40:48.436343750 +0100 +@@ -0,0 +1,91 @@ ++/* String matching match for iptables  + *  -+ * 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. ++ * (C) 2005 Pablo Neira Ayuso <pablo@eurodev.net> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation.  + */  + -+#include <linux/smp.h> ++#include <linux/init.h>  +#include <linux/module.h> ++#include <linux/kernel.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> ++#include <linux/textsearch.h>  + ++MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); ++MODULE_DESCRIPTION("IP tables string match module");  +MODULE_LICENSE("GPL");  + -+struct string_per_cpu { -+	int *skip; -+	int *shift; -+	int *len; -+}; ++static int match(const struct sk_buff *skb, ++		 const struct net_device *in, ++		 const struct net_device *out, ++		 const void *matchinfo, ++		 int offset, ++		 int *hotdrop) ++{ ++	struct ts_state state; ++	struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo;  + -+struct string_per_cpu *bm_string_data=NULL; ++	memset(&state, 0, sizeof(struct ts_state));  + -+/* 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; ++	return (skb_find_text((struct sk_buff *)skb, conf->from_offset,  ++			     conf->to_offset, conf->config, &state)  ++			     != UINT_MAX) && !conf->invert;  +}  + ++#define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m)  + -+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 int checkentry(const char *tablename, ++		      const struct ipt_ip *ip, ++		      void *matchinfo, ++		      unsigned int matchsize, ++		      unsigned int hook_mask)  +{ -+	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); -+} ++	struct ipt_string_info *conf = matchinfo; ++	struct ts_config *ts_conf;  + -+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; ++ ++	/* Damn, can't handle this case properly with iptables... */ ++	if (conf->from_offset > conf->to_offset) ++		return 0; ++ ++	ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, ++				     GFP_KERNEL, TS_AUTOLOAD); ++	if (IS_ERR(ts_conf)) ++		return 0;  + -+       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info))) -+               return 0; ++	conf->config = ts_conf;  + -+       return 1; ++	return 1;  +}  + -+void string_freeup_data(void) ++static void destroy(void *matchinfo, unsigned int matchsize)  +{ -+	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); -+	} ++	textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);  +}  + -+static struct ipt_match string_match -+= { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE }; ++static struct ipt_match string_match = { ++	.name 		= "string", ++	.match 		= match, ++	.checkentry	= checkentry, ++	.destroy 	= destroy, ++	.me 		= 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 -Nur linux-2.4.32/net/ipv4/netfilter/Makefile linux-2.4.32.patch/net/ipv4/netfilter/Makefile +--- linux-2.4.32/net/ipv4/netfilter/Makefile	2003-08-25 13:44:44.000000000 +0200 ++++ linux-2.4.32.patch/net/ipv4/netfilter/Makefile	2005-12-16 00:42:10.929499250 +0100 +@@ -85,6 +85,7 @@ + obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.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 +  + # targets | 
