1 --- linux/net/ipv4/netfilter/Config.in.org 2005-11-08 23:11:47.011929664 +0100
2 +++ linux/net/ipv4/netfilter/Config.in 2005-11-08 23:10:33.329131152 +0100
5 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
6 dep_tristate ' Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES
7 + dep_tristate ' String match support (EXPERIMENTAL) ' CONFIG_IP_NF_MATCH_STRING $CONFIG_IP_NF_IPTABLES
8 dep_tristate ' Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES
9 dep_tristate ' Layer 7 match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7 $CONFIG_IP_NF_CONNTRACK
10 dep_mbool ' Layer 7 debugging output (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_LAYER7_DEBUG $CONFIG_IP_NF_MATCH_LAYER7
11 --- linux/net/ipv4/netfilter/Makefile.org 2005-11-08 23:11:57.214378656 +0100
12 +++ linux/net/ipv4/netfilter/Makefile 2005-11-08 23:11:20.980886984 +0100
14 obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
15 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
16 obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
17 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
18 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
20 obj-$(CONFIG_IP_NF_MATCH_LAYER7) += ipt_layer7.o
21 --- linux/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
22 +++ linux/net/ipv4/netfilter/ipt_string.c 2005-11-08 23:08:51.531606728 +0100
24 +/* Kernel module to match a string into a packet.
26 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
29 + * 19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
30 + * Fixed SMP re-entrancy problem using per-cpu data areas
31 + * for the skip/shift tables.
32 + * 02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
33 + * Fixed kernel panic, due to overrunning boyer moore string
34 + * tables. Also slightly tweaked heuristic for deciding what
35 + * search algo to use.
36 + * 27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
37 + * Implemented Boyer Moore Sublinear search algorithm
38 + * alongside the existing linear search based on memcmp().
39 + * Also a quick check to decide which method to use on a per
43 +#include <linux/smp.h>
44 +#include <linux/module.h>
45 +#include <linux/skbuff.h>
46 +#include <linux/file.h>
47 +#include <net/sock.h>
49 +#include <linux/netfilter_ipv4/ip_tables.h>
50 +#include <linux/netfilter_ipv4/ipt_string.h>
52 +MODULE_LICENSE("GPL");
54 +struct string_per_cpu {
60 +struct string_per_cpu *bm_string_data=NULL;
62 +/* Boyer Moore Sublinear string search - VERY FAST */
63 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
65 + int M1, right_end, sk, sh;
68 + int *skip, *shift, *len;
70 + /* use data suitable for this CPU */
71 + shift=bm_string_data[smp_processor_id()].shift;
72 + skip=bm_string_data[smp_processor_id()].skip;
73 + len=bm_string_data[smp_processor_id()].len;
75 + /* Setup skip/shift tables */
76 + M1 = right_end = needle_len-1;
77 + for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;
78 + for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;
80 + for (i = 1; i < needle_len; i++) {
81 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
86 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
87 + for (i = M1; i > 0; i--) shift[len[i]] = i;
90 + for (i = 0; i < needle_len; i++) {
91 + if (len[i] == M1 - i) ended = i;
92 + if (ended) shift[i] = ended;
96 + while (right_end < haystack_len)
98 + for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);
99 + if (i == needle_len) {
100 + return haystack+(right_end - M1);
103 + sk = skip[haystack[right_end - i]];
105 + right_end = max(right_end - i + sk, right_end + sh);
111 +/* Linear string search based on memcmp() */
112 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
114 + char *k = haystack + (haystack_len-needle_len);
115 + char *t = haystack;
118 + if (memcmp(t, needle, needle_len) == 0)
128 +match(const struct sk_buff *skb,
129 + const struct net_device *in,
130 + const struct net_device *out,
131 + const void *matchinfo,
137 + const struct ipt_string_info *info = matchinfo;
138 + struct iphdr *ip = skb->nh.iph;
140 + char *needle, *haystack;
141 + proc_ipt_search search=search_linear;
143 + if ( !ip ) return 0;
145 + /* get lenghts, and validate them */
147 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
148 + if ( nlen > hlen ) return 0;
150 + needle=(char *)&info->string;
151 + haystack=(char *)ip+(ip->ihl*4);
153 + /* The sublinear search comes in to its own
154 + * on the larger packets */
155 + if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
156 + (nlen>IPT_STRING_NEEDLE_THRESH) ) {
157 + if ( hlen < BM_MAX_HLEN ) {
158 + search=search_sublinear;
160 + if (net_ratelimit())
161 + printk(KERN_INFO "ipt_string: Packet too big "
162 + "to attempt sublinear string search "
163 + "(%d bytes)\n", hlen );
167 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
171 +checkentry(const char *tablename,
172 + const struct ipt_ip *ip,
174 + unsigned int matchsize,
175 + unsigned int hook_mask)
178 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
184 +void string_freeup_data(void)
188 + if ( bm_string_data ) {
189 + for(c=0; c<smp_num_cpus; c++) {
190 + if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
191 + if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
192 + if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
194 + kfree(bm_string_data);
198 +static struct ipt_match string_match
199 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
201 +static int __init init(void)
207 + tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
208 + alen=sizeof(int)*BM_MAX_HLEN;
210 + /* allocate array of structures */
211 + if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
215 + memset(bm_string_data, 0, tlen);
217 + /* allocate our skip/shift tables */
218 + for(c=0; c<smp_num_cpus; c++) {
219 + if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
221 + if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
223 + if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
227 + return ipt_register_match(&string_match);
230 + string_freeup_data();
234 +static void __exit fini(void)
236 + ipt_unregister_match(&string_match);
237 + string_freeup_data();
242 --- linux/include/linux/netfilter_ipv4/ipt_string.h 1970-01-01 01:00:00.000000000 +0100
243 +++ linux/include/linux/netfilter_ipv4/ipt_string.h 2005-11-08 23:09:45.219444936 +0100
245 +#ifndef _IPT_STRING_H
246 +#define _IPT_STRING_H
248 +/* *** PERFORMANCE TWEAK ***
249 + * Packet size and search string threshold,
250 + * above which sublinear searches is used. */
251 +#define IPT_STRING_HAYSTACK_THRESH 100
252 +#define IPT_STRING_NEEDLE_THRESH 20
254 +#define BM_MAX_NLEN 256
255 +#define BM_MAX_HLEN 1024
257 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
259 +struct ipt_string_info {
260 + char string[BM_MAX_NLEN];
265 +#endif /* _IPT_STRING_H */