Messages in this thread Patch in this message |  | | From | Kim Yong Il <> | Subject | 2.4.9-ipt_string.patch | Date | Thu, 20 Sep 2001 09:52:01 +0900 |
| |
This is "iptables --string" patch
diff -urN linux-2.4.9.orig/Documentation/Configure.help linux-2.4.9/Documentation/Configure.help --- linux-2.4.9.orig/Documentation/Configure.help Mon Aug 13 02:51:41 2001 +++ linux-2.4.9/Documentation/Configure.help Fri Aug 17 12:28:25 2001 @@ -1939,6 +1939,14 @@ If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. +String match support (EXPERIMENTAL) +CONFIG_IP_NF_MATCH_STRING + String matching alows you to match packets which contain a + specified string of characters. + + If you want to compile it as a module, say M here and read + Documentation/modules.txt. If unsure, say `N'. + Unclean match support (EXPERIMENTAL) CONFIG_IP_NF_MATCH_UNCLEAN Unclean packet matching matches any strange or invalid packets, by diff -urN linux-2.4.9.orig/include/linux/netfilter_ipv4/ipt_string.h linux-2.4.9/include/linux/netfilter_ipv4/ipt_string.h --- linux-2.4.9.orig/include/linux/netfilter_ipv4/ipt_string.h Thu Jan 1 09:00:00 1970 +++ linux-2.4.9/include/linux/netfilter_ipv4/ipt_string.h Sat Aug 11 13:18:32 2001 @@ -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 -urN linux-2.4.9.orig/net/ipv4/netfilter/Config.in linux-2.4.9/net/ipv4/netfilter/Config.in --- linux-2.4.9.orig/net/ipv4/netfilter/Config.in Wed Mar 7 15:44:16 2001 +++ linux-2.4.9/net/ipv4/netfilter/Config.in Fri Aug 17 12:29:11 2001 @@ -26,6 +26,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 fi # The targets diff -urN linux-2.4.9.orig/net/ipv4/netfilter/Makefile linux-2.4.9/net/ipv4/netfilter/Makefile --- linux-2.4.9.orig/net/ipv4/netfilter/Makefile Thu Apr 26 07:00:28 2001 +++ linux-2.4.9/net/ipv4/netfilter/Makefile Fri Aug 17 12:28:53 2001 @@ -54,6 +54,7 @@ obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.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 diff -urN linux-2.4.9.orig/net/ipv4/netfilter/ipt_string.c linux-2.4.9/net/ipv4/netfilter/ipt_string.c --- linux-2.4.9.orig/net/ipv4/netfilter/ipt_string.c Thu Jan 1 09:00:00 1970 +++ linux-2.4.9/net/ipv4/netfilter/ipt_string.c Sat Aug 11 13:18:32 2001 @@ -0,0 +1,156 @@ +/* Kernel module to match a string into a packet. + * + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be> + * + * ChangeLog + * 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/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> + +int skip[BM_MAX_HLEN]; +int shift[BM_MAX_HLEN]; + +/* 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, len[BM_MAX_HLEN]; + int i; + + /* 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(int, 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; + } + + 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; +} + +static struct ipt_match string_match += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE }; + +static int __init init(void) +{ + return ipt_register_match(&string_match); +} + +static void __exit fini(void) +{ + ipt_unregister_match(&string_match); +} + +module_init(init); +module_exit(fini); |  |