]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-layer7.patch
This commit was manufactured by cvs2git to create branch 'LINUX_2_6_22'.
[packages/kernel.git] / kernel-layer7.patch
CommitLineData
7f651772 1--- linux-2.6.22-rc7/net/netfilter/Kconfig 2007-07-01 14:54:24.000000000 -0500
2+++ linux-2.6.22-rc7-layer7/net/netfilter/Kconfig 2007-07-03 03:21:32.000000000 -0500
3@@ -603,6 +603,26 @@ config NETFILTER_XT_MATCH_STATE
4
5 To compile it as a module, choose M here. If unsure, say N.
6
7+config NETFILTER_XT_MATCH_LAYER7
8+ tristate '"layer7" match support'
9+ depends on NETFILTER_XTABLES
10+ depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK)
11+ help
12+ Say Y if you want to be able to classify connections (and their
13+ packets) based on regular expression matching of their application
14+ layer data. This is one way to classify applications such as
15+ peer-to-peer filesharing systems that do not always use the same
16+ port.
17+
18+ To compile it as a module, choose M here. If unsure, say N.
19+
20+config NETFILTER_XT_MATCH_LAYER7_DEBUG
21+ bool 'Layer 7 debugging output'
22+ depends on NETFILTER_XT_MATCH_LAYER7
23+ help
24+ Say Y to get lots of debugging output.
25+
26+
27 config NETFILTER_XT_MATCH_STATISTIC
28 tristate '"statistic" match support'
29 depends on NETFILTER_XTABLES
30--- linux-2.6.22-rc7/net/netfilter/Makefile 2007-07-01 14:54:24.000000000 -0500
31+++ linux-2.6.22-rc7-layer7/net/netfilter/Makefile 2007-07-03 01:32:35.000000000 -0500
32@@ -0,0 +0,1 @@
33+obj-$(CONFIG_NETFILTER_XT_MATCH_LAYER7) += xt_layer7.o
34--- linux-2.6.22-rc7/net/netfilter/xt_layer7.c 1969-12-31 18:00:00.000000000 -0600
35+++ linux-2.6.22-rc7-layer7/net/netfilter/xt_layer7.c 2007-07-03 07:57:38.000000000 -0500
36@@ -0,0 +1,626 @@
37+/*
38+ Kernel module to match application layer (OSI layer 7) data in connections.
39+
40+ http://l7-filter.sf.net
41+
42+ (C) 2003, 2004, 2005, 2006, 2007 Matthew Strait and Ethan Sommer.
43+
44+ This program is free software; you can redistribute it and/or
45+ modify it under the terms of the GNU General Public License
46+ as published by the Free Software Foundation; either version
47+ 2 of the License, or (at your option) any later version.
48+ http://www.gnu.org/licenses/gpl.txt
49+
50+ Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>,
51+ xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait,
52+ Ethan Sommer, Justin Levandoski.
53+*/
54+
55+#include <linux/spinlock.h>
56+#include <net/ip.h>
57+#include <net/tcp.h>
58+#include <linux/module.h>
59+#include <linux/skbuff.h>
60+#include <linux/netfilter.h>
61+#include <net/netfilter/nf_conntrack.h>
62+#include <net/netfilter/nf_conntrack_core.h>
63+#include <linux/netfilter/x_tables.h>
64+#include <linux/netfilter/xt_layer7.h>
65+#include <linux/ctype.h>
66+#include <linux/proc_fs.h>
67+
68+#include "regexp/regexp.c"
69+
70+MODULE_LICENSE("GPL");
71+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
72+MODULE_DESCRIPTION("iptables application layer match module");
73+MODULE_ALIAS("ipt_layer7");
74+MODULE_VERSION("2.0");
75+
76+static int maxdatalen = 2048; // this is the default
77+module_param(maxdatalen, int, 0444);
78+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter");
79+#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG
80+ #define DPRINTK(format,args...) printk(format,##args)
81+#else
82+ #define DPRINTK(format,args...)
83+#endif
84+
85+#define TOTAL_PACKETS master_conntrack->counters[IP_CT_DIR_ORIGINAL].packets + \
86+ master_conntrack->counters[IP_CT_DIR_REPLY].packets
87+
88+/* Number of packets whose data we look at.
89+This can be modified through /proc/net/layer7_numpackets */
90+static int num_packets = 10;
91+
92+static struct pattern_cache {
93+ char * regex_string;
94+ regexp * pattern;
95+ struct pattern_cache * next;
96+} * first_pattern_cache = NULL;
97+
98+DEFINE_SPINLOCK(l7_lock);
99+
100+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
101+/* Converts an unfriendly string into a friendly one by
102+replacing unprintables with periods and all whitespace with " ". */
103+static char * friendly_print(unsigned char * s)
104+{
105+ char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
106+ int i;
107+
108+ if(!f) {
109+ if (net_ratelimit())
110+ printk(KERN_ERR "layer7: out of memory in "
111+ "friendly_print, bailing.\n");
112+ return NULL;
113+ }
114+
115+ for(i = 0; i < strlen(s); i++){
116+ if(isprint(s[i]) && s[i] < 128) f[i] = s[i];
117+ else if(isspace(s[i])) f[i] = ' ';
118+ else f[i] = '.';
119+ }
120+ f[i] = '\0';
121+ return f;
122+}
123+
124+static char dec2hex(int i)
125+{
126+ switch (i) {
127+ case 0 ... 9:
128+ return (i + '0');
129+ break;
130+ case 10 ... 15:
131+ return (i - 10 + 'a');
132+ break;
133+ default:
134+ if (net_ratelimit())
135+ printk("layer7: Problem in dec2hex\n");
136+ return '\0';
137+ }
138+}
139+
140+static char * hex_print(unsigned char * s)
141+{
142+ char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
143+ int i;
144+
145+ if(!g) {
146+ if (net_ratelimit())
147+ printk(KERN_ERR "layer7: out of memory in hex_print, "
148+ "bailing.\n");
149+ return NULL;
150+ }
151+
152+ for(i = 0; i < strlen(s); i++) {
153+ g[i*3 ] = dec2hex(s[i]/16);
154+ g[i*3 + 1] = dec2hex(s[i]%16);
155+ g[i*3 + 2] = ' ';
156+ }
157+ g[i*3] = '\0';
158+
159+ return g;
160+}
161+#endif // DEBUG
162+
163+/* Use instead of regcomp. As we expect to be seeing the same regexps over and
164+over again, it make sense to cache the results. */
165+static regexp * compile_and_cache(const char * regex_string,
166+ const char * protocol)
167+{
168+ struct pattern_cache * node = first_pattern_cache;
169+ struct pattern_cache * last_pattern_cache = first_pattern_cache;
170+ struct pattern_cache * tmp;
171+ unsigned int len;
172+
173+ while (node != NULL) {
174+ if (!strcmp(node->regex_string, regex_string))
175+ return node->pattern;
176+
177+ last_pattern_cache = node;/* points at the last non-NULL node */
178+ node = node->next;
179+ }
180+
181+ /* If we reach the end of the list, then we have not yet cached
182+ the pattern for this regex. Let's do that now.
183+ Be paranoid about running out of memory to avoid list corruption. */
184+ tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
185+
186+ if(!tmp) {
187+ if (net_ratelimit())
188+ printk(KERN_ERR "layer7: out of memory in "
189+ "compile_and_cache, bailing.\n");
190+ return NULL;
191+ }
192+
193+ tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
194+ tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC);
195+ tmp->next = NULL;
196+
197+ if(!tmp->regex_string || !tmp->pattern) {
198+ if (net_ratelimit())
199+ printk(KERN_ERR "layer7: out of memory in "
200+ "compile_and_cache, bailing.\n");
201+ kfree(tmp->regex_string);
202+ kfree(tmp->pattern);
203+ kfree(tmp);
204+ return NULL;
205+ }
206+
207+ /* Ok. The new node is all ready now. */
208+ node = tmp;
209+
210+ if(first_pattern_cache == NULL) /* list is empty */
211+ first_pattern_cache = node; /* make node the beginning */
212+ else
213+ last_pattern_cache->next = node; /* attach node to the end */
214+
215+ /* copy the string and compile the regex */
216+ len = strlen(regex_string);
217+ DPRINTK("About to compile this: \"%s\"\n", regex_string);
218+ node->pattern = regcomp((char *)regex_string, &len);
219+ if ( !node->pattern ) {
220+ if (net_ratelimit())
221+ printk(KERN_ERR "layer7: Error compiling regexp "
222+ "\"%s\" (%s)\n",
223+ regex_string, protocol);
224+ /* pattern is now cached as NULL, so we won't try again. */
225+ }
226+
227+ strcpy(node->regex_string, regex_string);
228+ return node->pattern;
229+}
230+
231+static int can_handle(const struct sk_buff *skb)
232+{
233+ if(!ip_hdr(skb)) /* not IP */
234+ return 0;
235+ if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
236+ ip_hdr(skb)->protocol != IPPROTO_UDP &&
237+ ip_hdr(skb)->protocol != IPPROTO_ICMP)
238+ return 0;
239+ return 1;
240+}
241+
242+/* Returns offset the into the skb->data that the application data starts */
243+static int app_data_offset(const struct sk_buff *skb)
244+{
245+ /* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
246+ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
247+ int ip_hl = 4*ip_hdr(skb)->ihl;
248+
249+ if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
250+ /* 12 == offset into TCP header for the header length field.
251+ Can't get this with skb->h.th->doff because the tcphdr
252+ struct doesn't get set when routing (this is confirmed to be
253+ true in Netfilter as well as QoS.) */
254+ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
255+
256+ return ip_hl + tcp_hl;
257+ } else if( ip_hdr(skb)->protocol == IPPROTO_UDP ) {
258+ return ip_hl + 8; /* UDP header is always 8 bytes */
259+ } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
260+ return ip_hl + 8; /* ICMP header is 8 bytes */
261+ } else {
262+ if (net_ratelimit())
263+ printk(KERN_ERR "layer7: tried to handle unknown "
264+ "protocol!\n");
265+ return ip_hl + 8; /* something reasonable */
266+ }
267+}
268+
269+/* handles whether there's a match when we aren't appending data anymore */
270+static int match_no_append(struct nf_conn * conntrack,
271+ struct nf_conn * master_conntrack,
272+ enum ip_conntrack_info ctinfo,
273+ enum ip_conntrack_info master_ctinfo,
274+ const struct xt_layer7_info * info)
275+{
276+ /* If we're in here, throw the app data away */
277+ if(master_conntrack->layer7.app_data != NULL) {
278+
279+ #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
280+ if(!master_conntrack->layer7.app_proto) {
281+ char * f =
282+ friendly_print(master_conntrack->layer7.app_data);
283+ char * g =
284+ hex_print(master_conntrack->layer7.app_data);
285+ DPRINTK("\nl7-filter gave up after %d bytes "
286+ "(%d packets):\n%s\n",
287+ strlen(f), TOTAL_PACKETS, f);
288+ kfree(f);
289+ DPRINTK("In hex: %s\n", g);
290+ kfree(g);
291+ }
292+ #endif
293+
294+ kfree(master_conntrack->layer7.app_data);
295+ master_conntrack->layer7.app_data = NULL; /* don't free again */
296+ }
297+
298+ if(master_conntrack->layer7.app_proto){
299+ /* Here child connections set their .app_proto (for /proc) */
300+ if(!conntrack->layer7.app_proto) {
301+ conntrack->layer7.app_proto =
302+ kmalloc(strlen(master_conntrack->layer7.app_proto)+1,
303+ GFP_ATOMIC);
304+ if(!conntrack->layer7.app_proto){
305+ if (net_ratelimit())
306+ printk(KERN_ERR "layer7: out of memory "
307+ "in match_no_append, "
308+ "bailing.\n");
309+ return 1;
310+ }
311+ strcpy(conntrack->layer7.app_proto,
312+ master_conntrack->layer7.app_proto);
313+ }
314+
315+ return (!strcmp(master_conntrack->layer7.app_proto,
316+ info->protocol));
317+ }
318+ else {
319+ /* If not classified, set to "unknown" to distinguish from
320+ connections that are still being tested. */
321+ master_conntrack->layer7.app_proto =
322+ kmalloc(strlen("unknown")+1, GFP_ATOMIC);
323+ if(!master_conntrack->layer7.app_proto){
324+ if (net_ratelimit())
325+ printk(KERN_ERR "layer7: out of memory in "
326+ "match_no_append, bailing.\n");
327+ return 1;
328+ }
329+ strcpy(master_conntrack->layer7.app_proto, "unknown");
330+ return 0;
331+ }
332+}
333+
334+/* add the new app data to the conntrack. Return number of bytes added. */
335+static int add_data(struct nf_conn * master_conntrack,
336+ char * app_data, int appdatalen)
337+{
338+ int length = 0, i;
339+ int oldlength = master_conntrack->layer7.app_data_len;
340+
341+ /* This is a fix for a race condition by Deti Fliegl. However, I'm not
342+ clear on whether the race condition exists or whether this really
343+ fixes it. I might just be being dense... Anyway, if it's not really
344+ a fix, all it does is waste a very small amount of time. */
345+ if(!master_conntrack->layer7.app_data) return 0;
346+
347+ /* Strip nulls. Make everything lower case (our regex lib doesn't
348+ do case insensitivity). Add it to the end of the current data. */
349+ for(i = 0; i < maxdatalen-oldlength-1 &&
350+ i < appdatalen; i++) {
351+ if(app_data[i] != '\0') {
352+ /* the kernel version of tolower mungs 'upper ascii' */
353+ master_conntrack->layer7.app_data[length+oldlength] =
354+ isascii(app_data[i])?
355+ tolower(app_data[i]) : app_data[i];
356+ length++;
357+ }
358+ }
359+
360+ master_conntrack->layer7.app_data[length+oldlength] = '\0';
361+ master_conntrack->layer7.app_data_len = length + oldlength;
362+
363+ return length;
364+}
365+
366+/* taken from drivers/video/modedb.c */
367+static int my_atoi(const char *s)
368+{
369+ int val = 0;
370+
371+ for (;; s++) {
372+ switch (*s) {
373+ case '0'...'9':
374+ val = 10*val+(*s-'0');
375+ break;
376+ default:
377+ return val;
378+ }
379+ }
380+}
381+
382+/* write out num_packets to userland. */
383+static int layer7_read_proc(char* page, char ** start, off_t off, int count,
384+ int* eof, void * data)
385+{
386+ if(num_packets > 99 && net_ratelimit())
387+ printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n");
388+
389+ page[0] = num_packets/10 + '0';
390+ page[1] = num_packets%10 + '0';
391+ page[2] = '\n';
392+ page[3] = '\0';
393+
394+ *eof=1;
395+
396+ return 3;
397+}
398+
399+/* Read in num_packets from userland */
400+static int layer7_write_proc(struct file* file, const char* buffer,
401+ unsigned long count, void *data)
402+{
403+ char * foo = kmalloc(count, GFP_ATOMIC);
404+
405+ if(!foo){
406+ if (net_ratelimit())
407+ printk(KERN_ERR "layer7: out of memory, bailing. "
408+ "num_packets unchanged.\n");
409+ return count;
410+ }
411+
412+ if(copy_from_user(foo, buffer, count)) {
413+ return -EFAULT;
414+ }
415+
416+
417+ num_packets = my_atoi(foo);
418+ kfree (foo);
419+
420+ /* This has an arbitrary limit to make the math easier. I'm lazy.
421+ But anyway, 99 is a LOT! If you want more, you're doing it wrong! */
422+ if(num_packets > 99) {
423+ printk(KERN_WARNING "layer7: num_packets can't be > 99.\n");
424+ num_packets = 99;
425+ } else if(num_packets < 1) {
426+ printk(KERN_WARNING "layer7: num_packets can't be < 1.\n");
427+ num_packets = 1;
428+ }
429+
430+ return count;
431+}
432+
433+static int
434+match(const struct sk_buff *skbin,
435+ const struct net_device *in,
436+ const struct net_device *out,
437+ const struct xt_match *match,
438+ const void *matchinfo,
439+ int offset,
440+ unsigned int protoff,
441+ int *hotdrop)
442+{
443+ /* sidestep const without getting a compiler warning... */
444+ struct sk_buff * skb = (struct sk_buff *)skbin;
445+
446+ const struct xt_layer7_info * info = matchinfo;
447+ enum ip_conntrack_info master_ctinfo, ctinfo;
448+ struct nf_conn *master_conntrack, *conntrack;
449+ unsigned char * app_data;
450+ unsigned int pattern_result, appdatalen;
451+ regexp * comppattern;
452+
453+ /* Be paranoid/incompetent - lock the entire match function. */
454+ spin_lock_bh(&l7_lock);
455+
456+ if(!can_handle(skb)){
457+ DPRINTK("layer7: This is some protocol I can't handle.\n");
458+ spin_unlock_bh(&l7_lock);
459+ return info->invert;
460+ }
461+
462+ /* Treat parent & all its children together as one connection, except
463+ for the purpose of setting conntrack->layer7.app_proto in the actual
464+ connection. This makes /proc/net/ip_conntrack more satisfying. */
465+ if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
466+ !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
467+ DPRINTK("layer7: couldn't get conntrack.\n");
468+ spin_unlock_bh(&l7_lock);
469+ return info->invert;
470+ }
471+
472+ /* Try to get a master conntrack (and its master etc) for FTP, etc. */
473+ while (master_ct(master_conntrack) != NULL)
474+ master_conntrack = master_ct(master_conntrack);
475+
476+ /* if we've classified it or seen too many packets */
477+ if(TOTAL_PACKETS > num_packets ||
478+ master_conntrack->layer7.app_proto) {
479+
480+ pattern_result = match_no_append(conntrack, master_conntrack,
481+ ctinfo, master_ctinfo, info);
482+
483+ /* skb->cb[0] == seen. Don't do things twice if there are
484+ multiple l7 rules. I'm not sure that using cb for this purpose
485+ is correct, even though it says "put your private variables
486+ there". But it doesn't look like it is being used for anything
487+ else in the skbs that make it here. */
488+ skb->cb[0] = 1; /* marking it seen here's probably irrelevant */
489+
490+ spin_unlock_bh(&l7_lock);
491+ return (pattern_result ^ info->invert);
492+ }
493+
494+ if(skb_is_nonlinear(skb)){
495+ if(skb_linearize(skb) != 0){
496+ if (net_ratelimit())
497+ printk(KERN_ERR "layer7: failed to linearize "
498+ "packet, bailing.\n");
499+ spin_unlock_bh(&l7_lock);
500+ return info->invert;
501+ }
502+ }
503+
504+ /* now that the skb is linearized, it's safe to set these. */
505+ app_data = skb->data + app_data_offset(skb);
506+ appdatalen = skb_tail_pointer(skb) - app_data;
507+
508+ /* the return value gets checked later, when we're ready to use it */
509+ comppattern = compile_and_cache(info->pattern, info->protocol);
510+
511+ /* On the first packet of a connection, allocate space for app data */
512+ if(TOTAL_PACKETS == 1 && !skb->cb[0] &&
513+ !master_conntrack->layer7.app_data){
514+ master_conntrack->layer7.app_data =
515+ kmalloc(maxdatalen, GFP_ATOMIC);
516+ if(!master_conntrack->layer7.app_data){
517+ if (net_ratelimit())
518+ printk(KERN_ERR "layer7: out of memory in "
519+ "match, bailing.\n");
520+ spin_unlock_bh(&l7_lock);
521+ return info->invert;
522+ }
523+
524+ master_conntrack->layer7.app_data[0] = '\0';
525+ }
526+
527+ /* Can be here, but unallocated, if numpackets is increased near
528+ the beginning of a connection */
529+ if(master_conntrack->layer7.app_data == NULL){
530+ spin_unlock_bh(&l7_lock);
531+ return (info->invert); /* unmatched */
532+ }
533+
534+ if(!skb->cb[0]){
535+ int newbytes;
536+ newbytes = add_data(master_conntrack, app_data, appdatalen);
537+
538+ if(newbytes == 0) { /* didn't add any data */
539+ skb->cb[0] = 1;
540+ /* Didn't match before, not going to match now */
541+ spin_unlock_bh(&l7_lock);
542+ return info->invert;
543+ }
544+ }
545+
546+ /* If looking for "unknown", then never match. "Unknown" means that
547+ we've given up; we're still trying with these packets. */
548+ if(!strcmp(info->protocol, "unknown")) {
549+ pattern_result = 0;
550+ /* If looking for "unset", then always match. "Unset" means that we
551+ haven't yet classified the connection. */
552+ } else if(!strcmp(info->protocol, "unset")) {
553+ pattern_result = 2;
554+ DPRINTK("layer7: matched unset: not yet classified "
555+ "(%d/%d packets)\n", TOTAL_PACKETS, num_packets);
556+ /* If the regexp failed to compile, don't bother running it */
557+ } else if(comppattern &&
558+ regexec(comppattern, master_conntrack->layer7.app_data)){
559+ DPRINTK("layer7: matched %s\n", info->protocol);
560+ pattern_result = 1;
561+ } else pattern_result = 0;
562+
563+ if(pattern_result == 1) {
564+ master_conntrack->layer7.app_proto =
565+ kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
566+ if(!master_conntrack->layer7.app_proto){
567+ if (net_ratelimit())
568+ printk(KERN_ERR "layer7: out of memory in "
569+ "match, bailing.\n");
570+ spin_unlock_bh(&l7_lock);
571+ return (pattern_result ^ info->invert);
572+ }
573+ strcpy(master_conntrack->layer7.app_proto, info->protocol);
574+ } else if(pattern_result > 1) { /* cleanup from "unset" */
575+ pattern_result = 1;
576+ }
577+
578+ /* mark the packet seen */
579+ skb->cb[0] = 1;
580+
581+ spin_unlock_bh(&l7_lock);
582+ return (pattern_result ^ info->invert);
583+}
584+
585+static int check(const char *tablename,
586+ const void *inf,
587+ const struct xt_match *match,
588+ void *matchinfo,
589+ unsigned int hook_mask)
590+
591+{
592+ // load nf_conntrack_ipv4
593+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
594+ printk(KERN_WARNING "can't load conntrack support for "
595+ "proto=%d\n", match->family);
596+ return 0;
597+ }
598+ return 1;
599+}
600+
601+static void
602+destroy(const struct xt_match *match, void *matchinfo)
603+{
604+ nf_ct_l3proto_module_put(match->family);
605+}
606+
607+static struct xt_match xt_layer7_match[] = {
608+{
609+ .name = "layer7",
610+ .family = AF_INET,
611+ .checkentry = check,
612+ .match = match,
613+ .destroy = destroy,
614+ .matchsize = sizeof(struct xt_layer7_info),
615+ .me = THIS_MODULE
616+}
617+};
618+
619+static void layer7_cleanup_proc(void)
620+{
621+ remove_proc_entry("layer7_numpackets", proc_net);
622+}
623+
624+/* register the proc file */
625+static void layer7_init_proc(void)
626+{
627+ struct proc_dir_entry* entry;
628+ entry = create_proc_entry("layer7_numpackets", 0644, proc_net);
629+ entry->read_proc = layer7_read_proc;
630+ entry->write_proc = layer7_write_proc;
631+}
632+
633+static int __init xt_layer7_init(void)
634+{
635+ need_conntrack();
636+
637+ layer7_init_proc();
638+ if(maxdatalen < 1) {
639+ printk(KERN_WARNING "layer7: maxdatalen can't be < 1, "
640+ "using 1\n");
641+ maxdatalen = 1;
642+ }
643+ /* This is not a hard limit. It's just here to prevent people from
644+ bringing their slow machines to a grinding halt. */
645+ else if(maxdatalen > 65536) {
646+ printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "
647+ "using 65536\n");
648+ maxdatalen = 65536;
649+ }
650+ return xt_register_matches(xt_layer7_match,
651+ ARRAY_SIZE(xt_layer7_match));
652+}
653+
654+static void __exit xt_layer7_fini(void)
655+{
656+ layer7_cleanup_proc();
657+ xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match));
658+}
659+
660+module_init(xt_layer7_init);
661+module_exit(xt_layer7_fini);
662+
663--- linux-2.6.22-rc7/net/netfilter/regexp/regexp.c 1969-12-31 18:00:00.000000000 -0600
664+++ linux-2.6.22-rc7-layer7/net/netfilter/regexp/regexp.c 2007-07-03 01:32:35.000000000 -0500
665@@ -0,0 +1,1197 @@
666+/*
667+ * regcomp and regexec -- regsub and regerror are elsewhere
668+ * @(#)regexp.c 1.3 of 18 April 87
669+ *
670+ * Copyright (c) 1986 by University of Toronto.
671+ * Written by Henry Spencer. Not derived from licensed software.
672+ *
673+ * Permission is granted to anyone to use this software for any
674+ * purpose on any computer system, and to redistribute it freely,
675+ * subject to the following restrictions:
676+ *
677+ * 1. The author is not responsible for the consequences of use of
678+ * this software, no matter how awful, even if they arise
679+ * from defects in it.
680+ *
681+ * 2. The origin of this software must not be misrepresented, either
682+ * by explicit claim or by omission.
683+ *
684+ * 3. Altered versions must be plainly marked as such, and must not
685+ * be misrepresented as being the original software.
686+ *
687+ * Beware that some of this code is subtly aware of the way operator
688+ * precedence is structured in regular expressions. Serious changes in
689+ * regular-expression syntax might require a total rethink.
690+ *
691+ * This code was modified by Ethan Sommer to work within the kernel
692+ * (it now uses kmalloc etc..)
693+ *
694+ * Modified slightly by Matthew Strait to use more modern C.
695+ */
696+
697+#include "regexp.h"
698+#include "regmagic.h"
699+
700+/* added by ethan and matt. Lets it work in both kernel and user space.
701+(So iptables can use it, for instance.) Yea, it goes both ways... */
702+#if __KERNEL__
703+ #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
704+#else
705+ #define printk(format,args...) printf(format,##args)
706+#endif
707+
708+void regerror(char * s)
709+{
710+ printk("<3>Regexp: %s\n", s);
711+ /* NOTREACHED */
712+}
713+
714+/*
715+ * The "internal use only" fields in regexp.h are present to pass info from
716+ * compile to execute that permits the execute phase to run lots faster on
717+ * simple cases. They are:
718+ *
719+ * regstart char that must begin a match; '\0' if none obvious
720+ * reganch is the match anchored (at beginning-of-line only)?
721+ * regmust string (pointer into program) that match must include, or NULL
722+ * regmlen length of regmust string
723+ *
724+ * Regstart and reganch permit very fast decisions on suitable starting points
725+ * for a match, cutting down the work a lot. Regmust permits fast rejection
726+ * of lines that cannot possibly match. The regmust tests are costly enough
727+ * that regcomp() supplies a regmust only if the r.e. contains something
728+ * potentially expensive (at present, the only such thing detected is * or +
729+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
730+ * supplied because the test in regexec() needs it and regcomp() is computing
731+ * it anyway.
732+ */
733+
734+/*
735+ * Structure for regexp "program". This is essentially a linear encoding
736+ * of a nondeterministic finite-state machine (aka syntax charts or
737+ * "railroad normal form" in parsing technology). Each node is an opcode
738+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
739+ * all nodes except BRANCH implement concatenation; a "next" pointer with
740+ * a BRANCH on both ends of it is connecting two alternatives. (Here we
741+ * have one of the subtle syntax dependencies: an individual BRANCH (as
742+ * opposed to a collection of them) is never concatenated with anything
743+ * because of operator precedence.) The operand of some types of node is
744+ * a literal string; for others, it is a node leading into a sub-FSM. In
745+ * particular, the operand of a BRANCH node is the first node of the branch.
746+ * (NB this is *not* a tree structure: the tail of the branch connects
747+ * to the thing following the set of BRANCHes.) The opcodes are:
748+ */
749+
750+/* definition number opnd? meaning */
751+#define END 0 /* no End of program. */
752+#define BOL 1 /* no Match "" at beginning of line. */
753+#define EOL 2 /* no Match "" at end of line. */
754+#define ANY 3 /* no Match any one character. */
755+#define ANYOF 4 /* str Match any character in this string. */
756+#define ANYBUT 5 /* str Match any character not in this string. */
757+#define BRANCH 6 /* node Match this alternative, or the next... */
758+#define BACK 7 /* no Match "", "next" ptr points backward. */
759+#define EXACTLY 8 /* str Match this string. */
760+#define NOTHING 9 /* no Match empty string. */
761+#define STAR 10 /* node Match this (simple) thing 0 or more times. */
762+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
763+#define OPEN 20 /* no Mark this point in input as start of #n. */
764+ /* OPEN+1 is number 1, etc. */
765+#define CLOSE 30 /* no Analogous to OPEN. */
766+
767+/*
768+ * Opcode notes:
769+ *
770+ * BRANCH The set of branches constituting a single choice are hooked
771+ * together with their "next" pointers, since precedence prevents
772+ * anything being concatenated to any individual branch. The
773+ * "next" pointer of the last BRANCH in a choice points to the
774+ * thing following the whole choice. This is also where the
775+ * final "next" pointer of each individual branch points; each
776+ * branch starts with the operand node of a BRANCH node.
777+ *
778+ * BACK Normal "next" pointers all implicitly point forward; BACK
779+ * exists to make loop structures possible.
780+ *
781+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
782+ * BRANCH structures using BACK. Simple cases (one character
783+ * per match) are implemented with STAR and PLUS for speed
784+ * and to minimize recursive plunges.
785+ *
786+ * OPEN,CLOSE ...are numbered at compile time.
787+ */
788+
789+/*
790+ * A node is one char of opcode followed by two chars of "next" pointer.
791+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
792+ * value is a positive offset from the opcode of the node containing it.
793+ * An operand, if any, simply follows the node. (Note that much of the
794+ * code generation knows about this implicit relationship.)
795+ *
796+ * Using two bytes for the "next" pointer is vast overkill for most things,
797+ * but allows patterns to get big without disasters.
798+ */
799+#define OP(p) (*(p))
800+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
801+#define OPERAND(p) ((p) + 3)
802+
803+/*
804+ * See regmagic.h for one further detail of program structure.
805+ */
806+
807+
808+/*
809+ * Utility definitions.
810+ */
811+#ifndef CHARBITS
812+#define UCHARAT(p) ((int)*(unsigned char *)(p))
813+#else
814+#define UCHARAT(p) ((int)*(p)&CHARBITS)
815+#endif
816+
817+#define FAIL(m) { regerror(m); return(NULL); }
818+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
819+#define META "^$.[()|?+*\\"
820+
821+/*
822+ * Flags to be passed up and down.
823+ */
824+#define HASWIDTH 01 /* Known never to match null string. */
825+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
826+#define SPSTART 04 /* Starts with * or +. */
827+#define WORST 0 /* Worst case. */
828+
829+/*
830+ * Global work variables for regcomp().
831+ */
832+struct match_globals {
833+char *reginput; /* String-input pointer. */
834+char *regbol; /* Beginning of input, for ^ check. */
835+char **regstartp; /* Pointer to startp array. */
836+char **regendp; /* Ditto for endp. */
837+char *regparse; /* Input-scan pointer. */
838+int regnpar; /* () count. */
839+char regdummy;
840+char *regcode; /* Code-emit pointer; &regdummy = don't. */
841+long regsize; /* Code size. */
842+};
843+
844+/*
845+ * Forward declarations for regcomp()'s friends.
846+ */
847+#ifndef STATIC
848+#define STATIC static
849+#endif
850+STATIC char *reg(struct match_globals *g, int paren,int *flagp);
851+STATIC char *regbranch(struct match_globals *g, int *flagp);
852+STATIC char *regpiece(struct match_globals *g, int *flagp);
853+STATIC char *regatom(struct match_globals *g, int *flagp);
854+STATIC char *regnode(struct match_globals *g, char op);
855+STATIC char *regnext(struct match_globals *g, char *p);
856+STATIC void regc(struct match_globals *g, char b);
857+STATIC void reginsert(struct match_globals *g, char op, char *opnd);
858+STATIC void regtail(struct match_globals *g, char *p, char *val);
859+STATIC void regoptail(struct match_globals *g, char *p, char *val);
860+
861+
862+__kernel_size_t my_strcspn(const char *s1,const char *s2)
863+{
864+ char *scan1;
865+ char *scan2;
866+ int count;
867+
868+ count = 0;
869+ for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {
870+ for (scan2 = (char *)s2; *scan2 != '\0';) /* ++ moved down. */
871+ if (*scan1 == *scan2++)
872+ return(count);
873+ count++;
874+ }
875+ return(count);
876+}
877+
878+/*
879+ - regcomp - compile a regular expression into internal code
880+ *
881+ * We can't allocate space until we know how big the compiled form will be,
882+ * but we can't compile it (and thus know how big it is) until we've got a
883+ * place to put the code. So we cheat: we compile it twice, once with code
884+ * generation turned off and size counting turned on, and once "for real".
885+ * This also means that we don't allocate space until we are sure that the
886+ * thing really will compile successfully, and we never have to move the
887+ * code and thus invalidate pointers into it. (Note that it has to be in
888+ * one piece because free() must be able to free it all.)
889+ *
890+ * Beware that the optimization-preparation code in here knows about some
891+ * of the structure of the compiled regexp.
892+ */
893+regexp *
894+regcomp(char *exp,int *patternsize)
895+{
896+ register regexp *r;
897+ register char *scan;
898+ register char *longest;
899+ register int len;
900+ int flags;
901+ struct match_globals g;
902+
903+ /* commented out by ethan
904+ extern char *malloc();
905+ */
906+
907+ if (exp == NULL)
908+ FAIL("NULL argument");
909+
910+ /* First pass: determine size, legality. */
911+ g.regparse = exp;
912+ g.regnpar = 1;
913+ g.regsize = 0L;
914+ g.regcode = &g.regdummy;
915+ regc(&g, MAGIC);
916+ if (reg(&g, 0, &flags) == NULL)
917+ return(NULL);
918+
919+ /* Small enough for pointer-storage convention? */
920+ if (g.regsize >= 32767L) /* Probably could be 65535L. */
921+ FAIL("regexp too big");
922+
923+ /* Allocate space. */
924+ *patternsize=sizeof(regexp) + (unsigned)g.regsize;
925+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)g.regsize);
926+ if (r == NULL)
927+ FAIL("out of space");
928+
929+ /* Second pass: emit code. */
930+ g.regparse = exp;
931+ g.regnpar = 1;
932+ g.regcode = r->program;
933+ regc(&g, MAGIC);
934+ if (reg(&g, 0, &flags) == NULL)
935+ return(NULL);
936+
937+ /* Dig out information for optimizations. */
938+ r->regstart = '\0'; /* Worst-case defaults. */
939+ r->reganch = 0;
940+ r->regmust = NULL;
941+ r->regmlen = 0;
942+ scan = r->program+1; /* First BRANCH. */
943+ if (OP(regnext(&g, scan)) == END) { /* Only one top-level choice. */
944+ scan = OPERAND(scan);
945+
946+ /* Starting-point info. */
947+ if (OP(scan) == EXACTLY)
948+ r->regstart = *OPERAND(scan);
949+ else if (OP(scan) == BOL)
950+ r->reganch++;
951+
952+ /*
953+ * If there's something expensive in the r.e., find the
954+ * longest literal string that must appear and make it the
955+ * regmust. Resolve ties in favor of later strings, since
956+ * the regstart check works with the beginning of the r.e.
957+ * and avoiding duplication strengthens checking. Not a
958+ * strong reason, but sufficient in the absence of others.
959+ */
960+ if (flags&SPSTART) {
961+ longest = NULL;
962+ len = 0;
963+ for (; scan != NULL; scan = regnext(&g, scan))
964+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
965+ longest = OPERAND(scan);
966+ len = strlen(OPERAND(scan));
967+ }
968+ r->regmust = longest;
969+ r->regmlen = len;
970+ }
971+ }
972+
973+ return(r);
974+}
975+
976+/*
977+ - reg - regular expression, i.e. main body or parenthesized thing
978+ *
979+ * Caller must absorb opening parenthesis.
980+ *
981+ * Combining parenthesis handling with the base level of regular expression
982+ * is a trifle forced, but the need to tie the tails of the branches to what
983+ * follows makes it hard to avoid.
984+ */
985+static char *
986+reg(struct match_globals *g, int paren, int *flagp /* Parenthesized? */ )
987+{
988+ register char *ret;
989+ register char *br;
990+ register char *ender;
991+ register int parno = 0; /* 0 makes gcc happy */
992+ int flags;
993+
994+ *flagp = HASWIDTH; /* Tentatively. */
995+
996+ /* Make an OPEN node, if parenthesized. */
997+ if (paren) {
998+ if (g->regnpar >= NSUBEXP)
999+ FAIL("too many ()");
1000+ parno = g->regnpar;
1001+ g->regnpar++;
1002+ ret = regnode(g, OPEN+parno);
1003+ } else
1004+ ret = NULL;
1005+
1006+ /* Pick up the branches, linking them together. */
1007+ br = regbranch(g, &flags);
1008+ if (br == NULL)
1009+ return(NULL);
1010+ if (ret != NULL)
1011+ regtail(g, ret, br); /* OPEN -> first. */
1012+ else
1013+ ret = br;
1014+ if (!(flags&HASWIDTH))
1015+ *flagp &= ~HASWIDTH;
1016+ *flagp |= flags&SPSTART;
1017+ while (*g->regparse == '|') {
1018+ g->regparse++;
1019+ br = regbranch(g, &flags);
1020+ if (br == NULL)
1021+ return(NULL);
1022+ regtail(g, ret, br); /* BRANCH -> BRANCH. */
1023+ if (!(flags&HASWIDTH))
1024+ *flagp &= ~HASWIDTH;
1025+ *flagp |= flags&SPSTART;
1026+ }
1027+
1028+ /* Make a closing node, and hook it on the end. */
1029+ ender = regnode(g, (paren) ? CLOSE+parno : END);
1030+ regtail(g, ret, ender);
1031+
1032+ /* Hook the tails of the branches to the closing node. */
1033+ for (br = ret; br != NULL; br = regnext(g, br))
1034+ regoptail(g, br, ender);
1035+
1036+ /* Check for proper termination. */
1037+ if (paren && *g->regparse++ != ')') {
1038+ FAIL("unmatched ()");
1039+ } else if (!paren && *g->regparse != '\0') {
1040+ if (*g->regparse == ')') {
1041+ FAIL("unmatched ()");
1042+ } else
1043+ FAIL("junk on end"); /* "Can't happen". */
1044+ /* NOTREACHED */
1045+ }
1046+
1047+ return(ret);
1048+}
1049+
1050+/*
1051+ - regbranch - one alternative of an | operator
1052+ *
1053+ * Implements the concatenation operator.
1054+ */
1055+static char *
1056+regbranch(struct match_globals *g, int *flagp)
1057+{
1058+ register char *ret;
1059+ register char *chain;
1060+ register char *latest;
1061+ int flags;
1062+
1063+ *flagp = WORST; /* Tentatively. */
1064+
1065+ ret = regnode(g, BRANCH);
1066+ chain = NULL;
1067+ while (*g->regparse != '\0' && *g->regparse != '|' && *g->regparse != ')') {
1068+ latest = regpiece(g, &flags);
1069+ if (latest == NULL)
1070+ return(NULL);
1071+ *flagp |= flags&HASWIDTH;
1072+ if (chain == NULL) /* First piece. */
1073+ *flagp |= flags&SPSTART;
1074+ else
1075+ regtail(g, chain, latest);
1076+ chain = latest;
1077+ }
1078+ if (chain == NULL) /* Loop ran zero times. */
1079+ (void) regnode(g, NOTHING);
1080+
1081+ return(ret);
1082+}
1083+
1084+/*
1085+ - regpiece - something followed by possible [*+?]
1086+ *
1087+ * Note that the branching code sequences used for ? and the general cases
1088+ * of * and + are somewhat optimized: they use the same NOTHING node as
1089+ * both the endmarker for their branch list and the body of the last branch.
1090+ * It might seem that this node could be dispensed with entirely, but the
1091+ * endmarker role is not redundant.
1092+ */
1093+static char *
1094+regpiece(struct match_globals *g, int *flagp)
1095+{
1096+ register char *ret;
1097+ register char op;
1098+ register char *next;
1099+ int flags;
1100+
1101+ ret = regatom(g, &flags);
1102+ if (ret == NULL)
1103+ return(NULL);
1104+
1105+ op = *g->regparse;
1106+ if (!ISMULT(op)) {
1107+ *flagp = flags;
1108+ return(ret);
1109+ }
1110+
1111+ if (!(flags&HASWIDTH) && op != '?')
1112+ FAIL("*+ operand could be empty");
1113+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
1114+
1115+ if (op == '*' && (flags&SIMPLE))
1116+ reginsert(g, STAR, ret);
1117+ else if (op == '*') {
1118+ /* Emit x* as (x&|), where & means "self". */
1119+ reginsert(g, BRANCH, ret); /* Either x */
1120+ regoptail(g, ret, regnode(g, BACK)); /* and loop */
1121+ regoptail(g, ret, ret); /* back */
1122+ regtail(g, ret, regnode(g, BRANCH)); /* or */
1123+ regtail(g, ret, regnode(g, NOTHING)); /* null. */
1124+ } else if (op == '+' && (flags&SIMPLE))
1125+ reginsert(g, PLUS, ret);
1126+ else if (op == '+') {
1127+ /* Emit x+ as x(&|), where & means "self". */
1128+ next = regnode(g, BRANCH); /* Either */
1129+ regtail(g, ret, next);
1130+ regtail(g, regnode(g, BACK), ret); /* loop back */
1131+ regtail(g, next, regnode(g, BRANCH)); /* or */
1132+ regtail(g, ret, regnode(g, NOTHING)); /* null. */
1133+ } else if (op == '?') {
1134+ /* Emit x? as (x|) */
1135+ reginsert(g, BRANCH, ret); /* Either x */
1136+ regtail(g, ret, regnode(g, BRANCH)); /* or */
1137+ next = regnode(g, NOTHING); /* null. */
1138+ regtail(g, ret, next);
1139+ regoptail(g, ret, next);
1140+ }
1141+ g->regparse++;
1142+ if (ISMULT(*g->regparse))
1143+ FAIL("nested *?+");
1144+
1145+ return(ret);
1146+}
1147+
1148+/*
1149+ - regatom - the lowest level
1150+ *
1151+ * Optimization: gobbles an entire sequence of ordinary characters so that
1152+ * it can turn them into a single node, which is smaller to store and
1153+ * faster to run. Backslashed characters are exceptions, each becoming a
1154+ * separate node; the code is simpler that way and it's not worth fixing.
1155+ */
1156+static char *
1157+regatom(struct match_globals *g, int *flagp)
1158+{
1159+ register char *ret;
1160+ int flags;
1161+
1162+ *flagp = WORST; /* Tentatively. */
1163+
1164+ switch (*g->regparse++) {
1165+ case '^':
1166+ ret = regnode(g, BOL);
1167+ break;
1168+ case '$':
1169+ ret = regnode(g, EOL);
1170+ break;
1171+ case '.':
1172+ ret = regnode(g, ANY);
1173+ *flagp |= HASWIDTH|SIMPLE;
1174+ break;
1175+ case '[': {
1176+ register int class;
1177+ register int classend;
1178+
1179+ if (*g->regparse == '^') { /* Complement of range. */
1180+ ret = regnode(g, ANYBUT);
1181+ g->regparse++;
1182+ } else
1183+ ret = regnode(g, ANYOF);
1184+ if (*g->regparse == ']' || *g->regparse == '-')
1185+ regc(g, *g->regparse++);
1186+ while (*g->regparse != '\0' && *g->regparse != ']') {
1187+ if (*g->regparse == '-') {
1188+ g->regparse++;
1189+ if (*g->regparse == ']' || *g->regparse == '\0')
1190+ regc(g, '-');
1191+ else {
1192+ class = UCHARAT(g->regparse-2)+1;
1193+ classend = UCHARAT(g->regparse);
1194+ if (class > classend+1)
1195+ FAIL("invalid [] range");
1196+ for (; class <= classend; class++)
1197+ regc(g, class);
1198+ g->regparse++;
1199+ }
1200+ } else
1201+ regc(g, *g->regparse++);
1202+ }
1203+ regc(g, '\0');
1204+ if (*g->regparse != ']')
1205+ FAIL("unmatched []");
1206+ g->regparse++;
1207+ *flagp |= HASWIDTH|SIMPLE;
1208+ }
1209+ break;
1210+ case '(':
1211+ ret = reg(g, 1, &flags);
1212+ if (ret == NULL)
1213+ return(NULL);
1214+ *flagp |= flags&(HASWIDTH|SPSTART);
1215+ break;
1216+ case '\0':
1217+ case '|':
1218+ case ')':
1219+ FAIL("internal urp"); /* Supposed to be caught earlier. */
1220+ break;
1221+ case '?':
1222+ case '+':
1223+ case '*':
1224+ FAIL("?+* follows nothing");
1225+ break;
1226+ case '\\':
1227+ if (*g->regparse == '\0')
1228+ FAIL("trailing \\");
1229+ ret = regnode(g, EXACTLY);
1230+ regc(g, *g->regparse++);
1231+ regc(g, '\0');
1232+ *flagp |= HASWIDTH|SIMPLE;
1233+ break;
1234+ default: {
1235+ register int len;
1236+ register char ender;
1237+
1238+ g->regparse--;
1239+ len = my_strcspn((const char *)g->regparse, (const char *)META);
1240+ if (len <= 0)
1241+ FAIL("internal disaster");
1242+ ender = *(g->regparse+len);
1243+ if (len > 1 && ISMULT(ender))
1244+ len--; /* Back off clear of ?+* operand. */
1245+ *flagp |= HASWIDTH;
1246+ if (len == 1)
1247+ *flagp |= SIMPLE;
1248+ ret = regnode(g, EXACTLY);
1249+ while (len > 0) {
1250+ regc(g, *g->regparse++);
1251+ len--;
1252+ }
1253+ regc(g, '\0');
1254+ }
1255+ break;
1256+ }
1257+
1258+ return(ret);
1259+}
1260+
1261+/*
1262+ - regnode - emit a node
1263+ */
1264+static char * /* Location. */
1265+regnode(struct match_globals *g, char op)
1266+{
1267+ register char *ret;
1268+ register char *ptr;
1269+
1270+ ret = g->regcode;
1271+ if (ret == &g->regdummy) {
1272+ g->regsize += 3;
1273+ return(ret);
1274+ }
1275+
1276+ ptr = ret;
1277+ *ptr++ = op;
1278+ *ptr++ = '\0'; /* Null "next" pointer. */
1279+ *ptr++ = '\0';
1280+ g->regcode = ptr;
1281+
1282+ return(ret);
1283+}
1284+
1285+/*
1286+ - regc - emit (if appropriate) a byte of code
1287+ */
1288+static void
1289+regc(struct match_globals *g, char b)
1290+{
1291+ if (g->regcode != &g->regdummy)
1292+ *g->regcode++ = b;
1293+ else
1294+ g->regsize++;
1295+}
1296+
1297+/*
1298+ - reginsert - insert an operator in front of already-emitted operand
1299+ *
1300+ * Means relocating the operand.
1301+ */
1302+static void
1303+reginsert(struct match_globals *g, char op, char* opnd)
1304+{
1305+ register char *src;
1306+ register char *dst;
1307+ register char *place;
1308+
1309+ if (g->regcode == &g->regdummy) {
1310+ g->regsize += 3;
1311+ return;
1312+ }
1313+
1314+ src = g->regcode;
1315+ g->regcode += 3;
1316+ dst = g->regcode;
1317+ while (src > opnd)
1318+ *--dst = *--src;
1319+
1320+ place = opnd; /* Op node, where operand used to be. */
1321+ *place++ = op;
1322+ *place++ = '\0';
1323+ *place++ = '\0';
1324+}
1325+
1326+/*
1327+ - regtail - set the next-pointer at the end of a node chain
1328+ */
1329+static void
1330+regtail(struct match_globals *g, char *p, char *val)
1331+{
1332+ register char *scan;
1333+ register char *temp;
1334+ register int offset;
1335+
1336+ if (p == &g->regdummy)
1337+ return;
1338+
1339+ /* Find last node. */
1340+ scan = p;
1341+ for (;;) {
1342+ temp = regnext(g, scan);
1343+ if (temp == NULL)
1344+ break;
1345+ scan = temp;
1346+ }
1347+
1348+ if (OP(scan) == BACK)
1349+ offset = scan - val;
1350+ else
1351+ offset = val - scan;
1352+ *(scan+1) = (offset>>8)&0377;
1353+ *(scan+2) = offset&0377;
1354+}
1355+
1356+/*
1357+ - regoptail - regtail on operand of first argument; nop if operandless
1358+ */
1359+static void
1360+regoptail(struct match_globals *g, char *p, char *val)
1361+{
1362+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
1363+ if (p == NULL || p == &g->regdummy || OP(p) != BRANCH)
1364+ return;
1365+ regtail(g, OPERAND(p), val);
1366+}
1367+
1368+/*
1369+ * regexec and friends
1370+ */
1371+
1372+
1373+/*
1374+ * Forwards.
1375+ */
1376+STATIC int regtry(struct match_globals *g, regexp *prog, char *string);
1377+STATIC int regmatch(struct match_globals *g, char *prog);
1378+STATIC int regrepeat(struct match_globals *g, char *p);
1379+
1380+#ifdef DEBUG
1381+int regnarrate = 0;
1382+void regdump();
1383+STATIC char *regprop(char *op);
1384+#endif
1385+
1386+/*
1387+ - regexec - match a regexp against a string
1388+ */
1389+int
1390+regexec(regexp *prog, char *string)
1391+{
1392+ register char *s;
1393+ struct match_globals g;
1394+
1395+ /* Be paranoid... */
1396+ if (prog == NULL || string == NULL) {
1397+ printk("<3>Regexp: NULL parameter\n");
1398+ return(0);
1399+ }
1400+
1401+ /* Check validity of program. */
1402+ if (UCHARAT(prog->program) != MAGIC) {
1403+ printk("<3>Regexp: corrupted program\n");
1404+ return(0);
1405+ }
1406+
1407+ /* If there is a "must appear" string, look for it. */
1408+ if (prog->regmust != NULL) {
1409+ s = string;
1410+ while ((s = strchr(s, prog->regmust[0])) != NULL) {
1411+ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
1412+ break; /* Found it. */
1413+ s++;
1414+ }
1415+ if (s == NULL) /* Not present. */
1416+ return(0);
1417+ }
1418+
1419+ /* Mark beginning of line for ^ . */
1420+ g.regbol = string;
1421+
1422+ /* Simplest case: anchored match need be tried only once. */
1423+ if (prog->reganch)
1424+ return(regtry(&g, prog, string));
1425+
1426+ /* Messy cases: unanchored match. */
1427+ s = string;
1428+ if (prog->regstart != '\0')
1429+ /* We know what char it must start with. */
1430+ while ((s = strchr(s, prog->regstart)) != NULL) {
1431+ if (regtry(&g, prog, s))
1432+ return(1);
1433+ s++;
1434+ }
1435+ else
1436+ /* We don't -- general case. */
1437+ do {
1438+ if (regtry(&g, prog, s))
1439+ return(1);
1440+ } while (*s++ != '\0');
1441+
1442+ /* Failure. */
1443+ return(0);
1444+}
1445+
1446+/*
1447+ - regtry - try match at specific point
1448+ */
1449+static int /* 0 failure, 1 success */
1450+regtry(struct match_globals *g, regexp *prog, char *string)
1451+{
1452+ register int i;
1453+ register char **sp;
1454+ register char **ep;
1455+
1456+ g->reginput = string;
1457+ g->regstartp = prog->startp;
1458+ g->regendp = prog->endp;
1459+
1460+ sp = prog->startp;
1461+ ep = prog->endp;
1462+ for (i = NSUBEXP; i > 0; i--) {
1463+ *sp++ = NULL;
1464+ *ep++ = NULL;
1465+ }
1466+ if (regmatch(g, prog->program + 1)) {
1467+ prog->startp[0] = string;
1468+ prog->endp[0] = g->reginput;
1469+ return(1);
1470+ } else
1471+ return(0);
1472+}
1473+
1474+/*
1475+ - regmatch - main matching routine
1476+ *
1477+ * Conceptually the strategy is simple: check to see whether the current
1478+ * node matches, call self recursively to see whether the rest matches,
1479+ * and then act accordingly. In practice we make some effort to avoid
1480+ * recursion, in particular by going through "ordinary" nodes (that don't
1481+ * need to know whether the rest of the match failed) by a loop instead of
1482+ * by recursion.
1483+ */
1484+static int /* 0 failure, 1 success */
1485+regmatch(struct match_globals *g, char *prog)
1486+{
1487+ register char *scan = prog; /* Current node. */
1488+ char *next; /* Next node. */
1489+
1490+#ifdef DEBUG
1491+ if (scan != NULL && regnarrate)
1492+ fprintf(stderr, "%s(\n", regprop(scan));
1493+#endif
1494+ while (scan != NULL) {
1495+#ifdef DEBUG
1496+ if (regnarrate)
1497+ fprintf(stderr, "%s...\n", regprop(scan));
1498+#endif
1499+ next = regnext(g, scan);
1500+
1501+ switch (OP(scan)) {
1502+ case BOL:
1503+ if (g->reginput != g->regbol)
1504+ return(0);
1505+ break;
1506+ case EOL:
1507+ if (*g->reginput != '\0')
1508+ return(0);
1509+ break;
1510+ case ANY:
1511+ if (*g->reginput == '\0')
1512+ return(0);
1513+ g->reginput++;
1514+ break;
1515+ case EXACTLY: {
1516+ register int len;
1517+ register char *opnd;
1518+
1519+ opnd = OPERAND(scan);
1520+ /* Inline the first character, for speed. */
1521+ if (*opnd != *g->reginput)
1522+ return(0);
1523+ len = strlen(opnd);
1524+ if (len > 1 && strncmp(opnd, g->reginput, len) != 0)
1525+ return(0);
1526+ g->reginput += len;
1527+ }
1528+ break;
1529+ case ANYOF:
1530+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) == NULL)
1531+ return(0);
1532+ g->reginput++;
1533+ break;
1534+ case ANYBUT:
1535+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) != NULL)
1536+ return(0);
1537+ g->reginput++;
1538+ break;
1539+ case NOTHING:
1540+ case BACK:
1541+ break;
1542+ case OPEN+1:
1543+ case OPEN+2:
1544+ case OPEN+3:
1545+ case OPEN+4:
1546+ case OPEN+5:
1547+ case OPEN+6:
1548+ case OPEN+7:
1549+ case OPEN+8:
1550+ case OPEN+9: {
1551+ register int no;
1552+ register char *save;
1553+
1554+ no = OP(scan) - OPEN;
1555+ save = g->reginput;
1556+
1557+ if (regmatch(g, next)) {
1558+ /*
1559+ * Don't set startp if some later
1560+ * invocation of the same parentheses
1561+ * already has.
1562+ */
1563+ if (g->regstartp[no] == NULL)
1564+ g->regstartp[no] = save;
1565+ return(1);
1566+ } else
1567+ return(0);
1568+ }
1569+ break;
1570+ case CLOSE+1:
1571+ case CLOSE+2:
1572+ case CLOSE+3:
1573+ case CLOSE+4:
1574+ case CLOSE+5:
1575+ case CLOSE+6:
1576+ case CLOSE+7:
1577+ case CLOSE+8:
1578+ case CLOSE+9:
1579+ {
1580+ register int no;
1581+ register char *save;
1582+
1583+ no = OP(scan) - CLOSE;
1584+ save = g->reginput;
1585+
1586+ if (regmatch(g, next)) {
1587+ /*
1588+ * Don't set endp if some later
1589+ * invocation of the same parentheses
1590+ * already has.
1591+ */
1592+ if (g->regendp[no] == NULL)
1593+ g->regendp[no] = save;
1594+ return(1);
1595+ } else
1596+ return(0);
1597+ }
1598+ break;
1599+ case BRANCH: {
1600+ register char *save;
1601+
1602+ if (OP(next) != BRANCH) /* No choice. */
1603+ next = OPERAND(scan); /* Avoid recursion. */
1604+ else {
1605+ do {
1606+ save = g->reginput;
1607+ if (regmatch(g, OPERAND(scan)))
1608+ return(1);
1609+ g->reginput = save;
1610+ scan = regnext(g, scan);
1611+ } while (scan != NULL && OP(scan) == BRANCH);
1612+ return(0);
1613+ /* NOTREACHED */
1614+ }
1615+ }
1616+ break;
1617+ case STAR:
1618+ case PLUS: {
1619+ register char nextch;
1620+ register int no;
1621+ register char *save;
1622+ register int min;
1623+
1624+ /*
1625+ * Lookahead to avoid useless match attempts
1626+ * when we know what character comes next.
1627+ */
1628+ nextch = '\0';
1629+ if (OP(next) == EXACTLY)
1630+ nextch = *OPERAND(next);
1631+ min = (OP(scan) == STAR) ? 0 : 1;
1632+ save = g->reginput;
1633+ no = regrepeat(g, OPERAND(scan));
1634+ while (no >= min) {
1635+ /* If it could work, try it. */
1636+ if (nextch == '\0' || *g->reginput == nextch)
1637+ if (regmatch(g, next))
1638+ return(1);
1639+ /* Couldn't or didn't -- back up. */
1640+ no--;
1641+ g->reginput = save + no;
1642+ }
1643+ return(0);
1644+ }
1645+ break;
1646+ case END:
1647+ return(1); /* Success! */
1648+ break;
1649+ default:
1650+ printk("<3>Regexp: memory corruption\n");
1651+ return(0);
1652+ break;
1653+ }
1654+
1655+ scan = next;
1656+ }
1657+
1658+ /*
1659+ * We get here only if there's trouble -- normally "case END" is
1660+ * the terminating point.
1661+ */
1662+ printk("<3>Regexp: corrupted pointers\n");
1663+ return(0);
1664+}
1665+
1666+/*
1667+ - regrepeat - repeatedly match something simple, report how many
1668+ */
1669+static int
1670+regrepeat(struct match_globals *g, char *p)
1671+{
1672+ register int count = 0;
1673+ register char *scan;
1674+ register char *opnd;
1675+
1676+ scan = g->reginput;
1677+ opnd = OPERAND(p);
1678+ switch (OP(p)) {
1679+ case ANY:
1680+ count = strlen(scan);
1681+ scan += count;
1682+ break;
1683+ case EXACTLY:
1684+ while (*opnd == *scan) {
1685+ count++;
1686+ scan++;
1687+ }
1688+ break;
1689+ case ANYOF:
1690+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
1691+ count++;
1692+ scan++;
1693+ }
1694+ break;
1695+ case ANYBUT:
1696+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
1697+ count++;
1698+ scan++;
1699+ }
1700+ break;
1701+ default: /* Oh dear. Called inappropriately. */
1702+ printk("<3>Regexp: internal foulup\n");
1703+ count = 0; /* Best compromise. */
1704+ break;
1705+ }
1706+ g->reginput = scan;
1707+
1708+ return(count);
1709+}
1710+
1711+/*
1712+ - regnext - dig the "next" pointer out of a node
1713+ */
1714+static char*
1715+regnext(struct match_globals *g, char *p)
1716+{
1717+ register int offset;
1718+
1719+ if (p == &g->regdummy)
1720+ return(NULL);
1721+
1722+ offset = NEXT(p);
1723+ if (offset == 0)
1724+ return(NULL);
1725+
1726+ if (OP(p) == BACK)
1727+ return(p-offset);
1728+ else
1729+ return(p+offset);
1730+}
1731+
1732+#ifdef DEBUG
1733+
1734+STATIC char *regprop();
1735+
1736+/*
1737+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
1738+ */
1739+void
1740+regdump(regexp *r)
1741+{
1742+ register char *s;
1743+ register char op = EXACTLY; /* Arbitrary non-END op. */
1744+ register char *next;
1745+ /* extern char *strchr(); */
1746+
1747+
1748+ s = r->program + 1;
1749+ while (op != END) { /* While that wasn't END last time... */
1750+ op = OP(s);
1751+ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
1752+ next = regnext(s);
1753+ if (next == NULL) /* Next ptr. */
1754+ printf("(0)");
1755+ else
1756+ printf("(%d)", (s-r->program)+(next-s));
1757+ s += 3;
1758+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
1759+ /* Literal string, where present. */
1760+ while (*s != '\0') {
1761+ putchar(*s);
1762+ s++;
1763+ }
1764+ s++;
1765+ }
1766+ putchar('\n');
1767+ }
1768+
1769+ /* Header fields of interest. */
1770+ if (r->regstart != '\0')
1771+ printf("start `%c' ", r->regstart);
1772+ if (r->reganch)
1773+ printf("anchored ");
1774+ if (r->regmust != NULL)
1775+ printf("must have \"%s\"", r->regmust);
1776+ printf("\n");
1777+}
1778+
1779+/*
1780+ - regprop - printable representation of opcode
1781+ */
1782+static char *
1783+regprop(char *op)
1784+{
1785+#define BUFLEN 50
1786+ register char *p;
1787+ static char buf[BUFLEN];
1788+
1789+ strcpy(buf, ":");
1790+
1791+ switch (OP(op)) {
1792+ case BOL:
1793+ p = "BOL";
1794+ break;
1795+ case EOL:
1796+ p = "EOL";
1797+ break;
1798+ case ANY:
1799+ p = "ANY";
1800+ break;
1801+ case ANYOF:
1802+ p = "ANYOF";
1803+ break;
1804+ case ANYBUT:
1805+ p = "ANYBUT";
1806+ break;
1807+ case BRANCH:
1808+ p = "BRANCH";
1809+ break;
1810+ case EXACTLY:
1811+ p = "EXACTLY";
1812+ break;
1813+ case NOTHING:
1814+ p = "NOTHING";
1815+ break;
1816+ case BACK:
1817+ p = "BACK";
1818+ break;
1819+ case END:
1820+ p = "END";
1821+ break;
1822+ case OPEN+1:
1823+ case OPEN+2:
1824+ case OPEN+3:
1825+ case OPEN+4:
1826+ case OPEN+5:
1827+ case OPEN+6:
1828+ case OPEN+7:
1829+ case OPEN+8:
1830+ case OPEN+9:
1831+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN);
1832+ p = NULL;
1833+ break;
1834+ case CLOSE+1:
1835+ case CLOSE+2:
1836+ case CLOSE+3:
1837+ case CLOSE+4:
1838+ case CLOSE+5:
1839+ case CLOSE+6:
1840+ case CLOSE+7:
1841+ case CLOSE+8:
1842+ case CLOSE+9:
1843+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE);
1844+ p = NULL;
1845+ break;
1846+ case STAR:
1847+ p = "STAR";
1848+ break;
1849+ case PLUS:
1850+ p = "PLUS";
1851+ break;
1852+ default:
1853+ printk("<3>Regexp: corrupted opcode\n");
1854+ break;
1855+ }
1856+ if (p != NULL)
1857+ strncat(buf, p, BUFLEN-strlen(buf));
1858+ return(buf);
1859+}
1860+#endif
1861+
1862+
1863--- linux-2.6.22-rc7/net/netfilter/regexp/regexp.h 1969-12-31 18:00:00.000000000 -0600
1864+++ linux-2.6.22-rc7-layer7/net/netfilter/regexp/regexp.h 2007-07-03 01:32:35.000000000 -0500
1865@@ -0,0 +1,41 @@
1866+/*
1867+ * Definitions etc. for regexp(3) routines.
1868+ *
1869+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
1870+ * not the System V one.
1871+ */
1872+
1873+#ifndef REGEXP_H
1874+#define REGEXP_H
1875+
1876+
1877+/*
1878+http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h ,
1879+which contains a version of this library, says:
1880+
1881+ *
1882+ * NSUBEXP must be at least 10, and no greater than 117 or the parser
1883+ * will not work properly.
1884+ *
1885+
1886+However, it looks rather like this library is limited to 10. If you think
1887+otherwise, let us know.
1888+*/
1889+
1890+#define NSUBEXP 10
1891+typedef struct regexp {
1892+ char *startp[NSUBEXP];
1893+ char *endp[NSUBEXP];
1894+ char regstart; /* Internal use only. */
1895+ char reganch; /* Internal use only. */
1896+ char *regmust; /* Internal use only. */
1897+ int regmlen; /* Internal use only. */
1898+ char program[1]; /* Unwarranted chumminess with compiler. */
1899+} regexp;
1900+
1901+regexp * regcomp(char *exp, int *patternsize);
1902+int regexec(regexp *prog, char *string);
1903+void regsub(regexp *prog, char *source, char *dest);
1904+void regerror(char *s);
1905+
1906+#endif
1907--- linux-2.6.22-rc7/net/netfilter/regexp/regmagic.h 1969-12-31 18:00:00.000000000 -0600
1908+++ linux-2.6.22-rc7-layer7/net/netfilter/regexp/regmagic.h 2007-07-03 01:32:35.000000000 -0500
1909@@ -0,0 +1,5 @@
1910+/*
1911+ * The first byte of the regexp internal "program" is actually this magic
1912+ * number; the start node begins in the second byte.
1913+ */
1914+#define MAGIC 0234
1915--- linux-2.6.22-rc7/net/netfilter/regexp/regsub.c 1969-12-31 18:00:00.000000000 -0600
1916+++ linux-2.6.22-rc7-layer7/net/netfilter/regexp/regsub.c 2007-07-03 01:32:35.000000000 -0500
1917@@ -0,0 +1,95 @@
1918+/*
1919+ * regsub
1920+ * @(#)regsub.c 1.3 of 2 April 86
1921+ *
1922+ * Copyright (c) 1986 by University of Toronto.
1923+ * Written by Henry Spencer. Not derived from licensed software.
1924+ *
1925+ * Permission is granted to anyone to use this software for any
1926+ * purpose on any computer system, and to redistribute it freely,
1927+ * subject to the following restrictions:
1928+ *
1929+ * 1. The author is not responsible for the consequences of use of
1930+ * this software, no matter how awful, even if they arise
1931+ * from defects in it.
1932+ *
1933+ * 2. The origin of this software must not be misrepresented, either
1934+ * by explicit claim or by omission.
1935+ *
1936+ * 3. Altered versions must be plainly marked as such, and must not
1937+ * be misrepresented as being the original software.
1938+ *
1939+ *
1940+ * This code was modified by Ethan Sommer to work within the kernel
1941+ * (it now uses kmalloc etc..)
1942+ *
1943+ */
1944+#include "regexp.h"
1945+#include "regmagic.h"
1946+#include <linux/string.h>
1947+
1948+
1949+#ifndef CHARBITS
1950+#define UCHARAT(p) ((int)*(unsigned char *)(p))
1951+#else
1952+#define UCHARAT(p) ((int)*(p)&CHARBITS)
1953+#endif
1954+
1955+#if 0
1956+//void regerror(char * s)
1957+//{
1958+// printk("regexp(3): %s", s);
1959+// /* NOTREACHED */
1960+//}
1961+#endif
1962+
1963+/*
1964+ - regsub - perform substitutions after a regexp match
1965+ */
1966+void
1967+regsub(regexp * prog, char * source, char * dest)
1968+{
1969+ register char *src;
1970+ register char *dst;
1971+ register char c;
1972+ register int no;
1973+ register int len;
1974+
1975+ /* Not necessary and gcc doesn't like it -MLS */
1976+ /*extern char *strncpy();*/
1977+
1978+ if (prog == NULL || source == NULL || dest == NULL) {
1979+ regerror("NULL parm to regsub");
1980+ return;
1981+ }
1982+ if (UCHARAT(prog->program) != MAGIC) {
1983+ regerror("damaged regexp fed to regsub");
1984+ return;
1985+ }
1986+
1987+ src = source;
1988+ dst = dest;
1989+ while ((c = *src++) != '\0') {
1990+ if (c == '&')
1991+ no = 0;
1992+ else if (c == '\\' && '0' <= *src && *src <= '9')
1993+ no = *src++ - '0';
1994+ else
1995+ no = -1;
1996+
1997+ if (no < 0) { /* Ordinary character. */
1998+ if (c == '\\' && (*src == '\\' || *src == '&'))
1999+ c = *src++;
2000+ *dst++ = c;
2001+ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
2002+ len = prog->endp[no] - prog->startp[no];
2003+ (void) strncpy(dst, prog->startp[no], len);
2004+ dst += len;
2005+ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
2006+ regerror("damaged match string");
2007+ return;
2008+ }
2009+ }
2010+ }
2011+ *dst++ = '\0';
2012+}
2013--- linux-2.6.22-rc7/net/netfilter/nf_conntrack_core.c 2007-07-01 14:54:24.000000000 -0500
2014+++ linux-2.6.22-rc7-layer7/net/netfilter/nf_conntrack_core.c 2007-07-03 01:32:35.000000000 -0500
2015@@ -330,6 +330,14 @@ destroy_conntrack(struct nf_conntrack *n
2016 * too. */
2017 nf_ct_remove_expectations(ct);
2018
2019+ #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
2020+ if(ct->layer7.app_proto)
2021+ kfree(ct->layer7.app_proto);
2022+ if(ct->layer7.app_data)
2023+ kfree(ct->layer7.app_data);
2024+ #endif
2025+
2026+
2027 /* We overload first tuple to link into unconfirmed list. */
2028 if (!nf_ct_is_confirmed(ct)) {
2029 BUG_ON(list_empty(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list));
2030--- linux-2.6.22-rc7/net/netfilter/nf_conntrack_standalone.c 2007-07-01 14:54:24.000000000 -0500
2031+++ linux-2.6.22-rc7-layer7/net/netfilter/nf_conntrack_standalone.c 2007-07-03 01:32:35.000000000 -0500
2032@@ -184,6 +184,11 @@ static int ct_seq_show(struct seq_file *
2033 return -ENOSPC;
2034 #endif
2035
2036+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
2037+ if(conntrack->layer7.app_proto)
2038+ if(seq_printf(s, "l7proto=%s ",conntrack->layer7.app_proto))
2039+ return -ENOSPC;
2040+#endif
2041 if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
2042 return -ENOSPC;
2043
2044--- linux-2.6.22-rc7/include/net/netfilter/nf_conntrack.h 2007-07-01 14:54:24.000000000 -0500
2045+++ linux-2.6.22-rc7-layer7/include/net/netfilter/nf_conntrack.h 2007-07-03 01:32:35.000000000 -0500
2046@@ -128,6 +128,22 @@ struct nf_conn
2047 u_int32_t secmark;
2048 #endif
2049
2050+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \
2051+ defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
2052+ struct {
2053+ /*
2054+ * e.g. "http". NULL before decision. "unknown" after decision
2055+ * if no match.
2056+ */
2057+ char *app_proto;
2058+ /*
2059+ * application layer data so far. NULL after match decision.
2060+ */
2061+ char *app_data;
2062+ unsigned int app_data_len;
2063+ } layer7;
2064+#endif
2065+
2066 /* Storage reserved for other modules: */
2067 union nf_conntrack_proto proto;
2068
2069--- linux-2.6.22-rc7/include/linux/netfilter/xt_layer7.h 1969-12-31 18:00:00.000000000 -0600
2070+++ linux-2.6.22-rc7-layer7/include/linux/netfilter/xt_layer7.h 2007-07-03 07:48:19.000000000 -0500
2071@@ -0,0 +1,13 @@
2072+#ifndef _XT_LAYER7_H
2073+#define _XT_LAYER7_H
2074+
2075+#define MAX_PATTERN_LEN 8192
2076+#define MAX_PROTOCOL_LEN 256
2077+
2078+struct xt_layer7_info {
2079+ char protocol[MAX_PROTOCOL_LEN];
2080+ char pattern[MAX_PATTERN_LEN];
2081+ u_int8_t invert;
2082+};
2083+
2084+#endif /* _XT_LAYER7_H */
This page took 5.934978 seconds and 4 git commands to generate.