Changeset 24004


Ignore:
Timestamp:
2010-11-15T13:24:48+01:00 (6 years ago)
Author:
acoul
Message:

linux/generic: update to layer7-2.22 for kernels >=2.6.36

Location:
trunk/target/linux/generic
Files:
2 added
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/generic/patches-2.6.36/100-netfilter_layer7_2.22.patch

    r24003 r24004  
    1 --- /dev/null 
    2 +++ b/include/linux/netfilter/xt_layer7.h 
    3 @@ -0,0 +1,13 @@ 
    4 +#ifndef _XT_LAYER7_H 
    5 +#define _XT_LAYER7_H 
    6 + 
    7 +#define MAX_PATTERN_LEN 8192 
    8 +#define MAX_PROTOCOL_LEN 256 
    9 + 
    10 +struct xt_layer7_info { 
    11 +    char protocol[MAX_PROTOCOL_LEN]; 
    12 +    char pattern[MAX_PATTERN_LEN]; 
    13 +    u_int8_t invert; 
    14 +}; 
    15 + 
    16 +#endif /* _XT_LAYER7_H */ 
    17 --- a/include/net/netfilter/nf_conntrack.h 
    18 +++ b/include/net/netfilter/nf_conntrack.h 
    19 @@ -116,6 +116,22 @@ struct nf_conn { 
    20         u_int32_t secmark; 
    21  #endif 
    22   
    23 +#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \ 
    24 +    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
    25 +       struct { 
    26 +               /* 
    27 +                * e.g. "http". NULL before decision. "unknown" after decision 
    28 +                * if no match. 
    29 +                */ 
    30 +               char *app_proto; 
    31 +               /* 
    32 +                * application layer data so far. NULL after match decision. 
    33 +                */ 
    34 +               char *app_data; 
    35 +               unsigned int app_data_len; 
    36 +       } layer7; 
    37 +#endif 
    38 + 
    39         /* Storage reserved for other modules: */ 
    40         union nf_conntrack_proto proto; 
    41   
    421--- a/net/netfilter/Kconfig 
    432+++ b/net/netfilter/Kconfig 
     
    509+       depends on NETFILTER_XTABLES 
    5110+       depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK) 
    52 +       depends on NF_CT_ACCT 
     11+       depends on NETFILTER_ADVANCED 
    5312+       help 
    5413+         Say Y if you want to be able to classify connections (and their 
     
    8039 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o 
    8140 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o 
    82 --- a/net/netfilter/nf_conntrack_core.c 
    83 +++ b/net/netfilter/nf_conntrack_core.c 
    84 @@ -202,6 +202,14 @@ destroy_conntrack(struct nf_conntrack *n 
    85          * too. */ 
    86         nf_ct_remove_expectations(ct); 
    87   
    88 +       #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
    89 +       if(ct->layer7.app_proto) 
    90 +               kfree(ct->layer7.app_proto); 
    91 +       if(ct->layer7.app_data) 
    92 +       kfree(ct->layer7.app_data); 
     41--- /dev/null 
     42+++ b/net/netfilter/xt_layer7.c 
     43@@ -0,0 +1,666 @@ 
     44+/* 
     45+  Kernel module to match application layer (OSI layer 7) data in connections. 
     46+ 
     47+  http://l7-filter.sf.net 
     48+ 
     49+  (C) 2003-2009 Matthew Strait and Ethan Sommer. 
     50+ 
     51+  This program is free software; you can redistribute it and/or 
     52+  modify it under the terms of the GNU General Public License 
     53+  as published by the Free Software Foundation; either version 
     54+  2 of the License, or (at your option) any later version. 
     55+  http://www.gnu.org/licenses/gpl.txt 
     56+ 
     57+  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>, 
     58+  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait, 
     59+  Ethan Sommer, Justin Levandoski. 
     60+*/ 
     61+ 
     62+#include <linux/spinlock.h> 
     63+#include <linux/version.h> 
     64+#include <net/ip.h> 
     65+#include <net/tcp.h> 
     66+#include <linux/module.h> 
     67+#include <linux/skbuff.h> 
     68+#include <linux/netfilter.h> 
     69+#include <net/netfilter/nf_conntrack.h> 
     70+#include <net/netfilter/nf_conntrack_core.h> 
     71+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) 
     72+#include <net/netfilter/nf_conntrack_extend.h> 
     73+#include <net/netfilter/nf_conntrack_acct.h> 
     74+#endif 
     75+#include <linux/netfilter/x_tables.h> 
     76+#include <linux/netfilter/xt_layer7.h> 
     77+#include <linux/ctype.h> 
     78+#include <linux/proc_fs.h> 
     79+ 
     80+#include "regexp/regexp.c" 
     81+ 
     82+MODULE_LICENSE("GPL"); 
     83+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); 
     84+MODULE_DESCRIPTION("iptables application layer match module"); 
     85+MODULE_ALIAS("ipt_layer7"); 
     86+MODULE_VERSION("2.21"); 
     87+ 
     88+static int maxdatalen = 2048; // this is the default 
     89+module_param(maxdatalen, int, 0444); 
     90+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); 
     91+#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG 
     92+       #define DPRINTK(format,args...) printk(format,##args) 
     93+#else 
     94+       #define DPRINTK(format,args...) 
     95+#endif 
     96+ 
     97+/* Number of packets whose data we look at. 
     98+This can be modified through /proc/net/layer7_numpackets */ 
     99+static int num_packets = 10; 
     100+ 
     101+static struct pattern_cache { 
     102+       char * regex_string; 
     103+       regexp * pattern; 
     104+       struct pattern_cache * next; 
     105+} * first_pattern_cache = NULL; 
     106+ 
     107+DEFINE_SPINLOCK(l7_lock); 
     108+ 
     109+static int total_acct_packets(struct nf_conn *ct) 
     110+{ 
     111+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) 
     112+       BUG_ON(ct == NULL); 
     113+       return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets); 
     114+#else 
     115+       struct nf_conn_counter *acct; 
     116+ 
     117+       BUG_ON(ct == NULL); 
     118+       acct = nf_conn_acct_find(ct); 
     119+       if (!acct) 
     120+               return 0; 
     121+       return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets); 
     122+#endif 
     123+} 
     124+ 
     125+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
     126+/* Converts an unfriendly string into a friendly one by 
     127+replacing unprintables with periods and all whitespace with " ". */ 
     128+static char * friendly_print(unsigned char * s) 
     129+{ 
     130+       char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); 
     131+       int i; 
     132+ 
     133+       if(!f) { 
     134+               if (net_ratelimit()) 
     135+                       printk(KERN_ERR "layer7: out of memory in " 
     136+                                       "friendly_print, bailing.\n"); 
     137+               return NULL; 
     138+       } 
     139+ 
     140+       for(i = 0; i < strlen(s); i++){ 
     141+               if(isprint(s[i]) && s[i] < 128) f[i] = s[i]; 
     142+               else if(isspace(s[i]))          f[i] = ' '; 
     143+               else                            f[i] = '.'; 
     144+       } 
     145+       f[i] = '\0'; 
     146+       return f; 
     147+} 
     148+ 
     149+static char dec2hex(int i) 
     150+{ 
     151+       switch (i) { 
     152+               case 0 ... 9: 
     153+                       return (i + '0'); 
     154+                       break; 
     155+               case 10 ... 15: 
     156+                       return (i - 10 + 'a'); 
     157+                       break; 
     158+               default: 
     159+                       if (net_ratelimit()) 
     160+                               printk("layer7: Problem in dec2hex\n"); 
     161+                       return '\0'; 
     162+       } 
     163+} 
     164+ 
     165+static char * hex_print(unsigned char * s) 
     166+{ 
     167+       char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); 
     168+       int i; 
     169+ 
     170+       if(!g) { 
     171+              if (net_ratelimit()) 
     172+                       printk(KERN_ERR "layer7: out of memory in hex_print, " 
     173+                                       "bailing.\n"); 
     174+              return NULL; 
     175+       } 
     176+ 
     177+       for(i = 0; i < strlen(s); i++) { 
     178+               g[i*3    ] = dec2hex(s[i]/16); 
     179+               g[i*3 + 1] = dec2hex(s[i]%16); 
     180+               g[i*3 + 2] = ' '; 
     181+       } 
     182+       g[i*3] = '\0'; 
     183+ 
     184+       return g; 
     185+} 
     186+#endif // DEBUG 
     187+ 
     188+/* Use instead of regcomp.  As we expect to be seeing the same regexps over and 
     189+over again, it make sense to cache the results. */ 
     190+static regexp * compile_and_cache(const char * regex_string,  
     191+                                  const char * protocol) 
     192+{ 
     193+       struct pattern_cache * node               = first_pattern_cache; 
     194+       struct pattern_cache * last_pattern_cache = first_pattern_cache; 
     195+       struct pattern_cache * tmp; 
     196+       unsigned int len; 
     197+ 
     198+       while (node != NULL) { 
     199+               if (!strcmp(node->regex_string, regex_string)) 
     200+               return node->pattern; 
     201+ 
     202+               last_pattern_cache = node;/* points at the last non-NULL node */ 
     203+               node = node->next; 
     204+       } 
     205+ 
     206+       /* If we reach the end of the list, then we have not yet cached 
     207+          the pattern for this regex. Let's do that now. 
     208+          Be paranoid about running out of memory to avoid list corruption. */ 
     209+       tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); 
     210+ 
     211+       if(!tmp) { 
     212+               if (net_ratelimit()) 
     213+                       printk(KERN_ERR "layer7: out of memory in " 
     214+                                       "compile_and_cache, bailing.\n"); 
     215+               return NULL; 
     216+       } 
     217+ 
     218+       tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); 
     219+       tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC); 
     220+       tmp->next = NULL; 
     221+ 
     222+       if(!tmp->regex_string || !tmp->pattern) { 
     223+               if (net_ratelimit()) 
     224+                       printk(KERN_ERR "layer7: out of memory in " 
     225+                                       "compile_and_cache, bailing.\n"); 
     226+               kfree(tmp->regex_string); 
     227+               kfree(tmp->pattern); 
     228+               kfree(tmp); 
     229+               return NULL; 
     230+       } 
     231+ 
     232+       /* Ok.  The new node is all ready now. */ 
     233+       node = tmp; 
     234+ 
     235+       if(first_pattern_cache == NULL) /* list is empty */ 
     236+               first_pattern_cache = node; /* make node the beginning */ 
     237+       else 
     238+               last_pattern_cache->next = node; /* attach node to the end */ 
     239+ 
     240+       /* copy the string and compile the regex */ 
     241+       len = strlen(regex_string); 
     242+       DPRINTK("About to compile this: \"%s\"\n", regex_string); 
     243+       node->pattern = regcomp((char *)regex_string, &len); 
     244+       if ( !node->pattern ) { 
     245+               if (net_ratelimit()) 
     246+                       printk(KERN_ERR "layer7: Error compiling regexp " 
     247+                                       "\"%s\" (%s)\n",  
     248+                                       regex_string, protocol); 
     249+               /* pattern is now cached as NULL, so we won't try again. */ 
     250+       } 
     251+ 
     252+       strcpy(node->regex_string, regex_string); 
     253+       return node->pattern; 
     254+} 
     255+ 
     256+static int can_handle(const struct sk_buff *skb) 
     257+{ 
     258+       if(!ip_hdr(skb)) /* not IP */ 
     259+               return 0; 
     260+       if(ip_hdr(skb)->protocol != IPPROTO_TCP && 
     261+          ip_hdr(skb)->protocol != IPPROTO_UDP && 
     262+          ip_hdr(skb)->protocol != IPPROTO_ICMP) 
     263+               return 0; 
     264+       return 1; 
     265+} 
     266+ 
     267+/* Returns offset the into the skb->data that the application data starts */ 
     268+static int app_data_offset(const struct sk_buff *skb) 
     269+{ 
     270+       /* In case we are ported somewhere (ebtables?) where ip_hdr(skb) 
     271+       isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ 
     272+       int ip_hl = 4*ip_hdr(skb)->ihl; 
     273+ 
     274+       if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { 
     275+               /* 12 == offset into TCP header for the header length field. 
     276+               Can't get this with skb->h.th->doff because the tcphdr 
     277+               struct doesn't get set when routing (this is confirmed to be 
     278+               true in Netfilter as well as QoS.) */ 
     279+               int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); 
     280+ 
     281+               return ip_hl + tcp_hl; 
     282+       } else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) { 
     283+               return ip_hl + 8; /* UDP header is always 8 bytes */ 
     284+       } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { 
     285+               return ip_hl + 8; /* ICMP header is 8 bytes */ 
     286+       } else { 
     287+               if (net_ratelimit()) 
     288+                       printk(KERN_ERR "layer7: tried to handle unknown " 
     289+                                       "protocol!\n"); 
     290+               return ip_hl + 8; /* something reasonable */ 
     291+       } 
     292+} 
     293+ 
     294+/* handles whether there's a match when we aren't appending data anymore */ 
     295+static int match_no_append(struct nf_conn * conntrack,  
     296+                           struct nf_conn * master_conntrack,  
     297+                           enum ip_conntrack_info ctinfo, 
     298+                           enum ip_conntrack_info master_ctinfo, 
     299+                           const struct xt_layer7_info * info) 
     300+{ 
     301+       /* If we're in here, throw the app data away */ 
     302+       if(master_conntrack->layer7.app_data != NULL) { 
     303+ 
     304+       #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
     305+               if(!master_conntrack->layer7.app_proto) { 
     306+                       char * f =  
     307+                         friendly_print(master_conntrack->layer7.app_data); 
     308+                       char * g =  
     309+                         hex_print(master_conntrack->layer7.app_data); 
     310+                       DPRINTK("\nl7-filter gave up after %d bytes " 
     311+                               "(%d packets):\n%s\n", 
     312+                               strlen(f), total_acct_packets(master_conntrack), f); 
     313+                       kfree(f); 
     314+                       DPRINTK("In hex: %s\n", g); 
     315+                       kfree(g); 
     316+               } 
    93317+       #endif 
    94318+ 
    95 + 
    96         /* We overload first tuple to link into unconfirmed list. */ 
    97         if (!nf_ct_is_confirmed(ct)) { 
    98                 BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); 
    99 --- a/net/netfilter/nf_conntrack_standalone.c 
    100 +++ b/net/netfilter/nf_conntrack_standalone.c 
    101 @@ -178,6 +178,12 @@ static int ct_seq_show(struct seq_file * 
    102                 goto release; 
    103  #endif 
    104   
    105 +#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
    106 +       if(ct->layer7.app_proto && 
    107 +           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto)) 
    108 +               return -ENOSPC; 
     319+               kfree(master_conntrack->layer7.app_data); 
     320+               master_conntrack->layer7.app_data = NULL; /* don't free again */ 
     321+       } 
     322+ 
     323+       if(master_conntrack->layer7.app_proto){ 
     324+               /* Here child connections set their .app_proto (for /proc) */ 
     325+               if(!conntrack->layer7.app_proto) { 
     326+                       conntrack->layer7.app_proto =  
     327+                         kmalloc(strlen(master_conntrack->layer7.app_proto)+1,  
     328+                           GFP_ATOMIC); 
     329+                       if(!conntrack->layer7.app_proto){ 
     330+                               if (net_ratelimit()) 
     331+                                       printk(KERN_ERR "layer7: out of memory " 
     332+                                                       "in match_no_append, " 
     333+                                                       "bailing.\n"); 
     334+                               return 1; 
     335+                       } 
     336+                       strcpy(conntrack->layer7.app_proto,  
     337+                               master_conntrack->layer7.app_proto); 
     338+               } 
     339+ 
     340+               return (!strcmp(master_conntrack->layer7.app_proto,  
     341+                               info->protocol)); 
     342+       } 
     343+       else { 
     344+               /* If not classified, set to "unknown" to distinguish from 
     345+               connections that are still being tested. */ 
     346+               master_conntrack->layer7.app_proto =  
     347+                       kmalloc(strlen("unknown")+1, GFP_ATOMIC); 
     348+               if(!master_conntrack->layer7.app_proto){ 
     349+                       if (net_ratelimit()) 
     350+                               printk(KERN_ERR "layer7: out of memory in " 
     351+                                               "match_no_append, bailing.\n"); 
     352+                       return 1; 
     353+               } 
     354+               strcpy(master_conntrack->layer7.app_proto, "unknown"); 
     355+               return 0; 
     356+       } 
     357+} 
     358+ 
     359+/* add the new app data to the conntrack.  Return number of bytes added. */ 
     360+static int add_data(struct nf_conn * master_conntrack, 
     361+                    char * app_data, int appdatalen) 
     362+{ 
     363+       int length = 0, i; 
     364+       int oldlength = master_conntrack->layer7.app_data_len; 
     365+ 
     366+       /* This is a fix for a race condition by Deti Fliegl. However, I'm not  
     367+          clear on whether the race condition exists or whether this really  
     368+          fixes it.  I might just be being dense... Anyway, if it's not really  
     369+          a fix, all it does is waste a very small amount of time. */ 
     370+       if(!master_conntrack->layer7.app_data) return 0; 
     371+ 
     372+       /* Strip nulls. Make everything lower case (our regex lib doesn't 
     373+       do case insensitivity).  Add it to the end of the current data. */ 
     374+       for(i = 0; i < maxdatalen-oldlength-1 && 
     375+                  i < appdatalen; i++) { 
     376+               if(app_data[i] != '\0') { 
     377+                       /* the kernel version of tolower mungs 'upper ascii' */ 
     378+                       master_conntrack->layer7.app_data[length+oldlength] = 
     379+                               isascii(app_data[i])?  
     380+                                       tolower(app_data[i]) : app_data[i]; 
     381+                       length++; 
     382+               } 
     383+       } 
     384+ 
     385+       master_conntrack->layer7.app_data[length+oldlength] = '\0'; 
     386+       master_conntrack->layer7.app_data_len = length + oldlength; 
     387+ 
     388+       return length; 
     389+} 
     390+ 
     391+/* taken from drivers/video/modedb.c */ 
     392+static int my_atoi(const char *s) 
     393+{ 
     394+       int val = 0; 
     395+ 
     396+       for (;; s++) { 
     397+               switch (*s) { 
     398+                       case '0'...'9': 
     399+                       val = 10*val+(*s-'0'); 
     400+                       break; 
     401+               default: 
     402+                       return val; 
     403+               } 
     404+       } 
     405+} 
     406+ 
     407+/* write out num_packets to userland. */ 
     408+static int layer7_read_proc(char* page, char ** start, off_t off, int count, 
     409+                            int* eof, void * data) 
     410+{ 
     411+       if(num_packets > 99 && net_ratelimit()) 
     412+               printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); 
     413+ 
     414+       page[0] = num_packets/10 + '0'; 
     415+       page[1] = num_packets%10 + '0'; 
     416+       page[2] = '\n'; 
     417+       page[3] = '\0'; 
     418+ 
     419+       *eof=1; 
     420+ 
     421+       return 3; 
     422+} 
     423+ 
     424+/* Read in num_packets from userland */ 
     425+static int layer7_write_proc(struct file* file, const char* buffer, 
     426+                             unsigned long count, void *data) 
     427+{ 
     428+       char * foo = kmalloc(count, GFP_ATOMIC); 
     429+ 
     430+       if(!foo){ 
     431+               if (net_ratelimit()) 
     432+                       printk(KERN_ERR "layer7: out of memory, bailing. " 
     433+                                       "num_packets unchanged.\n"); 
     434+               return count; 
     435+       } 
     436+ 
     437+       if(copy_from_user(foo, buffer, count)) { 
     438+               return -EFAULT; 
     439+       } 
     440+ 
     441+ 
     442+       num_packets = my_atoi(foo); 
     443+       kfree (foo); 
     444+ 
     445+       /* This has an arbitrary limit to make the math easier. I'm lazy. 
     446+       But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ 
     447+       if(num_packets > 99) { 
     448+               printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); 
     449+               num_packets = 99; 
     450+       } else if(num_packets < 1) { 
     451+               printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); 
     452+               num_packets = 1; 
     453+       } 
     454+ 
     455+       return count; 
     456+} 
     457+ 
     458+static bool 
     459+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     460+match(const struct sk_buff *skbin, const struct xt_match_param *par) 
     461+#else 
     462+match(const struct sk_buff *skbin, 
     463+      const struct net_device *in, 
     464+      const struct net_device *out, 
     465+      const struct xt_match *match, 
     466+      const void *matchinfo, 
     467+      int offset, 
     468+      unsigned int protoff, 
     469+      bool *hotdrop) 
    109470+#endif 
    110 + 
    111         if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 
    112                 goto release; 
    113   
     471+{ 
     472+       /* sidestep const without getting a compiler warning... */ 
     473+       struct sk_buff * skb = (struct sk_buff *)skbin;  
     474+ 
     475+       const struct xt_layer7_info * info =  
     476+       #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     477+               par->matchinfo; 
     478+       #else 
     479+               matchinfo; 
     480+       #endif 
     481+ 
     482+       enum ip_conntrack_info master_ctinfo, ctinfo; 
     483+       struct nf_conn *master_conntrack, *conntrack; 
     484+       unsigned char * app_data; 
     485+       unsigned int pattern_result, appdatalen; 
     486+       regexp * comppattern; 
     487+ 
     488+       /* Be paranoid/incompetent - lock the entire match function. */ 
     489+       spin_lock_bh(&l7_lock); 
     490+ 
     491+       if(!can_handle(skb)){ 
     492+               DPRINTK("layer7: This is some protocol I can't handle.\n"); 
     493+               spin_unlock_bh(&l7_lock); 
     494+               return info->invert; 
     495+       } 
     496+ 
     497+       /* Treat parent & all its children together as one connection, except 
     498+       for the purpose of setting conntrack->layer7.app_proto in the actual 
     499+       connection. This makes /proc/net/ip_conntrack more satisfying. */ 
     500+       if(!(conntrack = nf_ct_get(skb, &ctinfo)) || 
     501+          !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ 
     502+               DPRINTK("layer7: couldn't get conntrack.\n"); 
     503+               spin_unlock_bh(&l7_lock); 
     504+               return info->invert; 
     505+       } 
     506+ 
     507+       /* Try to get a master conntrack (and its master etc) for FTP, etc. */ 
     508+       while (master_ct(master_conntrack) != NULL) 
     509+               master_conntrack = master_ct(master_conntrack); 
     510+ 
     511+       /* if we've classified it or seen too many packets */ 
     512+       if(total_acct_packets(master_conntrack) > num_packets || 
     513+          master_conntrack->layer7.app_proto) { 
     514+ 
     515+               pattern_result = match_no_append(conntrack, master_conntrack,  
     516+                                                ctinfo, master_ctinfo, info); 
     517+ 
     518+               /* skb->cb[0] == seen. Don't do things twice if there are  
     519+               multiple l7 rules. I'm not sure that using cb for this purpose  
     520+               is correct, even though it says "put your private variables  
     521+               there". But it doesn't look like it is being used for anything 
     522+               else in the skbs that make it here. */ 
     523+               skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ 
     524+ 
     525+               spin_unlock_bh(&l7_lock); 
     526+               return (pattern_result ^ info->invert); 
     527+       } 
     528+ 
     529+       if(skb_is_nonlinear(skb)){ 
     530+               if(skb_linearize(skb) != 0){ 
     531+                       if (net_ratelimit()) 
     532+                               printk(KERN_ERR "layer7: failed to linearize " 
     533+                                               "packet, bailing.\n"); 
     534+                       spin_unlock_bh(&l7_lock); 
     535+                       return info->invert; 
     536+               } 
     537+       } 
     538+ 
     539+       /* now that the skb is linearized, it's safe to set these. */ 
     540+       app_data = skb->data + app_data_offset(skb); 
     541+       appdatalen = skb_tail_pointer(skb) - app_data; 
     542+ 
     543+       /* the return value gets checked later, when we're ready to use it */ 
     544+       comppattern = compile_and_cache(info->pattern, info->protocol); 
     545+ 
     546+       /* On the first packet of a connection, allocate space for app data */ 
     547+       if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&  
     548+          !master_conntrack->layer7.app_data){ 
     549+               master_conntrack->layer7.app_data =  
     550+                       kmalloc(maxdatalen, GFP_ATOMIC); 
     551+               if(!master_conntrack->layer7.app_data){ 
     552+                       if (net_ratelimit()) 
     553+                               printk(KERN_ERR "layer7: out of memory in " 
     554+                                               "match, bailing.\n"); 
     555+                       spin_unlock_bh(&l7_lock); 
     556+                       return info->invert; 
     557+               } 
     558+ 
     559+               master_conntrack->layer7.app_data[0] = '\0'; 
     560+       } 
     561+ 
     562+       /* Can be here, but unallocated, if numpackets is increased near 
     563+       the beginning of a connection */ 
     564+       if(master_conntrack->layer7.app_data == NULL){ 
     565+               spin_unlock_bh(&l7_lock); 
     566+               return info->invert; /* unmatched */ 
     567+       } 
     568+ 
     569+       if(!skb->cb[0]){ 
     570+               int newbytes; 
     571+               newbytes = add_data(master_conntrack, app_data, appdatalen); 
     572+ 
     573+               if(newbytes == 0) { /* didn't add any data */ 
     574+                       skb->cb[0] = 1; 
     575+                       /* Didn't match before, not going to match now */ 
     576+                       spin_unlock_bh(&l7_lock); 
     577+                       return info->invert; 
     578+               } 
     579+       } 
     580+ 
     581+       /* If looking for "unknown", then never match.  "Unknown" means that 
     582+       we've given up; we're still trying with these packets. */ 
     583+       if(!strcmp(info->protocol, "unknown")) { 
     584+               pattern_result = 0; 
     585+       /* If looking for "unset", then always match. "Unset" means that we 
     586+       haven't yet classified the connection. */ 
     587+       } else if(!strcmp(info->protocol, "unset")) { 
     588+               pattern_result = 2; 
     589+               DPRINTK("layer7: matched unset: not yet classified " 
     590+                       "(%d/%d packets)\n", 
     591+                        total_acct_packets(master_conntrack), num_packets); 
     592+       /* If the regexp failed to compile, don't bother running it */ 
     593+       } else if(comppattern &&  
     594+                 regexec(comppattern, master_conntrack->layer7.app_data)){ 
     595+               DPRINTK("layer7: matched %s\n", info->protocol); 
     596+               pattern_result = 1; 
     597+       } else pattern_result = 0; 
     598+ 
     599+       if(pattern_result == 1) { 
     600+               master_conntrack->layer7.app_proto =  
     601+                       kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); 
     602+               if(!master_conntrack->layer7.app_proto){ 
     603+                       if (net_ratelimit()) 
     604+                               printk(KERN_ERR "layer7: out of memory in " 
     605+                                               "match, bailing.\n"); 
     606+                       spin_unlock_bh(&l7_lock); 
     607+                       return (pattern_result ^ info->invert); 
     608+               } 
     609+               strcpy(master_conntrack->layer7.app_proto, info->protocol); 
     610+       } else if(pattern_result > 1) { /* cleanup from "unset" */ 
     611+               pattern_result = 1; 
     612+       } 
     613+ 
     614+       /* mark the packet seen */ 
     615+       skb->cb[0] = 1; 
     616+ 
     617+       spin_unlock_bh(&l7_lock); 
     618+       return (pattern_result ^ info->invert); 
     619+} 
     620+ 
     621+// load nf_conntrack_ipv4 
     622+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     623+static bool check(const struct xt_mtchk_param *par) 
     624+{ 
     625+        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { 
     626+                printk(KERN_WARNING "can't load conntrack support for " 
     627+                                    "proto=%d\n", par->match->family); 
     628+#else 
     629+static bool check(const char *tablename, const void *inf, 
     630+                const struct xt_match *match, void *matchinfo, 
     631+                unsigned int hook_mask) 
     632+{ 
     633+        if (nf_ct_l3proto_try_module_get(match->family) < 0) { 
     634+                printk(KERN_WARNING "can't load conntrack support for " 
     635+                                    "proto=%d\n", match->family); 
     636+#endif 
     637+                return 0; 
     638+        } 
     639+       return 1; 
     640+} 
     641+ 
     642+ 
     643+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     644+       static void destroy(const struct xt_mtdtor_param *par) 
     645+       { 
     646+               nf_ct_l3proto_module_put(par->match->family); 
     647+       } 
     648+#else 
     649+       static void destroy(const struct xt_match *match, void *matchinfo) 
     650+       { 
     651+               nf_ct_l3proto_module_put(match->family); 
     652+       } 
     653+#endif 
     654+ 
     655+static struct xt_match xt_layer7_match[] __read_mostly = { 
     656+{ 
     657+       .name           = "layer7", 
     658+       .family         = AF_INET, 
     659+       .checkentry     = check, 
     660+       .match          = match, 
     661+       .destroy        = destroy, 
     662+       .matchsize      = sizeof(struct xt_layer7_info), 
     663+       .me             = THIS_MODULE 
     664+} 
     665+}; 
     666+ 
     667+static void layer7_cleanup_proc(void) 
     668+{ 
     669+       remove_proc_entry("layer7_numpackets", init_net.proc_net); 
     670+} 
     671+ 
     672+/* register the proc file */ 
     673+static void layer7_init_proc(void) 
     674+{ 
     675+       struct proc_dir_entry* entry; 
     676+       entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net); 
     677+       entry->read_proc = layer7_read_proc; 
     678+       entry->write_proc = layer7_write_proc; 
     679+} 
     680+ 
     681+static int __init xt_layer7_init(void) 
     682+{ 
     683+       need_conntrack(); 
     684+ 
     685+       layer7_init_proc(); 
     686+       if(maxdatalen < 1) { 
     687+               printk(KERN_WARNING "layer7: maxdatalen can't be < 1, " 
     688+                       "using 1\n"); 
     689+               maxdatalen = 1; 
     690+       } 
     691+       /* This is not a hard limit.  It's just here to prevent people from 
     692+       bringing their slow machines to a grinding halt. */ 
     693+       else if(maxdatalen > 65536) { 
     694+               printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, " 
     695+                       "using 65536\n"); 
     696+               maxdatalen = 65536; 
     697+       } 
     698+       return xt_register_matches(xt_layer7_match, 
     699+                                  ARRAY_SIZE(xt_layer7_match)); 
     700+} 
     701+ 
     702+static void __exit xt_layer7_fini(void) 
     703+{ 
     704+       layer7_cleanup_proc(); 
     705+       xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match)); 
     706+} 
     707+ 
     708+module_init(xt_layer7_init); 
     709+module_exit(xt_layer7_fini); 
    114710--- /dev/null 
    115711+++ b/net/netfilter/regexp/regexp.c 
     
    14622058+       *dst++ = '\0'; 
    14632059+} 
     2060--- a/net/netfilter/nf_conntrack_core.c 
     2061+++ b/net/netfilter/nf_conntrack_core.c 
     2062@@ -202,6 +202,14 @@ destroy_conntrack(struct nf_conntrack *n 
     2063         * too. */ 
     2064        nf_ct_remove_expectations(ct); 
     2065  
     2066+       #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     2067+       if(ct->layer7.app_proto) 
     2068+               kfree(ct->layer7.app_proto); 
     2069+       if(ct->layer7.app_data) 
     2070+       kfree(ct->layer7.app_data); 
     2071+       #endif 
     2072+ 
     2073+ 
     2074        /* We overload first tuple to link into unconfirmed list. */ 
     2075        if (!nf_ct_is_confirmed(ct)) { 
     2076                BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); 
     2077--- a/net/netfilter/nf_conntrack_standalone.c 
     2078+++ b/net/netfilter/nf_conntrack_standalone.c 
     2079@@ -178,6 +178,12 @@ static int ct_seq_show(struct seq_file * 
     2080                goto release; 
     2081 #endif 
     2082  
     2083+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     2084+       if(ct->layer7.app_proto && 
     2085+           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto)) 
     2086+               return -ENOSPC; 
     2087+#endif 
     2088+ 
     2089        if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 
     2090                goto release; 
     2091  
     2092--- a/include/net/netfilter/nf_conntrack.h 
     2093+++ b/include/net/netfilter/nf_conntrack.h 
     2094@@ -116,6 +116,22 @@ struct nf_conn { 
     2095        u_int32_t secmark; 
     2096 #endif 
     2097  
     2098+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \ 
     2099+    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     2100+       struct { 
     2101+               /* 
     2102+                * e.g. "http". NULL before decision. "unknown" after decision 
     2103+                * if no match. 
     2104+                */ 
     2105+               char *app_proto; 
     2106+               /* 
     2107+                * application layer data so far. NULL after match decision. 
     2108+                */ 
     2109+               char *app_data; 
     2110+               unsigned int app_data_len; 
     2111+       } layer7; 
     2112+#endif 
     2113+ 
     2114        /* Storage reserved for other modules: */ 
     2115        union nf_conntrack_proto proto; 
     2116  
    14642117--- /dev/null 
    1465 +++ b/net/netfilter/xt_layer7.c 
    1466 @@ -0,0 +1,666 @@ 
    1467 +/* 
    1468 +  Kernel module to match application layer (OSI layer 7) data in connections. 
    1469 + 
    1470 +  http://l7-filter.sf.net 
    1471 + 
    1472 +  (C) 2003-2009 Matthew Strait and Ethan Sommer. 
    1473 + 
    1474 +  This program is free software; you can redistribute it and/or 
    1475 +  modify it under the terms of the GNU General Public License 
    1476 +  as published by the Free Software Foundation; either version 
    1477 +  2 of the License, or (at your option) any later version. 
    1478 +  http://www.gnu.org/licenses/gpl.txt 
    1479 + 
    1480 +  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>, 
    1481 +  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait, 
    1482 +  Ethan Sommer, Justin Levandoski. 
    1483 +*/ 
    1484 + 
    1485 +#include <linux/spinlock.h> 
    1486 +#include <linux/version.h> 
    1487 +#include <net/ip.h> 
    1488 +#include <net/tcp.h> 
    1489 +#include <linux/module.h> 
    1490 +#include <linux/skbuff.h> 
    1491 +#include <linux/netfilter.h> 
    1492 +#include <net/netfilter/nf_conntrack.h> 
    1493 +#include <net/netfilter/nf_conntrack_core.h> 
    1494 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) 
    1495 +#include <net/netfilter/nf_conntrack_extend.h> 
    1496 +#include <net/netfilter/nf_conntrack_acct.h> 
    1497 +#endif 
    1498 +#include <linux/netfilter/x_tables.h> 
    1499 +#include <linux/netfilter/xt_layer7.h> 
    1500 +#include <linux/ctype.h> 
    1501 +#include <linux/proc_fs.h> 
    1502 + 
    1503 +#include "regexp/regexp.c" 
    1504 + 
    1505 +MODULE_LICENSE("GPL"); 
    1506 +MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); 
    1507 +MODULE_DESCRIPTION("iptables application layer match module"); 
    1508 +MODULE_ALIAS("ipt_layer7"); 
    1509 +MODULE_VERSION("2.21"); 
    1510 + 
    1511 +static int maxdatalen = 2048; // this is the default 
    1512 +module_param(maxdatalen, int, 0444); 
    1513 +MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); 
    1514 +#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG 
    1515 +       #define DPRINTK(format,args...) printk(format,##args) 
    1516 +#else 
    1517 +       #define DPRINTK(format,args...) 
    1518 +#endif 
    1519 + 
    1520 +/* Number of packets whose data we look at. 
    1521 +This can be modified through /proc/net/layer7_numpackets */ 
    1522 +static int num_packets = 10; 
    1523 + 
    1524 +static struct pattern_cache { 
    1525 +       char * regex_string; 
    1526 +       regexp * pattern; 
    1527 +       struct pattern_cache * next; 
    1528 +} * first_pattern_cache = NULL; 
    1529 + 
    1530 +DEFINE_SPINLOCK(l7_lock); 
    1531 + 
    1532 +static int total_acct_packets(struct nf_conn *ct) 
    1533 +{ 
    1534 +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) 
    1535 +       BUG_ON(ct == NULL); 
    1536 +       return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets); 
    1537 +#else 
    1538 +       struct nf_conn_counter *acct; 
    1539 + 
    1540 +       BUG_ON(ct == NULL); 
    1541 +       acct = nf_conn_acct_find(ct); 
    1542 +       if (!acct) 
    1543 +               return 0; 
    1544 +       return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets); 
    1545 +#endif 
    1546 +} 
    1547 + 
    1548 +#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
    1549 +/* Converts an unfriendly string into a friendly one by 
    1550 +replacing unprintables with periods and all whitespace with " ". */ 
    1551 +static char * friendly_print(unsigned char * s) 
    1552 +{ 
    1553 +       char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); 
    1554 +       int i; 
    1555 + 
    1556 +       if(!f) { 
    1557 +               if (net_ratelimit()) 
    1558 +                       printk(KERN_ERR "layer7: out of memory in " 
    1559 +                                       "friendly_print, bailing.\n"); 
    1560 +               return NULL; 
    1561 +       } 
    1562 + 
    1563 +       for(i = 0; i < strlen(s); i++){ 
    1564 +               if(isprint(s[i]) && s[i] < 128) f[i] = s[i]; 
    1565 +               else if(isspace(s[i]))          f[i] = ' '; 
    1566 +               else                            f[i] = '.'; 
    1567 +       } 
    1568 +       f[i] = '\0'; 
    1569 +       return f; 
    1570 +} 
    1571 + 
    1572 +static char dec2hex(int i) 
    1573 +{ 
    1574 +       switch (i) { 
    1575 +               case 0 ... 9: 
    1576 +                       return (i + '0'); 
    1577 +                       break; 
    1578 +               case 10 ... 15: 
    1579 +                       return (i - 10 + 'a'); 
    1580 +                       break; 
    1581 +               default: 
    1582 +                       if (net_ratelimit()) 
    1583 +                               printk("layer7: Problem in dec2hex\n"); 
    1584 +                       return '\0'; 
    1585 +       } 
    1586 +} 
    1587 + 
    1588 +static char * hex_print(unsigned char * s) 
    1589 +{ 
    1590 +       char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); 
    1591 +       int i; 
    1592 + 
    1593 +       if(!g) { 
    1594 +              if (net_ratelimit()) 
    1595 +                       printk(KERN_ERR "layer7: out of memory in hex_print, " 
    1596 +                                       "bailing.\n"); 
    1597 +              return NULL; 
    1598 +       } 
    1599 + 
    1600 +       for(i = 0; i < strlen(s); i++) { 
    1601 +               g[i*3    ] = dec2hex(s[i]/16); 
    1602 +               g[i*3 + 1] = dec2hex(s[i]%16); 
    1603 +               g[i*3 + 2] = ' '; 
    1604 +       } 
    1605 +       g[i*3] = '\0'; 
    1606 + 
    1607 +       return g; 
    1608 +} 
    1609 +#endif // DEBUG 
    1610 + 
    1611 +/* Use instead of regcomp.  As we expect to be seeing the same regexps over and 
    1612 +over again, it make sense to cache the results. */ 
    1613 +static regexp * compile_and_cache(const char * regex_string,  
    1614 +                                  const char * protocol) 
    1615 +{ 
    1616 +       struct pattern_cache * node               = first_pattern_cache; 
    1617 +       struct pattern_cache * last_pattern_cache = first_pattern_cache; 
    1618 +       struct pattern_cache * tmp; 
    1619 +       unsigned int len; 
    1620 + 
    1621 +       while (node != NULL) { 
    1622 +               if (!strcmp(node->regex_string, regex_string)) 
    1623 +               return node->pattern; 
    1624 + 
    1625 +               last_pattern_cache = node;/* points at the last non-NULL node */ 
    1626 +               node = node->next; 
    1627 +       } 
    1628 + 
    1629 +       /* If we reach the end of the list, then we have not yet cached 
    1630 +          the pattern for this regex. Let's do that now. 
    1631 +          Be paranoid about running out of memory to avoid list corruption. */ 
    1632 +       tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); 
    1633 + 
    1634 +       if(!tmp) { 
    1635 +               if (net_ratelimit()) 
    1636 +                       printk(KERN_ERR "layer7: out of memory in " 
    1637 +                                       "compile_and_cache, bailing.\n"); 
    1638 +               return NULL; 
    1639 +       } 
    1640 + 
    1641 +       tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); 
    1642 +       tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC); 
    1643 +       tmp->next = NULL; 
    1644 + 
    1645 +       if(!tmp->regex_string || !tmp->pattern) { 
    1646 +               if (net_ratelimit()) 
    1647 +                       printk(KERN_ERR "layer7: out of memory in " 
    1648 +                                       "compile_and_cache, bailing.\n"); 
    1649 +               kfree(tmp->regex_string); 
    1650 +               kfree(tmp->pattern); 
    1651 +               kfree(tmp); 
    1652 +               return NULL; 
    1653 +       } 
    1654 + 
    1655 +       /* Ok.  The new node is all ready now. */ 
    1656 +       node = tmp; 
    1657 + 
    1658 +       if(first_pattern_cache == NULL) /* list is empty */ 
    1659 +               first_pattern_cache = node; /* make node the beginning */ 
    1660 +       else 
    1661 +               last_pattern_cache->next = node; /* attach node to the end */ 
    1662 + 
    1663 +       /* copy the string and compile the regex */ 
    1664 +       len = strlen(regex_string); 
    1665 +       DPRINTK("About to compile this: \"%s\"\n", regex_string); 
    1666 +       node->pattern = regcomp((char *)regex_string, &len); 
    1667 +       if ( !node->pattern ) { 
    1668 +               if (net_ratelimit()) 
    1669 +                       printk(KERN_ERR "layer7: Error compiling regexp " 
    1670 +                                       "\"%s\" (%s)\n",  
    1671 +                                       regex_string, protocol); 
    1672 +               /* pattern is now cached as NULL, so we won't try again. */ 
    1673 +       } 
    1674 + 
    1675 +       strcpy(node->regex_string, regex_string); 
    1676 +       return node->pattern; 
    1677 +} 
    1678 + 
    1679 +static int can_handle(const struct sk_buff *skb) 
    1680 +{ 
    1681 +       if(!ip_hdr(skb)) /* not IP */ 
    1682 +               return 0; 
    1683 +       if(ip_hdr(skb)->protocol != IPPROTO_TCP && 
    1684 +          ip_hdr(skb)->protocol != IPPROTO_UDP && 
    1685 +          ip_hdr(skb)->protocol != IPPROTO_ICMP) 
    1686 +               return 0; 
    1687 +       return 1; 
    1688 +} 
    1689 + 
    1690 +/* Returns offset the into the skb->data that the application data starts */ 
    1691 +static int app_data_offset(const struct sk_buff *skb) 
    1692 +{ 
    1693 +       /* In case we are ported somewhere (ebtables?) where ip_hdr(skb) 
    1694 +       isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ 
    1695 +       int ip_hl = 4*ip_hdr(skb)->ihl; 
    1696 + 
    1697 +       if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { 
    1698 +               /* 12 == offset into TCP header for the header length field. 
    1699 +               Can't get this with skb->h.th->doff because the tcphdr 
    1700 +               struct doesn't get set when routing (this is confirmed to be 
    1701 +               true in Netfilter as well as QoS.) */ 
    1702 +               int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); 
    1703 + 
    1704 +               return ip_hl + tcp_hl; 
    1705 +       } else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) { 
    1706 +               return ip_hl + 8; /* UDP header is always 8 bytes */ 
    1707 +       } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { 
    1708 +               return ip_hl + 8; /* ICMP header is 8 bytes */ 
    1709 +       } else { 
    1710 +               if (net_ratelimit()) 
    1711 +                       printk(KERN_ERR "layer7: tried to handle unknown " 
    1712 +                                       "protocol!\n"); 
    1713 +               return ip_hl + 8; /* something reasonable */ 
    1714 +       } 
    1715 +} 
    1716 + 
    1717 +/* handles whether there's a match when we aren't appending data anymore */ 
    1718 +static int match_no_append(struct nf_conn * conntrack,  
    1719 +                           struct nf_conn * master_conntrack,  
    1720 +                           enum ip_conntrack_info ctinfo, 
    1721 +                           enum ip_conntrack_info master_ctinfo, 
    1722 +                           const struct xt_layer7_info * info) 
    1723 +{ 
    1724 +       /* If we're in here, throw the app data away */ 
    1725 +       if(master_conntrack->layer7.app_data != NULL) { 
    1726 + 
    1727 +       #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
    1728 +               if(!master_conntrack->layer7.app_proto) { 
    1729 +                       char * f =  
    1730 +                         friendly_print(master_conntrack->layer7.app_data); 
    1731 +                       char * g =  
    1732 +                         hex_print(master_conntrack->layer7.app_data); 
    1733 +                       DPRINTK("\nl7-filter gave up after %d bytes " 
    1734 +                               "(%d packets):\n%s\n", 
    1735 +                               strlen(f), total_acct_packets(master_conntrack), f); 
    1736 +                       kfree(f); 
    1737 +                       DPRINTK("In hex: %s\n", g); 
    1738 +                       kfree(g); 
    1739 +               } 
    1740 +       #endif 
    1741 + 
    1742 +               kfree(master_conntrack->layer7.app_data); 
    1743 +               master_conntrack->layer7.app_data = NULL; /* don't free again */ 
    1744 +       } 
    1745 + 
    1746 +       if(master_conntrack->layer7.app_proto){ 
    1747 +               /* Here child connections set their .app_proto (for /proc) */ 
    1748 +               if(!conntrack->layer7.app_proto) { 
    1749 +                       conntrack->layer7.app_proto =  
    1750 +                         kmalloc(strlen(master_conntrack->layer7.app_proto)+1,  
    1751 +                           GFP_ATOMIC); 
    1752 +                       if(!conntrack->layer7.app_proto){ 
    1753 +                               if (net_ratelimit()) 
    1754 +                                       printk(KERN_ERR "layer7: out of memory " 
    1755 +                                                       "in match_no_append, " 
    1756 +                                                       "bailing.\n"); 
    1757 +                               return 1; 
    1758 +                       } 
    1759 +                       strcpy(conntrack->layer7.app_proto,  
    1760 +                               master_conntrack->layer7.app_proto); 
    1761 +               } 
    1762 + 
    1763 +               return (!strcmp(master_conntrack->layer7.app_proto,  
    1764 +                               info->protocol)); 
    1765 +       } 
    1766 +       else { 
    1767 +               /* If not classified, set to "unknown" to distinguish from 
    1768 +               connections that are still being tested. */ 
    1769 +               master_conntrack->layer7.app_proto =  
    1770 +                       kmalloc(strlen("unknown")+1, GFP_ATOMIC); 
    1771 +               if(!master_conntrack->layer7.app_proto){ 
    1772 +                       if (net_ratelimit()) 
    1773 +                               printk(KERN_ERR "layer7: out of memory in " 
    1774 +                                               "match_no_append, bailing.\n"); 
    1775 +                       return 1; 
    1776 +               } 
    1777 +               strcpy(master_conntrack->layer7.app_proto, "unknown"); 
    1778 +               return 0; 
    1779 +       } 
    1780 +} 
    1781 + 
    1782 +/* add the new app data to the conntrack.  Return number of bytes added. */ 
    1783 +static int add_data(struct nf_conn * master_conntrack, 
    1784 +                    char * app_data, int appdatalen) 
    1785 +{ 
    1786 +       int length = 0, i; 
    1787 +       int oldlength = master_conntrack->layer7.app_data_len; 
    1788 + 
    1789 +       /* This is a fix for a race condition by Deti Fliegl. However, I'm not  
    1790 +          clear on whether the race condition exists or whether this really  
    1791 +          fixes it.  I might just be being dense... Anyway, if it's not really  
    1792 +          a fix, all it does is waste a very small amount of time. */ 
    1793 +       if(!master_conntrack->layer7.app_data) return 0; 
    1794 + 
    1795 +       /* Strip nulls. Make everything lower case (our regex lib doesn't 
    1796 +       do case insensitivity).  Add it to the end of the current data. */ 
    1797 +       for(i = 0; i < maxdatalen-oldlength-1 && 
    1798 +                  i < appdatalen; i++) { 
    1799 +               if(app_data[i] != '\0') { 
    1800 +                       /* the kernel version of tolower mungs 'upper ascii' */ 
    1801 +                       master_conntrack->layer7.app_data[length+oldlength] = 
    1802 +                               isascii(app_data[i])?  
    1803 +                                       tolower(app_data[i]) : app_data[i]; 
    1804 +                       length++; 
    1805 +               } 
    1806 +       } 
    1807 + 
    1808 +       master_conntrack->layer7.app_data[length+oldlength] = '\0'; 
    1809 +       master_conntrack->layer7.app_data_len = length + oldlength; 
    1810 + 
    1811 +       return length; 
    1812 +} 
    1813 + 
    1814 +/* taken from drivers/video/modedb.c */ 
    1815 +static int my_atoi(const char *s) 
    1816 +{ 
    1817 +       int val = 0; 
    1818 + 
    1819 +       for (;; s++) { 
    1820 +               switch (*s) { 
    1821 +                       case '0'...'9': 
    1822 +                       val = 10*val+(*s-'0'); 
    1823 +                       break; 
    1824 +               default: 
    1825 +                       return val; 
    1826 +               } 
    1827 +       } 
    1828 +} 
    1829 + 
    1830 +/* write out num_packets to userland. */ 
    1831 +static int layer7_read_proc(char* page, char ** start, off_t off, int count, 
    1832 +                            int* eof, void * data) 
    1833 +{ 
    1834 +       if(num_packets > 99 && net_ratelimit()) 
    1835 +               printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); 
    1836 + 
    1837 +       page[0] = num_packets/10 + '0'; 
    1838 +       page[1] = num_packets%10 + '0'; 
    1839 +       page[2] = '\n'; 
    1840 +       page[3] = '\0'; 
    1841 + 
    1842 +       *eof=1; 
    1843 + 
    1844 +       return 3; 
    1845 +} 
    1846 + 
    1847 +/* Read in num_packets from userland */ 
    1848 +static int layer7_write_proc(struct file* file, const char* buffer, 
    1849 +                             unsigned long count, void *data) 
    1850 +{ 
    1851 +       char * foo = kmalloc(count, GFP_ATOMIC); 
    1852 + 
    1853 +       if(!foo){ 
    1854 +               if (net_ratelimit()) 
    1855 +                       printk(KERN_ERR "layer7: out of memory, bailing. " 
    1856 +                                       "num_packets unchanged.\n"); 
    1857 +               return count; 
    1858 +       } 
    1859 + 
    1860 +       if(copy_from_user(foo, buffer, count)) { 
    1861 +               return -EFAULT; 
    1862 +       } 
    1863 + 
    1864 + 
    1865 +       num_packets = my_atoi(foo); 
    1866 +       kfree (foo); 
    1867 + 
    1868 +       /* This has an arbitrary limit to make the math easier. I'm lazy. 
    1869 +       But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ 
    1870 +       if(num_packets > 99) { 
    1871 +               printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); 
    1872 +               num_packets = 99; 
    1873 +       } else if(num_packets < 1) { 
    1874 +               printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); 
    1875 +               num_packets = 1; 
    1876 +       } 
    1877 + 
    1878 +       return count; 
    1879 +} 
    1880 + 
    1881 +static bool 
    1882 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    1883 +match(const struct sk_buff *skbin, const struct xt_match_param *par) 
    1884 +#else 
    1885 +match(const struct sk_buff *skbin, 
    1886 +      const struct net_device *in, 
    1887 +      const struct net_device *out, 
    1888 +      const struct xt_match *match, 
    1889 +      const void *matchinfo, 
    1890 +      int offset, 
    1891 +      unsigned int protoff, 
    1892 +      bool *hotdrop) 
    1893 +#endif 
    1894 +{ 
    1895 +       /* sidestep const without getting a compiler warning... */ 
    1896 +       struct sk_buff * skb = (struct sk_buff *)skbin;  
    1897 + 
    1898 +       const struct xt_layer7_info * info =  
    1899 +       #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    1900 +               par->matchinfo; 
    1901 +       #else 
    1902 +               matchinfo; 
    1903 +       #endif 
    1904 + 
    1905 +       enum ip_conntrack_info master_ctinfo, ctinfo; 
    1906 +       struct nf_conn *master_conntrack, *conntrack; 
    1907 +       unsigned char * app_data; 
    1908 +       unsigned int pattern_result, appdatalen; 
    1909 +       regexp * comppattern; 
    1910 + 
    1911 +       /* Be paranoid/incompetent - lock the entire match function. */ 
    1912 +       spin_lock_bh(&l7_lock); 
    1913 + 
    1914 +       if(!can_handle(skb)){ 
    1915 +               DPRINTK("layer7: This is some protocol I can't handle.\n"); 
    1916 +               spin_unlock_bh(&l7_lock); 
    1917 +               return info->invert; 
    1918 +       } 
    1919 + 
    1920 +       /* Treat parent & all its children together as one connection, except 
    1921 +       for the purpose of setting conntrack->layer7.app_proto in the actual 
    1922 +       connection. This makes /proc/net/ip_conntrack more satisfying. */ 
    1923 +       if(!(conntrack = nf_ct_get(skb, &ctinfo)) || 
    1924 +          !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ 
    1925 +               DPRINTK("layer7: couldn't get conntrack.\n"); 
    1926 +               spin_unlock_bh(&l7_lock); 
    1927 +               return info->invert; 
    1928 +       } 
    1929 + 
    1930 +       /* Try to get a master conntrack (and its master etc) for FTP, etc. */ 
    1931 +       while (master_ct(master_conntrack) != NULL) 
    1932 +               master_conntrack = master_ct(master_conntrack); 
    1933 + 
    1934 +       /* if we've classified it or seen too many packets */ 
    1935 +       if(total_acct_packets(master_conntrack) > num_packets || 
    1936 +          master_conntrack->layer7.app_proto) { 
    1937 + 
    1938 +               pattern_result = match_no_append(conntrack, master_conntrack,  
    1939 +                                                ctinfo, master_ctinfo, info); 
    1940 + 
    1941 +               /* skb->cb[0] == seen. Don't do things twice if there are  
    1942 +               multiple l7 rules. I'm not sure that using cb for this purpose  
    1943 +               is correct, even though it says "put your private variables  
    1944 +               there". But it doesn't look like it is being used for anything 
    1945 +               else in the skbs that make it here. */ 
    1946 +               skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ 
    1947 + 
    1948 +               spin_unlock_bh(&l7_lock); 
    1949 +               return (pattern_result ^ info->invert); 
    1950 +       } 
    1951 + 
    1952 +       if(skb_is_nonlinear(skb)){ 
    1953 +               if(skb_linearize(skb) != 0){ 
    1954 +                       if (net_ratelimit()) 
    1955 +                               printk(KERN_ERR "layer7: failed to linearize " 
    1956 +                                               "packet, bailing.\n"); 
    1957 +                       spin_unlock_bh(&l7_lock); 
    1958 +                       return info->invert; 
    1959 +               } 
    1960 +       } 
    1961 + 
    1962 +       /* now that the skb is linearized, it's safe to set these. */ 
    1963 +       app_data = skb->data + app_data_offset(skb); 
    1964 +       appdatalen = skb_tail_pointer(skb) - app_data; 
    1965 + 
    1966 +       /* the return value gets checked later, when we're ready to use it */ 
    1967 +       comppattern = compile_and_cache(info->pattern, info->protocol); 
    1968 + 
    1969 +       /* On the first packet of a connection, allocate space for app data */ 
    1970 +       if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&  
    1971 +          !master_conntrack->layer7.app_data){ 
    1972 +               master_conntrack->layer7.app_data =  
    1973 +                       kmalloc(maxdatalen, GFP_ATOMIC); 
    1974 +               if(!master_conntrack->layer7.app_data){ 
    1975 +                       if (net_ratelimit()) 
    1976 +                               printk(KERN_ERR "layer7: out of memory in " 
    1977 +                                               "match, bailing.\n"); 
    1978 +                       spin_unlock_bh(&l7_lock); 
    1979 +                       return info->invert; 
    1980 +               } 
    1981 + 
    1982 +               master_conntrack->layer7.app_data[0] = '\0'; 
    1983 +       } 
    1984 + 
    1985 +       /* Can be here, but unallocated, if numpackets is increased near 
    1986 +       the beginning of a connection */ 
    1987 +       if(master_conntrack->layer7.app_data == NULL){ 
    1988 +               spin_unlock_bh(&l7_lock); 
    1989 +               return info->invert; /* unmatched */ 
    1990 +       } 
    1991 + 
    1992 +       if(!skb->cb[0]){ 
    1993 +               int newbytes; 
    1994 +               newbytes = add_data(master_conntrack, app_data, appdatalen); 
    1995 + 
    1996 +               if(newbytes == 0) { /* didn't add any data */ 
    1997 +                       skb->cb[0] = 1; 
    1998 +                       /* Didn't match before, not going to match now */ 
    1999 +                       spin_unlock_bh(&l7_lock); 
    2000 +                       return info->invert; 
    2001 +               } 
    2002 +       } 
    2003 + 
    2004 +       /* If looking for "unknown", then never match.  "Unknown" means that 
    2005 +       we've given up; we're still trying with these packets. */ 
    2006 +       if(!strcmp(info->protocol, "unknown")) { 
    2007 +               pattern_result = 0; 
    2008 +       /* If looking for "unset", then always match. "Unset" means that we 
    2009 +       haven't yet classified the connection. */ 
    2010 +       } else if(!strcmp(info->protocol, "unset")) { 
    2011 +               pattern_result = 2; 
    2012 +               DPRINTK("layer7: matched unset: not yet classified " 
    2013 +                       "(%d/%d packets)\n", 
    2014 +                        total_acct_packets(master_conntrack), num_packets); 
    2015 +       /* If the regexp failed to compile, don't bother running it */ 
    2016 +       } else if(comppattern &&  
    2017 +                 regexec(comppattern, master_conntrack->layer7.app_data)){ 
    2018 +               DPRINTK("layer7: matched %s\n", info->protocol); 
    2019 +               pattern_result = 1; 
    2020 +       } else pattern_result = 0; 
    2021 + 
    2022 +       if(pattern_result == 1) { 
    2023 +               master_conntrack->layer7.app_proto =  
    2024 +                       kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); 
    2025 +               if(!master_conntrack->layer7.app_proto){ 
    2026 +                       if (net_ratelimit()) 
    2027 +                               printk(KERN_ERR "layer7: out of memory in " 
    2028 +                                               "match, bailing.\n"); 
    2029 +                       spin_unlock_bh(&l7_lock); 
    2030 +                       return (pattern_result ^ info->invert); 
    2031 +               } 
    2032 +               strcpy(master_conntrack->layer7.app_proto, info->protocol); 
    2033 +       } else if(pattern_result > 1) { /* cleanup from "unset" */ 
    2034 +               pattern_result = 1; 
    2035 +       } 
    2036 + 
    2037 +       /* mark the packet seen */ 
    2038 +       skb->cb[0] = 1; 
    2039 + 
    2040 +       spin_unlock_bh(&l7_lock); 
    2041 +       return (pattern_result ^ info->invert); 
    2042 +} 
    2043 + 
    2044 +// load nf_conntrack_ipv4 
    2045 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    2046 +static bool check(const struct xt_mtchk_param *par) 
    2047 +{ 
    2048 +        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { 
    2049 +                printk(KERN_WARNING "can't load conntrack support for " 
    2050 +                                    "proto=%d\n", par->match->family); 
    2051 +#else 
    2052 +static bool check(const char *tablename, const void *inf, 
    2053 +                const struct xt_match *match, void *matchinfo, 
    2054 +                unsigned int hook_mask) 
    2055 +{ 
    2056 +        if (nf_ct_l3proto_try_module_get(match->family) < 0) { 
    2057 +                printk(KERN_WARNING "can't load conntrack support for " 
    2058 +                                    "proto=%d\n", match->family); 
    2059 +#endif 
    2060 +                return 0; 
    2061 +        } 
    2062 +       return 1; 
    2063 +} 
    2064 + 
    2065 + 
    2066 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    2067 +       static void destroy(const struct xt_mtdtor_param *par) 
    2068 +       { 
    2069 +               nf_ct_l3proto_module_put(par->match->family); 
    2070 +       } 
    2071 +#else 
    2072 +       static void destroy(const struct xt_match *match, void *matchinfo) 
    2073 +       { 
    2074 +               nf_ct_l3proto_module_put(match->family); 
    2075 +       } 
    2076 +#endif 
    2077 + 
    2078 +static struct xt_match xt_layer7_match[] __read_mostly = { 
    2079 +{ 
    2080 +       .name           = "layer7", 
    2081 +       .family         = AF_INET, 
    2082 +       .checkentry     = check, 
    2083 +       .match          = match, 
    2084 +       .destroy        = destroy, 
    2085 +       .matchsize      = sizeof(struct xt_layer7_info), 
    2086 +       .me             = THIS_MODULE 
    2087 +} 
     2118+++ b/include/linux/netfilter/xt_layer7.h 
     2119@@ -0,0 +1,13 @@ 
     2120+#ifndef _XT_LAYER7_H 
     2121+#define _XT_LAYER7_H 
     2122+ 
     2123+#define MAX_PATTERN_LEN 8192 
     2124+#define MAX_PROTOCOL_LEN 256 
     2125+ 
     2126+struct xt_layer7_info { 
     2127+    char protocol[MAX_PROTOCOL_LEN]; 
     2128+    char pattern[MAX_PATTERN_LEN]; 
     2129+    u_int8_t invert; 
    20882130+}; 
    20892131+ 
    2090 +static void layer7_cleanup_proc(void) 
    2091 +{ 
    2092 +       remove_proc_entry("layer7_numpackets", init_net.proc_net); 
    2093 +} 
    2094 + 
    2095 +/* register the proc file */ 
    2096 +static void layer7_init_proc(void) 
    2097 +{ 
    2098 +       struct proc_dir_entry* entry; 
    2099 +       entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net); 
    2100 +       entry->read_proc = layer7_read_proc; 
    2101 +       entry->write_proc = layer7_write_proc; 
    2102 +} 
    2103 + 
    2104 +static int __init xt_layer7_init(void) 
    2105 +{ 
    2106 +       need_conntrack(); 
    2107 + 
    2108 +       layer7_init_proc(); 
    2109 +       if(maxdatalen < 1) { 
    2110 +               printk(KERN_WARNING "layer7: maxdatalen can't be < 1, " 
    2111 +                       "using 1\n"); 
    2112 +               maxdatalen = 1; 
    2113 +       } 
    2114 +       /* This is not a hard limit.  It's just here to prevent people from 
    2115 +       bringing their slow machines to a grinding halt. */ 
    2116 +       else if(maxdatalen > 65536) { 
    2117 +               printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, " 
    2118 +                       "using 65536\n"); 
    2119 +               maxdatalen = 65536; 
    2120 +       } 
    2121 +       return xt_register_matches(xt_layer7_match, 
    2122 +                                  ARRAY_SIZE(xt_layer7_match)); 
    2123 +} 
    2124 + 
    2125 +static void __exit xt_layer7_fini(void) 
    2126 +{ 
    2127 +       layer7_cleanup_proc(); 
    2128 +       xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match)); 
    2129 +} 
    2130 + 
    2131 +module_init(xt_layer7_init); 
    2132 +module_exit(xt_layer7_fini); 
     2132+#endif /* _XT_LAYER7_H */ 
  • trunk/target/linux/generic/patches-2.6.37/100-netfilter_layer7_2.22.patch

    r24003 r24004  
    1 --- /dev/null 
    2 +++ b/include/linux/netfilter/xt_layer7.h 
    3 @@ -0,0 +1,13 @@ 
    4 +#ifndef _XT_LAYER7_H 
    5 +#define _XT_LAYER7_H 
    6 + 
    7 +#define MAX_PATTERN_LEN 8192 
    8 +#define MAX_PROTOCOL_LEN 256 
    9 + 
    10 +struct xt_layer7_info { 
    11 +    char protocol[MAX_PROTOCOL_LEN]; 
    12 +    char pattern[MAX_PATTERN_LEN]; 
    13 +    u_int8_t invert; 
    14 +}; 
    15 + 
    16 +#endif /* _XT_LAYER7_H */ 
    17 --- a/include/net/netfilter/nf_conntrack.h 
    18 +++ b/include/net/netfilter/nf_conntrack.h 
    19 @@ -116,6 +116,22 @@ struct nf_conn { 
    20         u_int32_t secmark; 
    21  #endif 
    22   
    23 +#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \ 
    24 +    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
    25 +       struct { 
    26 +               /* 
    27 +                * e.g. "http". NULL before decision. "unknown" after decision 
    28 +                * if no match. 
    29 +                */ 
    30 +               char *app_proto; 
    31 +               /* 
    32 +                * application layer data so far. NULL after match decision. 
    33 +                */ 
    34 +               char *app_data; 
    35 +               unsigned int app_data_len; 
    36 +       } layer7; 
    37 +#endif 
    38 + 
    39         /* Storage reserved for other modules: */ 
    40         union nf_conntrack_proto proto; 
    41   
    421--- a/net/netfilter/Kconfig 
    432+++ b/net/netfilter/Kconfig 
    44 @@ -948,6 +948,27 @@ config NETFILTER_XT_MATCH_STATE 
     3@@ -946,6 +946,27 @@ config NETFILTER_XT_MATCH_STATE 
    454  
    465          To compile it as a module, choose M here.  If unsure, say N. 
     
    509+       depends on NETFILTER_XTABLES 
    5110+       depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK) 
    52 +       depends on NF_CT_ACCT 
     11+       depends on NETFILTER_ADVANCED 
    5312+       help 
    5413+         Say Y if you want to be able to classify connections (and their 
     
    8039 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o 
    8140 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o 
    82 --- a/net/netfilter/nf_conntrack_core.c 
    83 +++ b/net/netfilter/nf_conntrack_core.c 
    84 @@ -212,6 +212,14 @@ destroy_conntrack(struct nf_conntrack *n 
    85          * too. */ 
    86         nf_ct_remove_expectations(ct); 
    87   
    88 +       #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
    89 +       if(ct->layer7.app_proto) 
    90 +               kfree(ct->layer7.app_proto); 
    91 +       if(ct->layer7.app_data) 
    92 +       kfree(ct->layer7.app_data); 
     41--- /dev/null 
     42+++ b/net/netfilter/xt_layer7.c 
     43@@ -0,0 +1,666 @@ 
     44+/* 
     45+  Kernel module to match application layer (OSI layer 7) data in connections. 
     46+ 
     47+  http://l7-filter.sf.net 
     48+ 
     49+  (C) 2003-2009 Matthew Strait and Ethan Sommer. 
     50+ 
     51+  This program is free software; you can redistribute it and/or 
     52+  modify it under the terms of the GNU General Public License 
     53+  as published by the Free Software Foundation; either version 
     54+  2 of the License, or (at your option) any later version. 
     55+  http://www.gnu.org/licenses/gpl.txt 
     56+ 
     57+  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>, 
     58+  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait, 
     59+  Ethan Sommer, Justin Levandoski. 
     60+*/ 
     61+ 
     62+#include <linux/spinlock.h> 
     63+#include <linux/version.h> 
     64+#include <net/ip.h> 
     65+#include <net/tcp.h> 
     66+#include <linux/module.h> 
     67+#include <linux/skbuff.h> 
     68+#include <linux/netfilter.h> 
     69+#include <net/netfilter/nf_conntrack.h> 
     70+#include <net/netfilter/nf_conntrack_core.h> 
     71+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) 
     72+#include <net/netfilter/nf_conntrack_extend.h> 
     73+#include <net/netfilter/nf_conntrack_acct.h> 
     74+#endif 
     75+#include <linux/netfilter/x_tables.h> 
     76+#include <linux/netfilter/xt_layer7.h> 
     77+#include <linux/ctype.h> 
     78+#include <linux/proc_fs.h> 
     79+ 
     80+#include "regexp/regexp.c" 
     81+ 
     82+MODULE_LICENSE("GPL"); 
     83+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); 
     84+MODULE_DESCRIPTION("iptables application layer match module"); 
     85+MODULE_ALIAS("ipt_layer7"); 
     86+MODULE_VERSION("2.21"); 
     87+ 
     88+static int maxdatalen = 2048; // this is the default 
     89+module_param(maxdatalen, int, 0444); 
     90+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); 
     91+#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG 
     92+       #define DPRINTK(format,args...) printk(format,##args) 
     93+#else 
     94+       #define DPRINTK(format,args...) 
     95+#endif 
     96+ 
     97+/* Number of packets whose data we look at. 
     98+This can be modified through /proc/net/layer7_numpackets */ 
     99+static int num_packets = 10; 
     100+ 
     101+static struct pattern_cache { 
     102+       char * regex_string; 
     103+       regexp * pattern; 
     104+       struct pattern_cache * next; 
     105+} * first_pattern_cache = NULL; 
     106+ 
     107+DEFINE_SPINLOCK(l7_lock); 
     108+ 
     109+static int total_acct_packets(struct nf_conn *ct) 
     110+{ 
     111+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) 
     112+       BUG_ON(ct == NULL); 
     113+       return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets); 
     114+#else 
     115+       struct nf_conn_counter *acct; 
     116+ 
     117+       BUG_ON(ct == NULL); 
     118+       acct = nf_conn_acct_find(ct); 
     119+       if (!acct) 
     120+               return 0; 
     121+       return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets); 
     122+#endif 
     123+} 
     124+ 
     125+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
     126+/* Converts an unfriendly string into a friendly one by 
     127+replacing unprintables with periods and all whitespace with " ". */ 
     128+static char * friendly_print(unsigned char * s) 
     129+{ 
     130+       char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); 
     131+       int i; 
     132+ 
     133+       if(!f) { 
     134+               if (net_ratelimit()) 
     135+                       printk(KERN_ERR "layer7: out of memory in " 
     136+                                       "friendly_print, bailing.\n"); 
     137+               return NULL; 
     138+       } 
     139+ 
     140+       for(i = 0; i < strlen(s); i++){ 
     141+               if(isprint(s[i]) && s[i] < 128) f[i] = s[i]; 
     142+               else if(isspace(s[i]))          f[i] = ' '; 
     143+               else                            f[i] = '.'; 
     144+       } 
     145+       f[i] = '\0'; 
     146+       return f; 
     147+} 
     148+ 
     149+static char dec2hex(int i) 
     150+{ 
     151+       switch (i) { 
     152+               case 0 ... 9: 
     153+                       return (i + '0'); 
     154+                       break; 
     155+               case 10 ... 15: 
     156+                       return (i - 10 + 'a'); 
     157+                       break; 
     158+               default: 
     159+                       if (net_ratelimit()) 
     160+                               printk("layer7: Problem in dec2hex\n"); 
     161+                       return '\0'; 
     162+       } 
     163+} 
     164+ 
     165+static char * hex_print(unsigned char * s) 
     166+{ 
     167+       char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); 
     168+       int i; 
     169+ 
     170+       if(!g) { 
     171+              if (net_ratelimit()) 
     172+                       printk(KERN_ERR "layer7: out of memory in hex_print, " 
     173+                                       "bailing.\n"); 
     174+              return NULL; 
     175+       } 
     176+ 
     177+       for(i = 0; i < strlen(s); i++) { 
     178+               g[i*3    ] = dec2hex(s[i]/16); 
     179+               g[i*3 + 1] = dec2hex(s[i]%16); 
     180+               g[i*3 + 2] = ' '; 
     181+       } 
     182+       g[i*3] = '\0'; 
     183+ 
     184+       return g; 
     185+} 
     186+#endif // DEBUG 
     187+ 
     188+/* Use instead of regcomp.  As we expect to be seeing the same regexps over and 
     189+over again, it make sense to cache the results. */ 
     190+static regexp * compile_and_cache(const char * regex_string,  
     191+                                  const char * protocol) 
     192+{ 
     193+       struct pattern_cache * node               = first_pattern_cache; 
     194+       struct pattern_cache * last_pattern_cache = first_pattern_cache; 
     195+       struct pattern_cache * tmp; 
     196+       unsigned int len; 
     197+ 
     198+       while (node != NULL) { 
     199+               if (!strcmp(node->regex_string, regex_string)) 
     200+               return node->pattern; 
     201+ 
     202+               last_pattern_cache = node;/* points at the last non-NULL node */ 
     203+               node = node->next; 
     204+       } 
     205+ 
     206+       /* If we reach the end of the list, then we have not yet cached 
     207+          the pattern for this regex. Let's do that now. 
     208+          Be paranoid about running out of memory to avoid list corruption. */ 
     209+       tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); 
     210+ 
     211+       if(!tmp) { 
     212+               if (net_ratelimit()) 
     213+                       printk(KERN_ERR "layer7: out of memory in " 
     214+                                       "compile_and_cache, bailing.\n"); 
     215+               return NULL; 
     216+       } 
     217+ 
     218+       tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); 
     219+       tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC); 
     220+       tmp->next = NULL; 
     221+ 
     222+       if(!tmp->regex_string || !tmp->pattern) { 
     223+               if (net_ratelimit()) 
     224+                       printk(KERN_ERR "layer7: out of memory in " 
     225+                                       "compile_and_cache, bailing.\n"); 
     226+               kfree(tmp->regex_string); 
     227+               kfree(tmp->pattern); 
     228+               kfree(tmp); 
     229+               return NULL; 
     230+       } 
     231+ 
     232+       /* Ok.  The new node is all ready now. */ 
     233+       node = tmp; 
     234+ 
     235+       if(first_pattern_cache == NULL) /* list is empty */ 
     236+               first_pattern_cache = node; /* make node the beginning */ 
     237+       else 
     238+               last_pattern_cache->next = node; /* attach node to the end */ 
     239+ 
     240+       /* copy the string and compile the regex */ 
     241+       len = strlen(regex_string); 
     242+       DPRINTK("About to compile this: \"%s\"\n", regex_string); 
     243+       node->pattern = regcomp((char *)regex_string, &len); 
     244+       if ( !node->pattern ) { 
     245+               if (net_ratelimit()) 
     246+                       printk(KERN_ERR "layer7: Error compiling regexp " 
     247+                                       "\"%s\" (%s)\n",  
     248+                                       regex_string, protocol); 
     249+               /* pattern is now cached as NULL, so we won't try again. */ 
     250+       } 
     251+ 
     252+       strcpy(node->regex_string, regex_string); 
     253+       return node->pattern; 
     254+} 
     255+ 
     256+static int can_handle(const struct sk_buff *skb) 
     257+{ 
     258+       if(!ip_hdr(skb)) /* not IP */ 
     259+               return 0; 
     260+       if(ip_hdr(skb)->protocol != IPPROTO_TCP && 
     261+          ip_hdr(skb)->protocol != IPPROTO_UDP && 
     262+          ip_hdr(skb)->protocol != IPPROTO_ICMP) 
     263+               return 0; 
     264+       return 1; 
     265+} 
     266+ 
     267+/* Returns offset the into the skb->data that the application data starts */ 
     268+static int app_data_offset(const struct sk_buff *skb) 
     269+{ 
     270+       /* In case we are ported somewhere (ebtables?) where ip_hdr(skb) 
     271+       isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ 
     272+       int ip_hl = 4*ip_hdr(skb)->ihl; 
     273+ 
     274+       if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { 
     275+               /* 12 == offset into TCP header for the header length field. 
     276+               Can't get this with skb->h.th->doff because the tcphdr 
     277+               struct doesn't get set when routing (this is confirmed to be 
     278+               true in Netfilter as well as QoS.) */ 
     279+               int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); 
     280+ 
     281+               return ip_hl + tcp_hl; 
     282+       } else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) { 
     283+               return ip_hl + 8; /* UDP header is always 8 bytes */ 
     284+       } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { 
     285+               return ip_hl + 8; /* ICMP header is 8 bytes */ 
     286+       } else { 
     287+               if (net_ratelimit()) 
     288+                       printk(KERN_ERR "layer7: tried to handle unknown " 
     289+                                       "protocol!\n"); 
     290+               return ip_hl + 8; /* something reasonable */ 
     291+       } 
     292+} 
     293+ 
     294+/* handles whether there's a match when we aren't appending data anymore */ 
     295+static int match_no_append(struct nf_conn * conntrack,  
     296+                           struct nf_conn * master_conntrack,  
     297+                           enum ip_conntrack_info ctinfo, 
     298+                           enum ip_conntrack_info master_ctinfo, 
     299+                           const struct xt_layer7_info * info) 
     300+{ 
     301+       /* If we're in here, throw the app data away */ 
     302+       if(master_conntrack->layer7.app_data != NULL) { 
     303+ 
     304+       #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
     305+               if(!master_conntrack->layer7.app_proto) { 
     306+                       char * f =  
     307+                         friendly_print(master_conntrack->layer7.app_data); 
     308+                       char * g =  
     309+                         hex_print(master_conntrack->layer7.app_data); 
     310+                       DPRINTK("\nl7-filter gave up after %d bytes " 
     311+                               "(%d packets):\n%s\n", 
     312+                               strlen(f), total_acct_packets(master_conntrack), f); 
     313+                       kfree(f); 
     314+                       DPRINTK("In hex: %s\n", g); 
     315+                       kfree(g); 
     316+               } 
    93317+       #endif 
    94318+ 
    95 + 
    96         /* We overload first tuple to link into unconfirmed list. */ 
    97         if (!nf_ct_is_confirmed(ct)) { 
    98                 BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); 
    99 --- a/net/netfilter/nf_conntrack_standalone.c 
    100 +++ b/net/netfilter/nf_conntrack_standalone.c 
    101 @@ -200,6 +200,12 @@ static int ct_seq_show(struct seq_file * 
    102                 goto release; 
    103  #endif 
    104   
    105 +#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
    106 +       if(ct->layer7.app_proto && 
    107 +           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto)) 
    108 +               return -ENOSPC; 
     319+               kfree(master_conntrack->layer7.app_data); 
     320+               master_conntrack->layer7.app_data = NULL; /* don't free again */ 
     321+       } 
     322+ 
     323+       if(master_conntrack->layer7.app_proto){ 
     324+               /* Here child connections set their .app_proto (for /proc) */ 
     325+               if(!conntrack->layer7.app_proto) { 
     326+                       conntrack->layer7.app_proto =  
     327+                         kmalloc(strlen(master_conntrack->layer7.app_proto)+1,  
     328+                           GFP_ATOMIC); 
     329+                       if(!conntrack->layer7.app_proto){ 
     330+                               if (net_ratelimit()) 
     331+                                       printk(KERN_ERR "layer7: out of memory " 
     332+                                                       "in match_no_append, " 
     333+                                                       "bailing.\n"); 
     334+                               return 1; 
     335+                       } 
     336+                       strcpy(conntrack->layer7.app_proto,  
     337+                               master_conntrack->layer7.app_proto); 
     338+               } 
     339+ 
     340+               return (!strcmp(master_conntrack->layer7.app_proto,  
     341+                               info->protocol)); 
     342+       } 
     343+       else { 
     344+               /* If not classified, set to "unknown" to distinguish from 
     345+               connections that are still being tested. */ 
     346+               master_conntrack->layer7.app_proto =  
     347+                       kmalloc(strlen("unknown")+1, GFP_ATOMIC); 
     348+               if(!master_conntrack->layer7.app_proto){ 
     349+                       if (net_ratelimit()) 
     350+                               printk(KERN_ERR "layer7: out of memory in " 
     351+                                               "match_no_append, bailing.\n"); 
     352+                       return 1; 
     353+               } 
     354+               strcpy(master_conntrack->layer7.app_proto, "unknown"); 
     355+               return 0; 
     356+       } 
     357+} 
     358+ 
     359+/* add the new app data to the conntrack.  Return number of bytes added. */ 
     360+static int add_data(struct nf_conn * master_conntrack, 
     361+                    char * app_data, int appdatalen) 
     362+{ 
     363+       int length = 0, i; 
     364+       int oldlength = master_conntrack->layer7.app_data_len; 
     365+ 
     366+       /* This is a fix for a race condition by Deti Fliegl. However, I'm not  
     367+          clear on whether the race condition exists or whether this really  
     368+          fixes it.  I might just be being dense... Anyway, if it's not really  
     369+          a fix, all it does is waste a very small amount of time. */ 
     370+       if(!master_conntrack->layer7.app_data) return 0; 
     371+ 
     372+       /* Strip nulls. Make everything lower case (our regex lib doesn't 
     373+       do case insensitivity).  Add it to the end of the current data. */ 
     374+       for(i = 0; i < maxdatalen-oldlength-1 && 
     375+                  i < appdatalen; i++) { 
     376+               if(app_data[i] != '\0') { 
     377+                       /* the kernel version of tolower mungs 'upper ascii' */ 
     378+                       master_conntrack->layer7.app_data[length+oldlength] = 
     379+                               isascii(app_data[i])?  
     380+                                       tolower(app_data[i]) : app_data[i]; 
     381+                       length++; 
     382+               } 
     383+       } 
     384+ 
     385+       master_conntrack->layer7.app_data[length+oldlength] = '\0'; 
     386+       master_conntrack->layer7.app_data_len = length + oldlength; 
     387+ 
     388+       return length; 
     389+} 
     390+ 
     391+/* taken from drivers/video/modedb.c */ 
     392+static int my_atoi(const char *s) 
     393+{ 
     394+       int val = 0; 
     395+ 
     396+       for (;; s++) { 
     397+               switch (*s) { 
     398+                       case '0'...'9': 
     399+                       val = 10*val+(*s-'0'); 
     400+                       break; 
     401+               default: 
     402+                       return val; 
     403+               } 
     404+       } 
     405+} 
     406+ 
     407+/* write out num_packets to userland. */ 
     408+static int layer7_read_proc(char* page, char ** start, off_t off, int count, 
     409+                            int* eof, void * data) 
     410+{ 
     411+       if(num_packets > 99 && net_ratelimit()) 
     412+               printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); 
     413+ 
     414+       page[0] = num_packets/10 + '0'; 
     415+       page[1] = num_packets%10 + '0'; 
     416+       page[2] = '\n'; 
     417+       page[3] = '\0'; 
     418+ 
     419+       *eof=1; 
     420+ 
     421+       return 3; 
     422+} 
     423+ 
     424+/* Read in num_packets from userland */ 
     425+static int layer7_write_proc(struct file* file, const char* buffer, 
     426+                             unsigned long count, void *data) 
     427+{ 
     428+       char * foo = kmalloc(count, GFP_ATOMIC); 
     429+ 
     430+       if(!foo){ 
     431+               if (net_ratelimit()) 
     432+                       printk(KERN_ERR "layer7: out of memory, bailing. " 
     433+                                       "num_packets unchanged.\n"); 
     434+               return count; 
     435+       } 
     436+ 
     437+       if(copy_from_user(foo, buffer, count)) { 
     438+               return -EFAULT; 
     439+       } 
     440+ 
     441+ 
     442+       num_packets = my_atoi(foo); 
     443+       kfree (foo); 
     444+ 
     445+       /* This has an arbitrary limit to make the math easier. I'm lazy. 
     446+       But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ 
     447+       if(num_packets > 99) { 
     448+               printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); 
     449+               num_packets = 99; 
     450+       } else if(num_packets < 1) { 
     451+               printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); 
     452+               num_packets = 1; 
     453+       } 
     454+ 
     455+       return count; 
     456+} 
     457+ 
     458+static bool 
     459+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     460+match(const struct sk_buff *skbin, const struct xt_match_param *par) 
     461+#else 
     462+match(const struct sk_buff *skbin, 
     463+      const struct net_device *in, 
     464+      const struct net_device *out, 
     465+      const struct xt_match *match, 
     466+      const void *matchinfo, 
     467+      int offset, 
     468+      unsigned int protoff, 
     469+      bool *hotdrop) 
    109470+#endif 
    110 + 
    111         if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 
    112                 goto release; 
    113   
     471+{ 
     472+       /* sidestep const without getting a compiler warning... */ 
     473+       struct sk_buff * skb = (struct sk_buff *)skbin;  
     474+ 
     475+       const struct xt_layer7_info * info =  
     476+       #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     477+               par->matchinfo; 
     478+       #else 
     479+               matchinfo; 
     480+       #endif 
     481+ 
     482+       enum ip_conntrack_info master_ctinfo, ctinfo; 
     483+       struct nf_conn *master_conntrack, *conntrack; 
     484+       unsigned char * app_data; 
     485+       unsigned int pattern_result, appdatalen; 
     486+       regexp * comppattern; 
     487+ 
     488+       /* Be paranoid/incompetent - lock the entire match function. */ 
     489+       spin_lock_bh(&l7_lock); 
     490+ 
     491+       if(!can_handle(skb)){ 
     492+               DPRINTK("layer7: This is some protocol I can't handle.\n"); 
     493+               spin_unlock_bh(&l7_lock); 
     494+               return info->invert; 
     495+       } 
     496+ 
     497+       /* Treat parent & all its children together as one connection, except 
     498+       for the purpose of setting conntrack->layer7.app_proto in the actual 
     499+       connection. This makes /proc/net/ip_conntrack more satisfying. */ 
     500+       if(!(conntrack = nf_ct_get(skb, &ctinfo)) || 
     501+          !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ 
     502+               DPRINTK("layer7: couldn't get conntrack.\n"); 
     503+               spin_unlock_bh(&l7_lock); 
     504+               return info->invert; 
     505+       } 
     506+ 
     507+       /* Try to get a master conntrack (and its master etc) for FTP, etc. */ 
     508+       while (master_ct(master_conntrack) != NULL) 
     509+               master_conntrack = master_ct(master_conntrack); 
     510+ 
     511+       /* if we've classified it or seen too many packets */ 
     512+       if(total_acct_packets(master_conntrack) > num_packets || 
     513+          master_conntrack->layer7.app_proto) { 
     514+ 
     515+               pattern_result = match_no_append(conntrack, master_conntrack,  
     516+                                                ctinfo, master_ctinfo, info); 
     517+ 
     518+               /* skb->cb[0] == seen. Don't do things twice if there are  
     519+               multiple l7 rules. I'm not sure that using cb for this purpose  
     520+               is correct, even though it says "put your private variables  
     521+               there". But it doesn't look like it is being used for anything 
     522+               else in the skbs that make it here. */ 
     523+               skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ 
     524+ 
     525+               spin_unlock_bh(&l7_lock); 
     526+               return (pattern_result ^ info->invert); 
     527+       } 
     528+ 
     529+       if(skb_is_nonlinear(skb)){ 
     530+               if(skb_linearize(skb) != 0){ 
     531+                       if (net_ratelimit()) 
     532+                               printk(KERN_ERR "layer7: failed to linearize " 
     533+                                               "packet, bailing.\n"); 
     534+                       spin_unlock_bh(&l7_lock); 
     535+                       return info->invert; 
     536+               } 
     537+       } 
     538+ 
     539+       /* now that the skb is linearized, it's safe to set these. */ 
     540+       app_data = skb->data + app_data_offset(skb); 
     541+       appdatalen = skb_tail_pointer(skb) - app_data; 
     542+ 
     543+       /* the return value gets checked later, when we're ready to use it */ 
     544+       comppattern = compile_and_cache(info->pattern, info->protocol); 
     545+ 
     546+       /* On the first packet of a connection, allocate space for app data */ 
     547+       if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&  
     548+          !master_conntrack->layer7.app_data){ 
     549+               master_conntrack->layer7.app_data =  
     550+                       kmalloc(maxdatalen, GFP_ATOMIC); 
     551+               if(!master_conntrack->layer7.app_data){ 
     552+                       if (net_ratelimit()) 
     553+                               printk(KERN_ERR "layer7: out of memory in " 
     554+                                               "match, bailing.\n"); 
     555+                       spin_unlock_bh(&l7_lock); 
     556+                       return info->invert; 
     557+               } 
     558+ 
     559+               master_conntrack->layer7.app_data[0] = '\0'; 
     560+       } 
     561+ 
     562+       /* Can be here, but unallocated, if numpackets is increased near 
     563+       the beginning of a connection */ 
     564+       if(master_conntrack->layer7.app_data == NULL){ 
     565+               spin_unlock_bh(&l7_lock); 
     566+               return info->invert; /* unmatched */ 
     567+       } 
     568+ 
     569+       if(!skb->cb[0]){ 
     570+               int newbytes; 
     571+               newbytes = add_data(master_conntrack, app_data, appdatalen); 
     572+ 
     573+               if(newbytes == 0) { /* didn't add any data */ 
     574+                       skb->cb[0] = 1; 
     575+                       /* Didn't match before, not going to match now */ 
     576+                       spin_unlock_bh(&l7_lock); 
     577+                       return info->invert; 
     578+               } 
     579+       } 
     580+ 
     581+       /* If looking for "unknown", then never match.  "Unknown" means that 
     582+       we've given up; we're still trying with these packets. */ 
     583+       if(!strcmp(info->protocol, "unknown")) { 
     584+               pattern_result = 0; 
     585+       /* If looking for "unset", then always match. "Unset" means that we 
     586+       haven't yet classified the connection. */ 
     587+       } else if(!strcmp(info->protocol, "unset")) { 
     588+               pattern_result = 2; 
     589+               DPRINTK("layer7: matched unset: not yet classified " 
     590+                       "(%d/%d packets)\n", 
     591+                        total_acct_packets(master_conntrack), num_packets); 
     592+       /* If the regexp failed to compile, don't bother running it */ 
     593+       } else if(comppattern &&  
     594+                 regexec(comppattern, master_conntrack->layer7.app_data)){ 
     595+               DPRINTK("layer7: matched %s\n", info->protocol); 
     596+               pattern_result = 1; 
     597+       } else pattern_result = 0; 
     598+ 
     599+       if(pattern_result == 1) { 
     600+               master_conntrack->layer7.app_proto =  
     601+                       kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); 
     602+               if(!master_conntrack->layer7.app_proto){ 
     603+                       if (net_ratelimit()) 
     604+                               printk(KERN_ERR "layer7: out of memory in " 
     605+                                               "match, bailing.\n"); 
     606+                       spin_unlock_bh(&l7_lock); 
     607+                       return (pattern_result ^ info->invert); 
     608+               } 
     609+               strcpy(master_conntrack->layer7.app_proto, info->protocol); 
     610+       } else if(pattern_result > 1) { /* cleanup from "unset" */ 
     611+               pattern_result = 1; 
     612+       } 
     613+ 
     614+       /* mark the packet seen */ 
     615+       skb->cb[0] = 1; 
     616+ 
     617+       spin_unlock_bh(&l7_lock); 
     618+       return (pattern_result ^ info->invert); 
     619+} 
     620+ 
     621+// load nf_conntrack_ipv4 
     622+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     623+static bool check(const struct xt_mtchk_param *par) 
     624+{ 
     625+        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { 
     626+                printk(KERN_WARNING "can't load conntrack support for " 
     627+                                    "proto=%d\n", par->match->family); 
     628+#else 
     629+static bool check(const char *tablename, const void *inf, 
     630+                const struct xt_match *match, void *matchinfo, 
     631+                unsigned int hook_mask) 
     632+{ 
     633+        if (nf_ct_l3proto_try_module_get(match->family) < 0) { 
     634+                printk(KERN_WARNING "can't load conntrack support for " 
     635+                                    "proto=%d\n", match->family); 
     636+#endif 
     637+                return 0; 
     638+        } 
     639+       return 1; 
     640+} 
     641+ 
     642+ 
     643+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     644+       static void destroy(const struct xt_mtdtor_param *par) 
     645+       { 
     646+               nf_ct_l3proto_module_put(par->match->family); 
     647+       } 
     648+#else 
     649+       static void destroy(const struct xt_match *match, void *matchinfo) 
     650+       { 
     651+               nf_ct_l3proto_module_put(match->family); 
     652+       } 
     653+#endif 
     654+ 
     655+static struct xt_match xt_layer7_match[] __read_mostly = { 
     656+{ 
     657+       .name           = "layer7", 
     658+       .family         = AF_INET, 
     659+       .checkentry     = check, 
     660+       .match          = match, 
     661+       .destroy        = destroy, 
     662+       .matchsize      = sizeof(struct xt_layer7_info), 
     663+       .me             = THIS_MODULE 
     664+} 
     665+}; 
     666+ 
     667+static void layer7_cleanup_proc(void) 
     668+{ 
     669+       remove_proc_entry("layer7_numpackets", init_net.proc_net); 
     670+} 
     671+ 
     672+/* register the proc file */ 
     673+static void layer7_init_proc(void) 
     674+{ 
     675+       struct proc_dir_entry* entry; 
     676+       entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net); 
     677+       entry->read_proc = layer7_read_proc; 
     678+       entry->write_proc = layer7_write_proc; 
     679+} 
     680+ 
     681+static int __init xt_layer7_init(void) 
     682+{ 
     683+       need_conntrack(); 
     684+ 
     685+       layer7_init_proc(); 
     686+       if(maxdatalen < 1) { 
     687+               printk(KERN_WARNING "layer7: maxdatalen can't be < 1, " 
     688+                       "using 1\n"); 
     689+               maxdatalen = 1; 
     690+       } 
     691+       /* This is not a hard limit.  It's just here to prevent people from 
     692+       bringing their slow machines to a grinding halt. */ 
     693+       else if(maxdatalen > 65536) { 
     694+               printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, " 
     695+                       "using 65536\n"); 
     696+               maxdatalen = 65536; 
     697+       } 
     698+       return xt_register_matches(xt_layer7_match, 
     699+                                  ARRAY_SIZE(xt_layer7_match)); 
     700+} 
     701+ 
     702+static void __exit xt_layer7_fini(void) 
     703+{ 
     704+       layer7_cleanup_proc(); 
     705+       xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match)); 
     706+} 
     707+ 
     708+module_init(xt_layer7_init); 
     709+module_exit(xt_layer7_fini); 
    114710--- /dev/null 
    115711+++ b/net/netfilter/regexp/regexp.c 
     
    14622058+       *dst++ = '\0'; 
    14632059+} 
     2060--- a/net/netfilter/nf_conntrack_core.c 
     2061+++ b/net/netfilter/nf_conntrack_core.c 
     2062@@ -202,6 +202,14 @@ destroy_conntrack(struct nf_conntrack *n 
     2063         * too. */ 
     2064        nf_ct_remove_expectations(ct); 
     2065  
     2066+       #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     2067+       if(ct->layer7.app_proto) 
     2068+               kfree(ct->layer7.app_proto); 
     2069+       if(ct->layer7.app_data) 
     2070+       kfree(ct->layer7.app_data); 
     2071+       #endif 
     2072+ 
     2073+ 
     2074        /* We overload first tuple to link into unconfirmed list. */ 
     2075        if (!nf_ct_is_confirmed(ct)) { 
     2076                BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); 
     2077--- a/net/netfilter/nf_conntrack_standalone.c 
     2078+++ b/net/netfilter/nf_conntrack_standalone.c 
     2079@@ -178,6 +178,12 @@ static int ct_seq_show(struct seq_file * 
     2080                goto release; 
     2081 #endif 
     2082  
     2083+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     2084+       if(ct->layer7.app_proto && 
     2085+           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto)) 
     2086+               return -ENOSPC; 
     2087+#endif 
     2088+ 
     2089        if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 
     2090                goto release; 
     2091  
     2092--- a/include/net/netfilter/nf_conntrack.h 
     2093+++ b/include/net/netfilter/nf_conntrack.h 
     2094@@ -116,6 +116,22 @@ struct nf_conn { 
     2095        u_int32_t secmark; 
     2096 #endif 
     2097  
     2098+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \ 
     2099+    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     2100+       struct { 
     2101+               /* 
     2102+                * e.g. "http". NULL before decision. "unknown" after decision 
     2103+                * if no match. 
     2104+                */ 
     2105+               char *app_proto; 
     2106+               /* 
     2107+                * application layer data so far. NULL after match decision. 
     2108+                */ 
     2109+               char *app_data; 
     2110+               unsigned int app_data_len; 
     2111+       } layer7; 
     2112+#endif 
     2113+ 
     2114        /* Storage reserved for other modules: */ 
     2115        union nf_conntrack_proto proto; 
     2116  
    14642117--- /dev/null 
    1465 +++ b/net/netfilter/xt_layer7.c 
    1466 @@ -0,0 +1,666 @@ 
    1467 +/* 
    1468 +  Kernel module to match application layer (OSI layer 7) data in connections. 
    1469 + 
    1470 +  http://l7-filter.sf.net 
    1471 + 
    1472 +  (C) 2003-2009 Matthew Strait and Ethan Sommer. 
    1473 + 
    1474 +  This program is free software; you can redistribute it and/or 
    1475 +  modify it under the terms of the GNU General Public License 
    1476 +  as published by the Free Software Foundation; either version 
    1477 +  2 of the License, or (at your option) any later version. 
    1478 +  http://www.gnu.org/licenses/gpl.txt 
    1479 + 
    1480 +  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>, 
    1481 +  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait, 
    1482 +  Ethan Sommer, Justin Levandoski. 
    1483 +*/ 
    1484 + 
    1485 +#include <linux/spinlock.h> 
    1486 +#include <linux/version.h> 
    1487 +#include <net/ip.h> 
    1488 +#include <net/tcp.h> 
    1489 +#include <linux/module.h> 
    1490 +#include <linux/skbuff.h> 
    1491 +#include <linux/netfilter.h> 
    1492 +#include <net/netfilter/nf_conntrack.h> 
    1493 +#include <net/netfilter/nf_conntrack_core.h> 
    1494 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) 
    1495 +#include <net/netfilter/nf_conntrack_extend.h> 
    1496 +#include <net/netfilter/nf_conntrack_acct.h> 
    1497 +#endif 
    1498 +#include <linux/netfilter/x_tables.h> 
    1499 +#include <linux/netfilter/xt_layer7.h> 
    1500 +#include <linux/ctype.h> 
    1501 +#include <linux/proc_fs.h> 
    1502 + 
    1503 +#include "regexp/regexp.c" 
    1504 + 
    1505 +MODULE_LICENSE("GPL"); 
    1506 +MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); 
    1507 +MODULE_DESCRIPTION("iptables application layer match module"); 
    1508 +MODULE_ALIAS("ipt_layer7"); 
    1509 +MODULE_VERSION("2.21"); 
    1510 + 
    1511 +static int maxdatalen = 2048; // this is the default 
    1512 +module_param(maxdatalen, int, 0444); 
    1513 +MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); 
    1514 +#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG 
    1515 +       #define DPRINTK(format,args...) printk(format,##args) 
    1516 +#else 
    1517 +       #define DPRINTK(format,args...) 
    1518 +#endif 
    1519 + 
    1520 +/* Number of packets whose data we look at. 
    1521 +This can be modified through /proc/net/layer7_numpackets */ 
    1522 +static int num_packets = 10; 
    1523 + 
    1524 +static struct pattern_cache { 
    1525 +       char * regex_string; 
    1526 +       regexp * pattern; 
    1527 +       struct pattern_cache * next; 
    1528 +} * first_pattern_cache = NULL; 
    1529 + 
    1530 +DEFINE_SPINLOCK(l7_lock); 
    1531 + 
    1532 +static int total_acct_packets(struct nf_conn *ct) 
    1533 +{ 
    1534 +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) 
    1535 +       BUG_ON(ct == NULL); 
    1536 +       return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets); 
    1537 +#else 
    1538 +       struct nf_conn_counter *acct; 
    1539 + 
    1540 +       BUG_ON(ct == NULL); 
    1541 +       acct = nf_conn_acct_find(ct); 
    1542 +       if (!acct) 
    1543 +               return 0; 
    1544 +       return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets); 
    1545 +#endif 
    1546 +} 
    1547 + 
    1548 +#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
    1549 +/* Converts an unfriendly string into a friendly one by 
    1550 +replacing unprintables with periods and all whitespace with " ". */ 
    1551 +static char * friendly_print(unsigned char * s) 
    1552 +{ 
    1553 +       char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); 
    1554 +       int i; 
    1555 + 
    1556 +       if(!f) { 
    1557 +               if (net_ratelimit()) 
    1558 +                       printk(KERN_ERR "layer7: out of memory in " 
    1559 +                                       "friendly_print, bailing.\n"); 
    1560 +               return NULL; 
    1561 +       } 
    1562 + 
    1563 +       for(i = 0; i < strlen(s); i++){ 
    1564 +               if(isprint(s[i]) && s[i] < 128) f[i] = s[i]; 
    1565 +               else if(isspace(s[i]))          f[i] = ' '; 
    1566 +               else                            f[i] = '.'; 
    1567 +       } 
    1568 +       f[i] = '\0'; 
    1569 +       return f; 
    1570 +} 
    1571 + 
    1572 +static char dec2hex(int i) 
    1573 +{ 
    1574 +       switch (i) { 
    1575 +               case 0 ... 9: 
    1576 +                       return (i + '0'); 
    1577 +                       break; 
    1578 +               case 10 ... 15: 
    1579 +                       return (i - 10 + 'a'); 
    1580 +                       break; 
    1581 +               default: 
    1582 +                       if (net_ratelimit()) 
    1583 +                               printk("layer7: Problem in dec2hex\n"); 
    1584 +                       return '\0'; 
    1585 +       } 
    1586 +} 
    1587 + 
    1588 +static char * hex_print(unsigned char * s) 
    1589 +{ 
    1590 +       char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); 
    1591 +       int i; 
    1592 + 
    1593 +       if(!g) { 
    1594 +              if (net_ratelimit()) 
    1595 +                       printk(KERN_ERR "layer7: out of memory in hex_print, " 
    1596 +                                       "bailing.\n"); 
    1597 +              return NULL; 
    1598 +       } 
    1599 + 
    1600 +       for(i = 0; i < strlen(s); i++) { 
    1601 +               g[i*3    ] = dec2hex(s[i]/16); 
    1602 +               g[i*3 + 1] = dec2hex(s[i]%16); 
    1603 +               g[i*3 + 2] = ' '; 
    1604 +       } 
    1605 +       g[i*3] = '\0'; 
    1606 + 
    1607 +       return g; 
    1608 +} 
    1609 +#endif // DEBUG 
    1610 + 
    1611 +/* Use instead of regcomp.  As we expect to be seeing the same regexps over and 
    1612 +over again, it make sense to cache the results. */ 
    1613 +static regexp * compile_and_cache(const char * regex_string,  
    1614 +                                  const char * protocol) 
    1615 +{ 
    1616 +       struct pattern_cache * node               = first_pattern_cache; 
    1617 +       struct pattern_cache * last_pattern_cache = first_pattern_cache; 
    1618 +       struct pattern_cache * tmp; 
    1619 +       unsigned int len; 
    1620 + 
    1621 +       while (node != NULL) { 
    1622 +               if (!strcmp(node->regex_string, regex_string)) 
    1623 +               return node->pattern; 
    1624 + 
    1625 +               last_pattern_cache = node;/* points at the last non-NULL node */ 
    1626 +               node = node->next; 
    1627 +       } 
    1628 + 
    1629 +       /* If we reach the end of the list, then we have not yet cached 
    1630 +          the pattern for this regex. Let's do that now. 
    1631 +          Be paranoid about running out of memory to avoid list corruption. */ 
    1632 +       tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); 
    1633 + 
    1634 +       if(!tmp) { 
    1635 +               if (net_ratelimit()) 
    1636 +                       printk(KERN_ERR "layer7: out of memory in " 
    1637 +                                       "compile_and_cache, bailing.\n"); 
    1638 +               return NULL; 
    1639 +       } 
    1640 + 
    1641 +       tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); 
    1642 +       tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC); 
    1643 +       tmp->next = NULL; 
    1644 + 
    1645 +       if(!tmp->regex_string || !tmp->pattern) { 
    1646 +               if (net_ratelimit()) 
    1647 +                       printk(KERN_ERR "layer7: out of memory in " 
    1648 +                                       "compile_and_cache, bailing.\n"); 
    1649 +               kfree(tmp->regex_string); 
    1650 +               kfree(tmp->pattern); 
    1651 +               kfree(tmp); 
    1652 +               return NULL; 
    1653 +       } 
    1654 + 
    1655 +       /* Ok.  The new node is all ready now. */ 
    1656 +       node = tmp; 
    1657 + 
    1658 +       if(first_pattern_cache == NULL) /* list is empty */ 
    1659 +               first_pattern_cache = node; /* make node the beginning */ 
    1660 +       else 
    1661 +               last_pattern_cache->next = node; /* attach node to the end */ 
    1662 + 
    1663 +       /* copy the string and compile the regex */ 
    1664 +       len = strlen(regex_string); 
    1665 +       DPRINTK("About to compile this: \"%s\"\n", regex_string); 
    1666 +       node->pattern = regcomp((char *)regex_string, &len); 
    1667 +       if ( !node->pattern ) { 
    1668 +               if (net_ratelimit()) 
    1669 +                       printk(KERN_ERR "layer7: Error compiling regexp " 
    1670 +                                       "\"%s\" (%s)\n",  
    1671 +                                       regex_string, protocol); 
    1672 +               /* pattern is now cached as NULL, so we won't try again. */ 
    1673 +       } 
    1674 + 
    1675 +       strcpy(node->regex_string, regex_string); 
    1676 +       return node->pattern; 
    1677 +} 
    1678 + 
    1679 +static int can_handle(const struct sk_buff *skb) 
    1680 +{ 
    1681 +       if(!ip_hdr(skb)) /* not IP */ 
    1682 +               return 0; 
    1683 +       if(ip_hdr(skb)->protocol != IPPROTO_TCP && 
    1684 +          ip_hdr(skb)->protocol != IPPROTO_UDP && 
    1685 +          ip_hdr(skb)->protocol != IPPROTO_ICMP) 
    1686 +               return 0; 
    1687 +       return 1; 
    1688 +} 
    1689 + 
    1690 +/* Returns offset the into the skb->data that the application data starts */ 
    1691 +static int app_data_offset(const struct sk_buff *skb) 
    1692 +{ 
    1693 +       /* In case we are ported somewhere (ebtables?) where ip_hdr(skb) 
    1694 +       isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ 
    1695 +       int ip_hl = 4*ip_hdr(skb)->ihl; 
    1696 + 
    1697 +       if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { 
    1698 +               /* 12 == offset into TCP header for the header length field. 
    1699 +               Can't get this with skb->h.th->doff because the tcphdr 
    1700 +               struct doesn't get set when routing (this is confirmed to be 
    1701 +               true in Netfilter as well as QoS.) */ 
    1702 +               int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); 
    1703 + 
    1704 +               return ip_hl + tcp_hl; 
    1705 +       } else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) { 
    1706 +               return ip_hl + 8; /* UDP header is always 8 bytes */ 
    1707 +       } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { 
    1708 +               return ip_hl + 8; /* ICMP header is 8 bytes */ 
    1709 +       } else { 
    1710 +               if (net_ratelimit()) 
    1711 +                       printk(KERN_ERR "layer7: tried to handle unknown " 
    1712 +                                       "protocol!\n"); 
    1713 +               return ip_hl + 8; /* something reasonable */ 
    1714 +       } 
    1715 +} 
    1716 + 
    1717 +/* handles whether there's a match when we aren't appending data anymore */ 
    1718 +static int match_no_append(struct nf_conn * conntrack,  
    1719 +                           struct nf_conn * master_conntrack,  
    1720 +                           enum ip_conntrack_info ctinfo, 
    1721 +                           enum ip_conntrack_info master_ctinfo, 
    1722 +                           const struct xt_layer7_info * info) 
    1723 +{ 
    1724 +       /* If we're in here, throw the app data away */ 
    1725 +       if(master_conntrack->layer7.app_data != NULL) { 
    1726 + 
    1727 +       #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
    1728 +               if(!master_conntrack->layer7.app_proto) { 
    1729 +                       char * f =  
    1730 +                         friendly_print(master_conntrack->layer7.app_data); 
    1731 +                       char * g =  
    1732 +                         hex_print(master_conntrack->layer7.app_data); 
    1733 +                       DPRINTK("\nl7-filter gave up after %d bytes " 
    1734 +                               "(%d packets):\n%s\n", 
    1735 +                               strlen(f), total_acct_packets(master_conntrack), f); 
    1736 +                       kfree(f); 
    1737 +                       DPRINTK("In hex: %s\n", g); 
    1738 +                       kfree(g); 
    1739 +               } 
    1740 +       #endif 
    1741 + 
    1742 +               kfree(master_conntrack->layer7.app_data); 
    1743 +               master_conntrack->layer7.app_data = NULL; /* don't free again */ 
    1744 +       } 
    1745 + 
    1746 +       if(master_conntrack->layer7.app_proto){ 
    1747 +               /* Here child connections set their .app_proto (for /proc) */ 
    1748 +               if(!conntrack->layer7.app_proto) { 
    1749 +                       conntrack->layer7.app_proto =  
    1750 +                         kmalloc(strlen(master_conntrack->layer7.app_proto)+1,  
    1751 +                           GFP_ATOMIC); 
    1752 +                       if(!conntrack->layer7.app_proto){ 
    1753 +                               if (net_ratelimit()) 
    1754 +                                       printk(KERN_ERR "layer7: out of memory " 
    1755 +                                                       "in match_no_append, " 
    1756 +                                                       "bailing.\n"); 
    1757 +                               return 1; 
    1758 +                       } 
    1759 +                       strcpy(conntrack->layer7.app_proto,  
    1760 +                               master_conntrack->layer7.app_proto); 
    1761 +               } 
    1762 + 
    1763 +               return (!strcmp(master_conntrack->layer7.app_proto,  
    1764 +                               info->protocol)); 
    1765 +       } 
    1766 +       else { 
    1767 +               /* If not classified, set to "unknown" to distinguish from 
    1768 +               connections that are still being tested. */ 
    1769 +               master_conntrack->layer7.app_proto =  
    1770 +                       kmalloc(strlen("unknown")+1, GFP_ATOMIC); 
    1771 +               if(!master_conntrack->layer7.app_proto){ 
    1772 +                       if (net_ratelimit()) 
    1773 +                               printk(KERN_ERR "layer7: out of memory in " 
    1774 +                                               "match_no_append, bailing.\n"); 
    1775 +                       return 1; 
    1776 +               } 
    1777 +               strcpy(master_conntrack->layer7.app_proto, "unknown"); 
    1778 +               return 0; 
    1779 +       } 
    1780 +} 
    1781 + 
    1782 +/* add the new app data to the conntrack.  Return number of bytes added. */ 
    1783 +static int add_data(struct nf_conn * master_conntrack, 
    1784 +                    char * app_data, int appdatalen) 
    1785 +{ 
    1786 +       int length = 0, i; 
    1787 +       int oldlength = master_conntrack->layer7.app_data_len; 
    1788 + 
    1789 +       /* This is a fix for a race condition by Deti Fliegl. However, I'm not  
    1790 +          clear on whether the race condition exists or whether this really  
    1791 +          fixes it.  I might just be being dense... Anyway, if it's not really  
    1792 +          a fix, all it does is waste a very small amount of time. */ 
    1793 +       if(!master_conntrack->layer7.app_data) return 0; 
    1794 + 
    1795 +       /* Strip nulls. Make everything lower case (our regex lib doesn't 
    1796 +       do case insensitivity).  Add it to the end of the current data. */ 
    1797 +       for(i = 0; i < maxdatalen-oldlength-1 && 
    1798 +                  i < appdatalen; i++) { 
    1799 +               if(app_data[i] != '\0') { 
    1800 +                       /* the kernel version of tolower mungs 'upper ascii' */ 
    1801 +                       master_conntrack->layer7.app_data[length+oldlength] = 
    1802 +                               isascii(app_data[i])?  
    1803 +                                       tolower(app_data[i]) : app_data[i]; 
    1804 +                       length++; 
    1805 +               } 
    1806 +       } 
    1807 + 
    1808 +       master_conntrack->layer7.app_data[length+oldlength] = '\0'; 
    1809 +       master_conntrack->layer7.app_data_len = length + oldlength; 
    1810 + 
    1811 +       return length; 
    1812 +} 
    1813 + 
    1814 +/* taken from drivers/video/modedb.c */ 
    1815 +static int my_atoi(const char *s) 
    1816 +{ 
    1817 +       int val = 0; 
    1818 + 
    1819 +       for (;; s++) { 
    1820 +               switch (*s) { 
    1821 +                       case '0'...'9': 
    1822 +                       val = 10*val+(*s-'0'); 
    1823 +                       break; 
    1824 +               default: 
    1825 +                       return val; 
    1826 +               } 
    1827 +       } 
    1828 +} 
    1829 + 
    1830 +/* write out num_packets to userland. */ 
    1831 +static int layer7_read_proc(char* page, char ** start, off_t off, int count, 
    1832 +                            int* eof, void * data) 
    1833 +{ 
    1834 +       if(num_packets > 99 && net_ratelimit()) 
    1835 +               printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); 
    1836 + 
    1837 +       page[0] = num_packets/10 + '0'; 
    1838 +       page[1] = num_packets%10 + '0'; 
    1839 +       page[2] = '\n'; 
    1840 +       page[3] = '\0'; 
    1841 + 
    1842 +       *eof=1; 
    1843 + 
    1844 +       return 3; 
    1845 +} 
    1846 + 
    1847 +/* Read in num_packets from userland */ 
    1848 +static int layer7_write_proc(struct file* file, const char* buffer, 
    1849 +                             unsigned long count, void *data) 
    1850 +{ 
    1851 +       char * foo = kmalloc(count, GFP_ATOMIC); 
    1852 + 
    1853 +       if(!foo){ 
    1854 +               if (net_ratelimit()) 
    1855 +                       printk(KERN_ERR "layer7: out of memory, bailing. " 
    1856 +                                       "num_packets unchanged.\n"); 
    1857 +               return count; 
    1858 +       } 
    1859 + 
    1860 +       if(copy_from_user(foo, buffer, count)) { 
    1861 +               return -EFAULT; 
    1862 +       } 
    1863 + 
    1864 + 
    1865 +       num_packets = my_atoi(foo); 
    1866 +       kfree (foo); 
    1867 + 
    1868 +       /* This has an arbitrary limit to make the math easier. I'm lazy. 
    1869 +       But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ 
    1870 +       if(num_packets > 99) { 
    1871 +               printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); 
    1872 +               num_packets = 99; 
    1873 +       } else if(num_packets < 1) { 
    1874 +               printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); 
    1875 +               num_packets = 1; 
    1876 +       } 
    1877 + 
    1878 +       return count; 
    1879 +} 
    1880 + 
    1881 +static bool 
    1882 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    1883 +match(const struct sk_buff *skbin, const struct xt_match_param *par) 
    1884 +#else 
    1885 +match(const struct sk_buff *skbin, 
    1886 +      const struct net_device *in, 
    1887 +      const struct net_device *out, 
    1888 +      const struct xt_match *match, 
    1889 +      const void *matchinfo, 
    1890 +      int offset, 
    1891 +      unsigned int protoff, 
    1892 +      bool *hotdrop) 
    1893 +#endif 
    1894 +{ 
    1895 +       /* sidestep const without getting a compiler warning... */ 
    1896 +       struct sk_buff * skb = (struct sk_buff *)skbin;  
    1897 + 
    1898 +       const struct xt_layer7_info * info =  
    1899 +       #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    1900 +               par->matchinfo; 
    1901 +       #else 
    1902 +               matchinfo; 
    1903 +       #endif 
    1904 + 
    1905 +       enum ip_conntrack_info master_ctinfo, ctinfo; 
    1906 +       struct nf_conn *master_conntrack, *conntrack; 
    1907 +       unsigned char * app_data; 
    1908 +       unsigned int pattern_result, appdatalen; 
    1909 +       regexp * comppattern; 
    1910 + 
    1911 +       /* Be paranoid/incompetent - lock the entire match function. */ 
    1912 +       spin_lock_bh(&l7_lock); 
    1913 + 
    1914 +       if(!can_handle(skb)){ 
    1915 +               DPRINTK("layer7: This is some protocol I can't handle.\n"); 
    1916 +               spin_unlock_bh(&l7_lock); 
    1917 +               return info->invert; 
    1918 +       } 
    1919 + 
    1920 +       /* Treat parent & all its children together as one connection, except 
    1921 +       for the purpose of setting conntrack->layer7.app_proto in the actual 
    1922 +       connection. This makes /proc/net/ip_conntrack more satisfying. */ 
    1923 +       if(!(conntrack = nf_ct_get(skb, &ctinfo)) || 
    1924 +          !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ 
    1925 +               DPRINTK("layer7: couldn't get conntrack.\n"); 
    1926 +               spin_unlock_bh(&l7_lock); 
    1927 +               return info->invert; 
    1928 +       } 
    1929 + 
    1930 +       /* Try to get a master conntrack (and its master etc) for FTP, etc. */ 
    1931 +       while (master_ct(master_conntrack) != NULL) 
    1932 +               master_conntrack = master_ct(master_conntrack); 
    1933 + 
    1934 +       /* if we've classified it or seen too many packets */ 
    1935 +       if(total_acct_packets(master_conntrack) > num_packets || 
    1936 +          master_conntrack->layer7.app_proto) { 
    1937 + 
    1938 +               pattern_result = match_no_append(conntrack, master_conntrack,  
    1939 +                                                ctinfo, master_ctinfo, info); 
    1940 + 
    1941 +               /* skb->cb[0] == seen. Don't do things twice if there are  
    1942 +               multiple l7 rules. I'm not sure that using cb for this purpose  
    1943 +               is correct, even though it says "put your private variables  
    1944 +               there". But it doesn't look like it is being used for anything 
    1945 +               else in the skbs that make it here. */ 
    1946 +               skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ 
    1947 + 
    1948 +               spin_unlock_bh(&l7_lock); 
    1949 +               return (pattern_result ^ info->invert); 
    1950 +       } 
    1951 + 
    1952 +       if(skb_is_nonlinear(skb)){ 
    1953 +               if(skb_linearize(skb) != 0){ 
    1954 +                       if (net_ratelimit()) 
    1955 +                               printk(KERN_ERR "layer7: failed to linearize " 
    1956 +                                               "packet, bailing.\n"); 
    1957 +                       spin_unlock_bh(&l7_lock); 
    1958 +                       return info->invert; 
    1959 +               } 
    1960 +       } 
    1961 + 
    1962 +       /* now that the skb is linearized, it's safe to set these. */ 
    1963 +       app_data = skb->data + app_data_offset(skb); 
    1964 +       appdatalen = skb_tail_pointer(skb) - app_data; 
    1965 + 
    1966 +       /* the return value gets checked later, when we're ready to use it */ 
    1967 +       comppattern = compile_and_cache(info->pattern, info->protocol); 
    1968 + 
    1969 +       /* On the first packet of a connection, allocate space for app data */ 
    1970 +       if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&  
    1971 +          !master_conntrack->layer7.app_data){ 
    1972 +               master_conntrack->layer7.app_data =  
    1973 +                       kmalloc(maxdatalen, GFP_ATOMIC); 
    1974 +               if(!master_conntrack->layer7.app_data){ 
    1975 +                       if (net_ratelimit()) 
    1976 +                               printk(KERN_ERR "layer7: out of memory in " 
    1977 +                                               "match, bailing.\n"); 
    1978 +                       spin_unlock_bh(&l7_lock); 
    1979 +                       return info->invert; 
    1980 +               } 
    1981 + 
    1982 +               master_conntrack->layer7.app_data[0] = '\0'; 
    1983 +       } 
    1984 + 
    1985 +       /* Can be here, but unallocated, if numpackets is increased near 
    1986 +       the beginning of a connection */ 
    1987 +       if(master_conntrack->layer7.app_data == NULL){ 
    1988 +               spin_unlock_bh(&l7_lock); 
    1989 +               return info->invert; /* unmatched */ 
    1990 +       } 
    1991 + 
    1992 +       if(!skb->cb[0]){ 
    1993 +               int newbytes; 
    1994 +               newbytes = add_data(master_conntrack, app_data, appdatalen); 
    1995 + 
    1996 +               if(newbytes == 0) { /* didn't add any data */ 
    1997 +                       skb->cb[0] = 1; 
    1998 +                       /* Didn't match before, not going to match now */ 
    1999 +                       spin_unlock_bh(&l7_lock); 
    2000 +                       return info->invert; 
    2001 +               } 
    2002 +       } 
    2003 + 
    2004 +       /* If looking for "unknown", then never match.  "Unknown" means that 
    2005 +       we've given up; we're still trying with these packets. */ 
    2006 +       if(!strcmp(info->protocol, "unknown")) { 
    2007 +               pattern_result = 0; 
    2008 +       /* If looking for "unset", then always match. "Unset" means that we 
    2009 +       haven't yet classified the connection. */ 
    2010 +       } else if(!strcmp(info->protocol, "unset")) { 
    2011 +               pattern_result = 2; 
    2012 +               DPRINTK("layer7: matched unset: not yet classified " 
    2013 +                       "(%d/%d packets)\n", 
    2014 +                        total_acct_packets(master_conntrack), num_packets); 
    2015 +       /* If the regexp failed to compile, don't bother running it */ 
    2016 +       } else if(comppattern &&  
    2017 +                 regexec(comppattern, master_conntrack->layer7.app_data)){ 
    2018 +               DPRINTK("layer7: matched %s\n", info->protocol); 
    2019 +               pattern_result = 1; 
    2020 +       } else pattern_result = 0; 
    2021 + 
    2022 +       if(pattern_result == 1) { 
    2023 +               master_conntrack->layer7.app_proto =  
    2024 +                       kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); 
    2025 +               if(!master_conntrack->layer7.app_proto){ 
    2026 +                       if (net_ratelimit()) 
    2027 +                               printk(KERN_ERR "layer7: out of memory in " 
    2028 +                                               "match, bailing.\n"); 
    2029 +                       spin_unlock_bh(&l7_lock); 
    2030 +                       return (pattern_result ^ info->invert); 
    2031 +               } 
    2032 +               strcpy(master_conntrack->layer7.app_proto, info->protocol); 
    2033 +       } else if(pattern_result > 1) { /* cleanup from "unset" */ 
    2034 +               pattern_result = 1; 
    2035 +       } 
    2036 + 
    2037 +       /* mark the packet seen */ 
    2038 +       skb->cb[0] = 1; 
    2039 + 
    2040 +       spin_unlock_bh(&l7_lock); 
    2041 +       return (pattern_result ^ info->invert); 
    2042 +} 
    2043 + 
    2044 +// load nf_conntrack_ipv4 
    2045 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    2046 +static bool check(const struct xt_mtchk_param *par) 
    2047 +{ 
    2048 +        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { 
    2049 +                printk(KERN_WARNING "can't load conntrack support for " 
    2050 +                                    "proto=%d\n", par->match->family); 
    2051 +#else 
    2052 +static bool check(const char *tablename, const void *inf, 
    2053 +                const struct xt_match *match, void *matchinfo, 
    2054 +                unsigned int hook_mask) 
    2055 +{ 
    2056 +        if (nf_ct_l3proto_try_module_get(match->family) < 0) { 
    2057 +                printk(KERN_WARNING "can't load conntrack support for " 
    2058 +                                    "proto=%d\n", match->family); 
    2059 +#endif 
    2060 +                return 0; 
    2061 +        } 
    2062 +       return 1; 
    2063 +} 
    2064 + 
    2065 + 
    2066 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
    2067 +       static void destroy(const struct xt_mtdtor_param *par) 
    2068 +       { 
    2069 +               nf_ct_l3proto_module_put(par->match->family); 
    2070 +       } 
    2071 +#else 
    2072 +       static void destroy(const struct xt_match *match, void *matchinfo) 
    2073 +       { 
    2074 +               nf_ct_l3proto_module_put(match->family); 
    2075 +       } 
    2076 +#endif 
    2077 + 
    2078 +static struct xt_match xt_layer7_match[] __read_mostly = { 
    2079 +{ 
    2080 +       .name           = "layer7", 
    2081 +       .family         = AF_INET, 
    2082 +       .checkentry     = check, 
    2083 +       .match          = match, 
    2084 +       .destroy        = destroy, 
    2085 +       .matchsize      = sizeof(struct xt_layer7_info), 
    2086 +       .me             = THIS_MODULE 
    2087 +} 
     2118+++ b/include/linux/netfilter/xt_layer7.h 
     2119@@ -0,0 +1,13 @@ 
     2120+#ifndef _XT_LAYER7_H 
     2121+#define _XT_LAYER7_H 
     2122+ 
     2123+#define MAX_PATTERN_LEN 8192 
     2124+#define MAX_PROTOCOL_LEN 256 
     2125+ 
     2126+struct xt_layer7_info { 
     2127+    char protocol[MAX_PROTOCOL_LEN]; 
     2128+    char pattern[MAX_PATTERN_LEN]; 
     2129+    u_int8_t invert; 
    20882130+}; 
    20892131+ 
    2090 +static void layer7_cleanup_proc(void) 
    2091 +{ 
    2092 +       remove_proc_entry("layer7_numpackets", init_net.proc_net); 
    2093 +} 
    2094 + 
    2095 +/* register the proc file */ 
    2096 +static void layer7_init_proc(void) 
    2097 +{ 
    2098 +       struct proc_dir_entry* entry; 
    2099 +       entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net); 
    2100 +       entry->read_proc = layer7_read_proc; 
    2101 +       entry->write_proc = layer7_write_proc; 
    2102 +} 
    2103 + 
    2104 +static int __init xt_layer7_init(void) 
    2105 +{ 
    2106 +       need_conntrack(); 
    2107 + 
    2108 +       layer7_init_proc(); 
    2109 +       if(maxdatalen < 1) { 
    2110 +               printk(KERN_WARNING "layer7: maxdatalen can't be < 1, " 
    2111 +                       "using 1\n"); 
    2112 +               maxdatalen = 1; 
    2113 +       } 
    2114 +       /* This is not a hard limit.  It's just here to prevent people from 
    2115 +       bringing their slow machines to a grinding halt. */ 
    2116 +       else if(maxdatalen > 65536) { 
    2117 +               printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, " 
    2118 +                       "using 65536\n"); 
    2119 +               maxdatalen = 65536; 
    2120 +       } 
    2121 +       return xt_register_matches(xt_layer7_match, 
    2122 +                                  ARRAY_SIZE(xt_layer7_match)); 
    2123 +} 
    2124 + 
    2125 +static void __exit xt_layer7_fini(void) 
    2126 +{ 
    2127 +       layer7_cleanup_proc(); 
    2128 +       xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match)); 
    2129 +} 
    2130 + 
    2131 +module_init(xt_layer7_init); 
    2132 +module_exit(xt_layer7_fini); 
     2132+#endif /* _XT_LAYER7_H */ 
Note: See TracChangeset for help on using the changeset viewer.