source: trunk/target/linux/generic/patches-2.6.39/100-netfilter_layer7_2.22.patch @ 26615

Last change on this file since 26615 was 26615, checked in by nbd, 5 years ago

generic: Add support for 2.6.39

Add support for 2.6.39 based on rc3. Runtime tested on bcm63xx.

File size: 56.7 KB
  • net/netfilter/Kconfig

    a b config NETFILTER_XT_MATCH_STATE 
    10201020 
    10211021          To compile it as a module, choose M here.  If unsure, say N. 
    10221022 
     1023config NETFILTER_XT_MATCH_LAYER7 
     1024        tristate '"layer7" match support' 
     1025        depends on NETFILTER_XTABLES 
     1026        depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK) 
     1027       depends on NETFILTER_ADVANCED 
     1028        help 
     1029          Say Y if you want to be able to classify connections (and their 
     1030          packets) based on regular expression matching of their application 
     1031          layer data.   This is one way to classify applications such as 
     1032          peer-to-peer filesharing systems that do not always use the same 
     1033          port. 
     1034 
     1035          To compile it as a module, choose M here.  If unsure, say N. 
     1036 
     1037config NETFILTER_XT_MATCH_LAYER7_DEBUG 
     1038        bool 'Layer 7 debugging output' 
     1039        depends on NETFILTER_XT_MATCH_LAYER7 
     1040        help 
     1041          Say Y to get lots of debugging output. 
     1042 
     1043 
    10231044config NETFILTER_XT_MATCH_STATISTIC 
    10241045        tristate '"statistic" match support' 
    10251046        depends on NETFILTER_ADVANCED 
  • net/netfilter/Makefile

    a b obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT)  
    102102obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o 
    103103obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o 
    104104obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o 
     105obj-$(CONFIG_NETFILTER_XT_MATCH_LAYER7) += xt_layer7.o 
    105106obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o 
    106107obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o 
    107108obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o 
  • new file net/netfilter/xt_layer7.c

    - +  
     1/* 
     2  Kernel module to match application layer (OSI layer 7) data in connections. 
     3 
     4  http://l7-filter.sf.net 
     5 
     6  (C) 2003-2009 Matthew Strait and Ethan Sommer. 
     7 
     8  This program is free software; you can redistribute it and/or 
     9  modify it under the terms of the GNU General Public License 
     10  as published by the Free Software Foundation; either version 
     11  2 of the License, or (at your option) any later version. 
     12  http://www.gnu.org/licenses/gpl.txt 
     13 
     14  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>, 
     15  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait, 
     16  Ethan Sommer, Justin Levandoski. 
     17*/ 
     18 
     19#include <linux/spinlock.h> 
     20#include <linux/version.h> 
     21#include <net/ip.h> 
     22#include <net/tcp.h> 
     23#include <linux/module.h> 
     24#include <linux/skbuff.h> 
     25#include <linux/netfilter.h> 
     26#include <net/netfilter/nf_conntrack.h> 
     27#include <net/netfilter/nf_conntrack_core.h> 
     28#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) 
     29#include <net/netfilter/nf_conntrack_extend.h> 
     30#include <net/netfilter/nf_conntrack_acct.h> 
     31#endif 
     32#include <linux/netfilter/x_tables.h> 
     33#include <linux/netfilter/xt_layer7.h> 
     34#include <linux/ctype.h> 
     35#include <linux/proc_fs.h> 
     36 
     37#include "regexp/regexp.c" 
     38 
     39MODULE_LICENSE("GPL"); 
     40MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); 
     41MODULE_DESCRIPTION("iptables application layer match module"); 
     42MODULE_ALIAS("ipt_layer7"); 
     43MODULE_VERSION("2.21"); 
     44 
     45static int maxdatalen = 2048; // this is the default 
     46module_param(maxdatalen, int, 0444); 
     47MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); 
     48#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG 
     49        #define DPRINTK(format,args...) printk(format,##args) 
     50#else 
     51        #define DPRINTK(format,args...) 
     52#endif 
     53 
     54/* Number of packets whose data we look at. 
     55This can be modified through /proc/net/layer7_numpackets */ 
     56static int num_packets = 10; 
     57 
     58static struct pattern_cache { 
     59        char * regex_string; 
     60        regexp * pattern; 
     61        struct pattern_cache * next; 
     62} * first_pattern_cache = NULL; 
     63 
     64DEFINE_SPINLOCK(l7_lock); 
     65 
     66static int total_acct_packets(struct nf_conn *ct) 
     67{ 
     68#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) 
     69        BUG_ON(ct == NULL); 
     70        return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets); 
     71#else 
     72        struct nf_conn_counter *acct; 
     73 
     74        BUG_ON(ct == NULL); 
     75        acct = nf_conn_acct_find(ct); 
     76        if (!acct) 
     77                return 0; 
     78        return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets); 
     79#endif 
     80} 
     81 
     82#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
     83/* Converts an unfriendly string into a friendly one by 
     84replacing unprintables with periods and all whitespace with " ". */ 
     85static char * friendly_print(unsigned char * s) 
     86{ 
     87        char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); 
     88        int i; 
     89 
     90        if(!f) { 
     91                if (net_ratelimit()) 
     92                        printk(KERN_ERR "layer7: out of memory in " 
     93                                        "friendly_print, bailing.\n"); 
     94                return NULL; 
     95        } 
     96 
     97        for(i = 0; i < strlen(s); i++){ 
     98                if(isprint(s[i]) && s[i] < 128) f[i] = s[i]; 
     99                else if(isspace(s[i]))          f[i] = ' '; 
     100                else                            f[i] = '.'; 
     101        } 
     102        f[i] = '\0'; 
     103        return f; 
     104} 
     105 
     106static char dec2hex(int i) 
     107{ 
     108        switch (i) { 
     109                case 0 ... 9: 
     110                        return (i + '0'); 
     111                        break; 
     112                case 10 ... 15: 
     113                        return (i - 10 + 'a'); 
     114                        break; 
     115                default: 
     116                        if (net_ratelimit()) 
     117                                printk("layer7: Problem in dec2hex\n"); 
     118                        return '\0'; 
     119        } 
     120} 
     121 
     122static char * hex_print(unsigned char * s) 
     123{ 
     124        char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); 
     125        int i; 
     126 
     127        if(!g) { 
     128               if (net_ratelimit()) 
     129                        printk(KERN_ERR "layer7: out of memory in hex_print, " 
     130                                        "bailing.\n"); 
     131               return NULL; 
     132        } 
     133 
     134        for(i = 0; i < strlen(s); i++) { 
     135                g[i*3    ] = dec2hex(s[i]/16); 
     136                g[i*3 + 1] = dec2hex(s[i]%16); 
     137                g[i*3 + 2] = ' '; 
     138        } 
     139        g[i*3] = '\0'; 
     140 
     141        return g; 
     142} 
     143#endif // DEBUG 
     144 
     145/* Use instead of regcomp.  As we expect to be seeing the same regexps over and 
     146over again, it make sense to cache the results. */ 
     147static regexp * compile_and_cache(const char * regex_string,  
     148                                  const char * protocol) 
     149{ 
     150        struct pattern_cache * node               = first_pattern_cache; 
     151        struct pattern_cache * last_pattern_cache = first_pattern_cache; 
     152        struct pattern_cache * tmp; 
     153        unsigned int len; 
     154 
     155        while (node != NULL) { 
     156                if (!strcmp(node->regex_string, regex_string)) 
     157                return node->pattern; 
     158 
     159                last_pattern_cache = node;/* points at the last non-NULL node */ 
     160                node = node->next; 
     161        } 
     162 
     163        /* If we reach the end of the list, then we have not yet cached 
     164           the pattern for this regex. Let's do that now. 
     165           Be paranoid about running out of memory to avoid list corruption. */ 
     166        tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); 
     167 
     168        if(!tmp) { 
     169                if (net_ratelimit()) 
     170                        printk(KERN_ERR "layer7: out of memory in " 
     171                                        "compile_and_cache, bailing.\n"); 
     172                return NULL; 
     173        } 
     174 
     175        tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); 
     176        tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC); 
     177        tmp->next = NULL; 
     178 
     179        if(!tmp->regex_string || !tmp->pattern) { 
     180                if (net_ratelimit()) 
     181                        printk(KERN_ERR "layer7: out of memory in " 
     182                                        "compile_and_cache, bailing.\n"); 
     183                kfree(tmp->regex_string); 
     184                kfree(tmp->pattern); 
     185                kfree(tmp); 
     186                return NULL; 
     187        } 
     188 
     189        /* Ok.  The new node is all ready now. */ 
     190        node = tmp; 
     191 
     192        if(first_pattern_cache == NULL) /* list is empty */ 
     193                first_pattern_cache = node; /* make node the beginning */ 
     194        else 
     195                last_pattern_cache->next = node; /* attach node to the end */ 
     196 
     197        /* copy the string and compile the regex */ 
     198        len = strlen(regex_string); 
     199        DPRINTK("About to compile this: \"%s\"\n", regex_string); 
     200        node->pattern = regcomp((char *)regex_string, &len); 
     201        if ( !node->pattern ) { 
     202                if (net_ratelimit()) 
     203                        printk(KERN_ERR "layer7: Error compiling regexp " 
     204                                        "\"%s\" (%s)\n",  
     205                                        regex_string, protocol); 
     206                /* pattern is now cached as NULL, so we won't try again. */ 
     207        } 
     208 
     209        strcpy(node->regex_string, regex_string); 
     210        return node->pattern; 
     211} 
     212 
     213static int can_handle(const struct sk_buff *skb) 
     214{ 
     215        if(!ip_hdr(skb)) /* not IP */ 
     216                return 0; 
     217        if(ip_hdr(skb)->protocol != IPPROTO_TCP && 
     218           ip_hdr(skb)->protocol != IPPROTO_UDP && 
     219           ip_hdr(skb)->protocol != IPPROTO_ICMP) 
     220                return 0; 
     221        return 1; 
     222} 
     223 
     224/* Returns offset the into the skb->data that the application data starts */ 
     225static int app_data_offset(const struct sk_buff *skb) 
     226{ 
     227        /* In case we are ported somewhere (ebtables?) where ip_hdr(skb) 
     228        isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ 
     229        int ip_hl = 4*ip_hdr(skb)->ihl; 
     230 
     231        if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { 
     232                /* 12 == offset into TCP header for the header length field. 
     233                Can't get this with skb->h.th->doff because the tcphdr 
     234                struct doesn't get set when routing (this is confirmed to be 
     235                true in Netfilter as well as QoS.) */ 
     236                int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); 
     237 
     238                return ip_hl + tcp_hl; 
     239        } else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) { 
     240                return ip_hl + 8; /* UDP header is always 8 bytes */ 
     241        } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { 
     242                return ip_hl + 8; /* ICMP header is 8 bytes */ 
     243        } else { 
     244                if (net_ratelimit()) 
     245                        printk(KERN_ERR "layer7: tried to handle unknown " 
     246                                        "protocol!\n"); 
     247                return ip_hl + 8; /* something reasonable */ 
     248        } 
     249} 
     250 
     251/* handles whether there's a match when we aren't appending data anymore */ 
     252static int match_no_append(struct nf_conn * conntrack,  
     253                           struct nf_conn * master_conntrack,  
     254                           enum ip_conntrack_info ctinfo, 
     255                           enum ip_conntrack_info master_ctinfo, 
     256                           const struct xt_layer7_info * info) 
     257{ 
     258        /* If we're in here, throw the app data away */ 
     259        if(master_conntrack->layer7.app_data != NULL) { 
     260 
     261        #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG 
     262                if(!master_conntrack->layer7.app_proto) { 
     263                        char * f =  
     264                          friendly_print(master_conntrack->layer7.app_data); 
     265                        char * g =  
     266                          hex_print(master_conntrack->layer7.app_data); 
     267                        DPRINTK("\nl7-filter gave up after %d bytes " 
     268                                "(%d packets):\n%s\n", 
     269                                strlen(f), total_acct_packets(master_conntrack), f); 
     270                        kfree(f); 
     271                        DPRINTK("In hex: %s\n", g); 
     272                        kfree(g); 
     273                } 
     274        #endif 
     275 
     276                kfree(master_conntrack->layer7.app_data); 
     277                master_conntrack->layer7.app_data = NULL; /* don't free again */ 
     278        } 
     279 
     280        if(master_conntrack->layer7.app_proto){ 
     281                /* Here child connections set their .app_proto (for /proc) */ 
     282                if(!conntrack->layer7.app_proto) { 
     283                        conntrack->layer7.app_proto =  
     284                          kmalloc(strlen(master_conntrack->layer7.app_proto)+1,  
     285                            GFP_ATOMIC); 
     286                        if(!conntrack->layer7.app_proto){ 
     287                                if (net_ratelimit()) 
     288                                        printk(KERN_ERR "layer7: out of memory " 
     289                                                        "in match_no_append, " 
     290                                                        "bailing.\n"); 
     291                                return 1; 
     292                        } 
     293                        strcpy(conntrack->layer7.app_proto,  
     294                                master_conntrack->layer7.app_proto); 
     295                } 
     296 
     297                return (!strcmp(master_conntrack->layer7.app_proto,  
     298                                info->protocol)); 
     299        } 
     300        else { 
     301                /* If not classified, set to "unknown" to distinguish from 
     302                connections that are still being tested. */ 
     303                master_conntrack->layer7.app_proto =  
     304                        kmalloc(strlen("unknown")+1, GFP_ATOMIC); 
     305                if(!master_conntrack->layer7.app_proto){ 
     306                        if (net_ratelimit()) 
     307                                printk(KERN_ERR "layer7: out of memory in " 
     308                                                "match_no_append, bailing.\n"); 
     309                        return 1; 
     310                } 
     311                strcpy(master_conntrack->layer7.app_proto, "unknown"); 
     312                return 0; 
     313        } 
     314} 
     315 
     316/* add the new app data to the conntrack.  Return number of bytes added. */ 
     317static int add_data(struct nf_conn * master_conntrack, 
     318                    char * app_data, int appdatalen) 
     319{ 
     320        int length = 0, i; 
     321        int oldlength = master_conntrack->layer7.app_data_len; 
     322 
     323        /* This is a fix for a race condition by Deti Fliegl. However, I'm not  
     324           clear on whether the race condition exists or whether this really  
     325           fixes it.  I might just be being dense... Anyway, if it's not really  
     326           a fix, all it does is waste a very small amount of time. */ 
     327        if(!master_conntrack->layer7.app_data) return 0; 
     328 
     329        /* Strip nulls. Make everything lower case (our regex lib doesn't 
     330        do case insensitivity).  Add it to the end of the current data. */ 
     331        for(i = 0; i < maxdatalen-oldlength-1 && 
     332                   i < appdatalen; i++) { 
     333                if(app_data[i] != '\0') { 
     334                        /* the kernel version of tolower mungs 'upper ascii' */ 
     335                        master_conntrack->layer7.app_data[length+oldlength] = 
     336                                isascii(app_data[i])?  
     337                                        tolower(app_data[i]) : app_data[i]; 
     338                        length++; 
     339                } 
     340        } 
     341 
     342        master_conntrack->layer7.app_data[length+oldlength] = '\0'; 
     343        master_conntrack->layer7.app_data_len = length + oldlength; 
     344 
     345        return length; 
     346} 
     347 
     348/* taken from drivers/video/modedb.c */ 
     349static int my_atoi(const char *s) 
     350{ 
     351        int val = 0; 
     352 
     353        for (;; s++) { 
     354                switch (*s) { 
     355                        case '0'...'9': 
     356                        val = 10*val+(*s-'0'); 
     357                        break; 
     358                default: 
     359                        return val; 
     360                } 
     361        } 
     362} 
     363 
     364/* write out num_packets to userland. */ 
     365static int layer7_read_proc(char* page, char ** start, off_t off, int count, 
     366                            int* eof, void * data) 
     367{ 
     368        if(num_packets > 99 && net_ratelimit()) 
     369                printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); 
     370 
     371        page[0] = num_packets/10 + '0'; 
     372        page[1] = num_packets%10 + '0'; 
     373        page[2] = '\n'; 
     374        page[3] = '\0'; 
     375 
     376        *eof=1; 
     377 
     378        return 3; 
     379} 
     380 
     381/* Read in num_packets from userland */ 
     382static int layer7_write_proc(struct file* file, const char* buffer, 
     383                             unsigned long count, void *data) 
     384{ 
     385        char * foo = kmalloc(count, GFP_ATOMIC); 
     386 
     387        if(!foo){ 
     388                if (net_ratelimit()) 
     389                        printk(KERN_ERR "layer7: out of memory, bailing. " 
     390                                        "num_packets unchanged.\n"); 
     391                return count; 
     392        } 
     393 
     394        if(copy_from_user(foo, buffer, count)) { 
     395                return -EFAULT; 
     396        } 
     397 
     398 
     399        num_packets = my_atoi(foo); 
     400        kfree (foo); 
     401 
     402        /* This has an arbitrary limit to make the math easier. I'm lazy. 
     403        But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ 
     404        if(num_packets > 99) { 
     405                printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); 
     406                num_packets = 99; 
     407        } else if(num_packets < 1) { 
     408                printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); 
     409                num_packets = 1; 
     410        } 
     411 
     412        return count; 
     413} 
     414 
     415static bool 
     416#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     417match(const struct sk_buff *skbin, const struct xt_match_param *par) 
     418#else 
     419match(const struct sk_buff *skbin, 
     420      const struct net_device *in, 
     421      const struct net_device *out, 
     422      const struct xt_match *match, 
     423      const void *matchinfo, 
     424      int offset, 
     425      unsigned int protoff, 
     426      bool *hotdrop) 
     427#endif 
     428{ 
     429        /* sidestep const without getting a compiler warning... */ 
     430        struct sk_buff * skb = (struct sk_buff *)skbin;  
     431 
     432        const struct xt_layer7_info * info =  
     433        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     434                par->matchinfo; 
     435        #else 
     436                matchinfo; 
     437        #endif 
     438 
     439        enum ip_conntrack_info master_ctinfo, ctinfo; 
     440        struct nf_conn *master_conntrack, *conntrack; 
     441        unsigned char * app_data; 
     442        unsigned int pattern_result, appdatalen; 
     443        regexp * comppattern; 
     444 
     445        /* Be paranoid/incompetent - lock the entire match function. */ 
     446        spin_lock_bh(&l7_lock); 
     447 
     448        if(!can_handle(skb)){ 
     449                DPRINTK("layer7: This is some protocol I can't handle.\n"); 
     450                spin_unlock_bh(&l7_lock); 
     451                return info->invert; 
     452        } 
     453 
     454        /* Treat parent & all its children together as one connection, except 
     455        for the purpose of setting conntrack->layer7.app_proto in the actual 
     456        connection. This makes /proc/net/ip_conntrack more satisfying. */ 
     457        if(!(conntrack = nf_ct_get(skb, &ctinfo)) || 
     458           !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ 
     459                DPRINTK("layer7: couldn't get conntrack.\n"); 
     460                spin_unlock_bh(&l7_lock); 
     461                return info->invert; 
     462        } 
     463 
     464        /* Try to get a master conntrack (and its master etc) for FTP, etc. */ 
     465        while (master_ct(master_conntrack) != NULL) 
     466                master_conntrack = master_ct(master_conntrack); 
     467 
     468        /* if we've classified it or seen too many packets */ 
     469        if(total_acct_packets(master_conntrack) > num_packets || 
     470           master_conntrack->layer7.app_proto) { 
     471 
     472                pattern_result = match_no_append(conntrack, master_conntrack,  
     473                                                 ctinfo, master_ctinfo, info); 
     474 
     475                /* skb->cb[0] == seen. Don't do things twice if there are  
     476                multiple l7 rules. I'm not sure that using cb for this purpose  
     477                is correct, even though it says "put your private variables  
     478                there". But it doesn't look like it is being used for anything 
     479                else in the skbs that make it here. */ 
     480                skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ 
     481 
     482                spin_unlock_bh(&l7_lock); 
     483                return (pattern_result ^ info->invert); 
     484        } 
     485 
     486        if(skb_is_nonlinear(skb)){ 
     487                if(skb_linearize(skb) != 0){ 
     488                        if (net_ratelimit()) 
     489                                printk(KERN_ERR "layer7: failed to linearize " 
     490                                                "packet, bailing.\n"); 
     491                        spin_unlock_bh(&l7_lock); 
     492                        return info->invert; 
     493                } 
     494        } 
     495 
     496        /* now that the skb is linearized, it's safe to set these. */ 
     497        app_data = skb->data + app_data_offset(skb); 
     498        appdatalen = skb_tail_pointer(skb) - app_data; 
     499 
     500        /* the return value gets checked later, when we're ready to use it */ 
     501        comppattern = compile_and_cache(info->pattern, info->protocol); 
     502 
     503        /* On the first packet of a connection, allocate space for app data */ 
     504        if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&  
     505           !master_conntrack->layer7.app_data){ 
     506                master_conntrack->layer7.app_data =  
     507                        kmalloc(maxdatalen, GFP_ATOMIC); 
     508                if(!master_conntrack->layer7.app_data){ 
     509                        if (net_ratelimit()) 
     510                                printk(KERN_ERR "layer7: out of memory in " 
     511                                                "match, bailing.\n"); 
     512                        spin_unlock_bh(&l7_lock); 
     513                        return info->invert; 
     514                } 
     515 
     516                master_conntrack->layer7.app_data[0] = '\0'; 
     517        } 
     518 
     519        /* Can be here, but unallocated, if numpackets is increased near 
     520        the beginning of a connection */ 
     521        if(master_conntrack->layer7.app_data == NULL){ 
     522                spin_unlock_bh(&l7_lock); 
     523                return info->invert; /* unmatched */ 
     524        } 
     525 
     526        if(!skb->cb[0]){ 
     527                int newbytes; 
     528                newbytes = add_data(master_conntrack, app_data, appdatalen); 
     529 
     530                if(newbytes == 0) { /* didn't add any data */ 
     531                        skb->cb[0] = 1; 
     532                        /* Didn't match before, not going to match now */ 
     533                        spin_unlock_bh(&l7_lock); 
     534                        return info->invert; 
     535                } 
     536        } 
     537 
     538        /* If looking for "unknown", then never match.  "Unknown" means that 
     539        we've given up; we're still trying with these packets. */ 
     540        if(!strcmp(info->protocol, "unknown")) { 
     541                pattern_result = 0; 
     542        /* If looking for "unset", then always match. "Unset" means that we 
     543        haven't yet classified the connection. */ 
     544        } else if(!strcmp(info->protocol, "unset")) { 
     545                pattern_result = 2; 
     546                DPRINTK("layer7: matched unset: not yet classified " 
     547                        "(%d/%d packets)\n", 
     548                        total_acct_packets(master_conntrack), num_packets); 
     549        /* If the regexp failed to compile, don't bother running it */ 
     550        } else if(comppattern &&  
     551                  regexec(comppattern, master_conntrack->layer7.app_data)){ 
     552                DPRINTK("layer7: matched %s\n", info->protocol); 
     553                pattern_result = 1; 
     554        } else pattern_result = 0; 
     555 
     556        if(pattern_result == 1) { 
     557                master_conntrack->layer7.app_proto =  
     558                        kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); 
     559                if(!master_conntrack->layer7.app_proto){ 
     560                        if (net_ratelimit()) 
     561                                printk(KERN_ERR "layer7: out of memory in " 
     562                                                "match, bailing.\n"); 
     563                        spin_unlock_bh(&l7_lock); 
     564                        return (pattern_result ^ info->invert); 
     565                } 
     566                strcpy(master_conntrack->layer7.app_proto, info->protocol); 
     567        } else if(pattern_result > 1) { /* cleanup from "unset" */ 
     568                pattern_result = 1; 
     569        } 
     570 
     571        /* mark the packet seen */ 
     572        skb->cb[0] = 1; 
     573 
     574        spin_unlock_bh(&l7_lock); 
     575        return (pattern_result ^ info->invert); 
     576} 
     577 
     578// load nf_conntrack_ipv4 
     579#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     580static bool check(const struct xt_mtchk_param *par) 
     581{ 
     582        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { 
     583                printk(KERN_WARNING "can't load conntrack support for " 
     584                                    "proto=%d\n", par->match->family); 
     585#else 
     586static bool check(const char *tablename, const void *inf, 
     587                 const struct xt_match *match, void *matchinfo, 
     588                 unsigned int hook_mask) 
     589{ 
     590        if (nf_ct_l3proto_try_module_get(match->family) < 0) { 
     591                printk(KERN_WARNING "can't load conntrack support for " 
     592                                    "proto=%d\n", match->family); 
     593#endif 
     594                return 0; 
     595        } 
     596        return 1; 
     597} 
     598 
     599 
     600#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) 
     601        static void destroy(const struct xt_mtdtor_param *par) 
     602        { 
     603                nf_ct_l3proto_module_put(par->match->family); 
     604        } 
     605#else 
     606        static void destroy(const struct xt_match *match, void *matchinfo) 
     607        { 
     608                nf_ct_l3proto_module_put(match->family); 
     609        } 
     610#endif 
     611 
     612static struct xt_match xt_layer7_match[] __read_mostly = { 
     613{ 
     614        .name           = "layer7", 
     615        .family         = AF_INET, 
     616        .checkentry     = check, 
     617        .match          = match, 
     618        .destroy        = destroy, 
     619        .matchsize      = sizeof(struct xt_layer7_info), 
     620        .me             = THIS_MODULE 
     621} 
     622}; 
     623 
     624static void layer7_cleanup_proc(void) 
     625{ 
     626        remove_proc_entry("layer7_numpackets", init_net.proc_net); 
     627} 
     628 
     629/* register the proc file */ 
     630static void layer7_init_proc(void) 
     631{ 
     632        struct proc_dir_entry* entry; 
     633        entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net); 
     634        entry->read_proc = layer7_read_proc; 
     635        entry->write_proc = layer7_write_proc; 
     636} 
     637 
     638static int __init xt_layer7_init(void) 
     639{ 
     640        need_conntrack(); 
     641 
     642        layer7_init_proc(); 
     643        if(maxdatalen < 1) { 
     644                printk(KERN_WARNING "layer7: maxdatalen can't be < 1, " 
     645                        "using 1\n"); 
     646                maxdatalen = 1; 
     647        } 
     648        /* This is not a hard limit.  It's just here to prevent people from 
     649        bringing their slow machines to a grinding halt. */ 
     650        else if(maxdatalen > 65536) { 
     651                printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, " 
     652                        "using 65536\n"); 
     653                maxdatalen = 65536; 
     654        } 
     655        return xt_register_matches(xt_layer7_match, 
     656                                   ARRAY_SIZE(xt_layer7_match)); 
     657} 
     658 
     659static void __exit xt_layer7_fini(void) 
     660{ 
     661        layer7_cleanup_proc(); 
     662        xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match)); 
     663} 
     664 
     665module_init(xt_layer7_init); 
     666module_exit(xt_layer7_fini); 
  • new file net/netfilter/regexp/regexp.c

    - +  
     1/* 
     2 * regcomp and regexec -- regsub and regerror are elsewhere 
     3 * @(#)regexp.c 1.3 of 18 April 87 
     4 * 
     5 *      Copyright (c) 1986 by University of Toronto. 
     6 *      Written by Henry Spencer.  Not derived from licensed software. 
     7 * 
     8 *      Permission is granted to anyone to use this software for any 
     9 *      purpose on any computer system, and to redistribute it freely, 
     10 *      subject to the following restrictions: 
     11 * 
     12 *      1. The author is not responsible for the consequences of use of 
     13 *              this software, no matter how awful, even if they arise 
     14 *              from defects in it. 
     15 * 
     16 *      2. The origin of this software must not be misrepresented, either 
     17 *              by explicit claim or by omission. 
     18 * 
     19 *      3. Altered versions must be plainly marked as such, and must not 
     20 *              be misrepresented as being the original software. 
     21 * 
     22 * Beware that some of this code is subtly aware of the way operator 
     23 * precedence is structured in regular expressions.  Serious changes in 
     24 * regular-expression syntax might require a total rethink. 
     25 * 
     26 * This code was modified by Ethan Sommer to work within the kernel 
     27 * (it now uses kmalloc etc..) 
     28 * 
     29 * Modified slightly by Matthew Strait to use more modern C. 
     30 */ 
     31 
     32#include "regexp.h" 
     33#include "regmagic.h" 
     34 
     35/* added by ethan and matt.  Lets it work in both kernel and user space. 
     36(So iptables can use it, for instance.)  Yea, it goes both ways... */ 
     37#if __KERNEL__ 
     38  #define malloc(foo) kmalloc(foo,GFP_ATOMIC) 
     39#else 
     40  #define printk(format,args...) printf(format,##args) 
     41#endif 
     42 
     43void regerror(char * s) 
     44{ 
     45        printk("<3>Regexp: %s\n", s); 
     46        /* NOTREACHED */ 
     47} 
     48 
     49/* 
     50 * The "internal use only" fields in regexp.h are present to pass info from 
     51 * compile to execute that permits the execute phase to run lots faster on 
     52 * simple cases.  They are: 
     53 * 
     54 * regstart     char that must begin a match; '\0' if none obvious 
     55 * reganch      is the match anchored (at beginning-of-line only)? 
     56 * regmust      string (pointer into program) that match must include, or NULL 
     57 * regmlen      length of regmust string 
     58 * 
     59 * Regstart and reganch permit very fast decisions on suitable starting points 
     60 * for a match, cutting down the work a lot.  Regmust permits fast rejection 
     61 * of lines that cannot possibly match.  The regmust tests are costly enough 
     62 * that regcomp() supplies a regmust only if the r.e. contains something 
     63 * potentially expensive (at present, the only such thing detected is * or + 
     64 * at the start of the r.e., which can involve a lot of backup).  Regmlen is 
     65 * supplied because the test in regexec() needs it and regcomp() is computing 
     66 * it anyway. 
     67 */ 
     68 
     69/* 
     70 * Structure for regexp "program".  This is essentially a linear encoding 
     71 * of a nondeterministic finite-state machine (aka syntax charts or 
     72 * "railroad normal form" in parsing technology).  Each node is an opcode 
     73 * plus a "next" pointer, possibly plus an operand.  "Next" pointers of 
     74 * all nodes except BRANCH implement concatenation; a "next" pointer with 
     75 * a BRANCH on both ends of it is connecting two alternatives.  (Here we 
     76 * have one of the subtle syntax dependencies:  an individual BRANCH (as 
     77 * opposed to a collection of them) is never concatenated with anything 
     78 * because of operator precedence.)  The operand of some types of node is 
     79 * a literal string; for others, it is a node leading into a sub-FSM.  In 
     80 * particular, the operand of a BRANCH node is the first node of the branch. 
     81 * (NB this is *not* a tree structure:  the tail of the branch connects 
     82 * to the thing following the set of BRANCHes.)  The opcodes are: 
     83 */ 
     84 
     85/* definition   number  opnd?   meaning */ 
     86#define END     0       /* no   End of program. */ 
     87#define BOL     1       /* no   Match "" at beginning of line. */ 
     88#define EOL     2       /* no   Match "" at end of line. */ 
     89#define ANY     3       /* no   Match any one character. */ 
     90#define ANYOF   4       /* str  Match any character in this string. */ 
     91#define ANYBUT  5       /* str  Match any character not in this string. */ 
     92#define BRANCH  6       /* node Match this alternative, or the next... */ 
     93#define BACK    7       /* no   Match "", "next" ptr points backward. */ 
     94#define EXACTLY 8       /* str  Match this string. */ 
     95#define NOTHING 9       /* no   Match empty string. */ 
     96#define STAR    10      /* node Match this (simple) thing 0 or more times. */ 
     97#define PLUS    11      /* node Match this (simple) thing 1 or more times. */ 
     98#define OPEN    20      /* no   Mark this point in input as start of #n. */ 
     99                        /*      OPEN+1 is number 1, etc. */ 
     100#define CLOSE   30      /* no   Analogous to OPEN. */ 
     101 
     102/* 
     103 * Opcode notes: 
     104 * 
     105 * BRANCH       The set of branches constituting a single choice are hooked 
     106 *              together with their "next" pointers, since precedence prevents 
     107 *              anything being concatenated to any individual branch.  The 
     108 *              "next" pointer of the last BRANCH in a choice points to the 
     109 *              thing following the whole choice.  This is also where the 
     110 *              final "next" pointer of each individual branch points; each 
     111 *              branch starts with the operand node of a BRANCH node. 
     112 * 
     113 * BACK         Normal "next" pointers all implicitly point forward; BACK 
     114 *              exists to make loop structures possible. 
     115 * 
     116 * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular 
     117 *              BRANCH structures using BACK.  Simple cases (one character 
     118 *              per match) are implemented with STAR and PLUS for speed 
     119 *              and to minimize recursive plunges. 
     120 * 
     121 * OPEN,CLOSE   ...are numbered at compile time. 
     122 */ 
     123 
     124/* 
     125 * A node is one char of opcode followed by two chars of "next" pointer. 
     126 * "Next" pointers are stored as two 8-bit pieces, high order first.  The 
     127 * value is a positive offset from the opcode of the node containing it. 
     128 * An operand, if any, simply follows the node.  (Note that much of the 
     129 * code generation knows about this implicit relationship.) 
     130 * 
     131 * Using two bytes for the "next" pointer is vast overkill for most things, 
     132 * but allows patterns to get big without disasters. 
     133 */ 
     134#define OP(p)   (*(p)) 
     135#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) 
     136#define OPERAND(p)      ((p) + 3) 
     137 
     138/* 
     139 * See regmagic.h for one further detail of program structure. 
     140 */ 
     141 
     142 
     143/* 
     144 * Utility definitions. 
     145 */ 
     146#ifndef CHARBITS 
     147#define UCHARAT(p)      ((int)*(unsigned char *)(p)) 
     148#else 
     149#define UCHARAT(p)      ((int)*(p)&CHARBITS) 
     150#endif 
     151 
     152#define FAIL(m) { regerror(m); return(NULL); } 
     153#define ISMULT(c)       ((c) == '*' || (c) == '+' || (c) == '?') 
     154#define META    "^$.[()|?+*\\" 
     155 
     156/* 
     157 * Flags to be passed up and down. 
     158 */ 
     159#define HASWIDTH        01      /* Known never to match null string. */ 
     160#define SIMPLE          02      /* Simple enough to be STAR/PLUS operand. */ 
     161#define SPSTART         04      /* Starts with * or +. */ 
     162#define WORST           0       /* Worst case. */ 
     163 
     164/* 
     165 * Global work variables for regcomp(). 
     166 */ 
     167struct match_globals { 
     168char *reginput;         /* String-input pointer. */ 
     169char *regbol;           /* Beginning of input, for ^ check. */ 
     170char **regstartp;       /* Pointer to startp array. */ 
     171char **regendp;         /* Ditto for endp. */ 
     172char *regparse;         /* Input-scan pointer. */ 
     173int regnpar;            /* () count. */ 
     174char regdummy; 
     175char *regcode;          /* Code-emit pointer; &regdummy = don't. */ 
     176long regsize;           /* Code size. */ 
     177}; 
     178 
     179/* 
     180 * Forward declarations for regcomp()'s friends. 
     181 */ 
     182#ifndef STATIC 
     183#define STATIC  static 
     184#endif 
     185STATIC char *reg(struct match_globals *g, int paren,int *flagp); 
     186STATIC char *regbranch(struct match_globals *g, int *flagp); 
     187STATIC char *regpiece(struct match_globals *g, int *flagp); 
     188STATIC char *regatom(struct match_globals *g, int *flagp); 
     189STATIC char *regnode(struct match_globals *g, char op); 
     190STATIC char *regnext(struct match_globals *g, char *p); 
     191STATIC void regc(struct match_globals *g, char b); 
     192STATIC void reginsert(struct match_globals *g, char op, char *opnd); 
     193STATIC void regtail(struct match_globals *g, char *p, char *val); 
     194STATIC void regoptail(struct match_globals *g, char *p, char *val); 
     195 
     196 
     197__kernel_size_t my_strcspn(const char *s1,const char *s2) 
     198{ 
     199        char *scan1; 
     200        char *scan2; 
     201        int count; 
     202 
     203        count = 0; 
     204        for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) { 
     205                for (scan2 = (char *)s2; *scan2 != '\0';)       /* ++ moved down. */ 
     206                        if (*scan1 == *scan2++) 
     207                                return(count); 
     208                count++; 
     209        } 
     210        return(count); 
     211} 
     212 
     213/* 
     214 - regcomp - compile a regular expression into internal code 
     215 * 
     216 * We can't allocate space until we know how big the compiled form will be, 
     217 * but we can't compile it (and thus know how big it is) until we've got a 
     218 * place to put the code.  So we cheat:  we compile it twice, once with code 
     219 * generation turned off and size counting turned on, and once "for real". 
     220 * This also means that we don't allocate space until we are sure that the 
     221 * thing really will compile successfully, and we never have to move the 
     222 * code and thus invalidate pointers into it.  (Note that it has to be in 
     223 * one piece because free() must be able to free it all.) 
     224 * 
     225 * Beware that the optimization-preparation code in here knows about some 
     226 * of the structure of the compiled regexp. 
     227 */ 
     228regexp * 
     229regcomp(char *exp,int *patternsize) 
     230{ 
     231        register regexp *r; 
     232        register char *scan; 
     233        register char *longest; 
     234        register int len; 
     235        int flags; 
     236        struct match_globals g; 
     237         
     238        /* commented out by ethan 
     239           extern char *malloc(); 
     240        */ 
     241 
     242        if (exp == NULL) 
     243                FAIL("NULL argument"); 
     244 
     245        /* First pass: determine size, legality. */ 
     246        g.regparse = exp; 
     247        g.regnpar = 1; 
     248        g.regsize = 0L; 
     249        g.regcode = &g.regdummy; 
     250        regc(&g, MAGIC); 
     251        if (reg(&g, 0, &flags) == NULL) 
     252                return(NULL); 
     253 
     254        /* Small enough for pointer-storage convention? */ 
     255        if (g.regsize >= 32767L)                /* Probably could be 65535L. */ 
     256                FAIL("regexp too big"); 
     257 
     258        /* Allocate space. */ 
     259        *patternsize=sizeof(regexp) + (unsigned)g.regsize; 
     260        r = (regexp *)malloc(sizeof(regexp) + (unsigned)g.regsize); 
     261        if (r == NULL) 
     262                FAIL("out of space"); 
     263 
     264        /* Second pass: emit code. */ 
     265        g.regparse = exp; 
     266        g.regnpar = 1; 
     267        g.regcode = r->program; 
     268        regc(&g, MAGIC); 
     269        if (reg(&g, 0, &flags) == NULL) 
     270                return(NULL); 
     271 
     272        /* Dig out information for optimizations. */ 
     273        r->regstart = '\0';     /* Worst-case defaults. */ 
     274        r->reganch = 0; 
     275        r->regmust = NULL; 
     276        r->regmlen = 0; 
     277        scan = r->program+1;                    /* First BRANCH. */ 
     278        if (OP(regnext(&g, scan)) == END) {             /* Only one top-level choice. */ 
     279                scan = OPERAND(scan); 
     280 
     281                /* Starting-point info. */ 
     282                if (OP(scan) == EXACTLY) 
     283                        r->regstart = *OPERAND(scan); 
     284                else if (OP(scan) == BOL) 
     285                        r->reganch++; 
     286 
     287                /* 
     288                 * If there's something expensive in the r.e., find the 
     289                 * longest literal string that must appear and make it the 
     290                 * regmust.  Resolve ties in favor of later strings, since 
     291                 * the regstart check works with the beginning of the r.e. 
     292                 * and avoiding duplication strengthens checking.  Not a 
     293                 * strong reason, but sufficient in the absence of others. 
     294                 */ 
     295                if (flags&SPSTART) { 
     296                        longest = NULL; 
     297                        len = 0; 
     298                        for (; scan != NULL; scan = regnext(&g, scan)) 
     299                                if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { 
     300                                        longest = OPERAND(scan); 
     301                                        len = strlen(OPERAND(scan)); 
     302                                } 
     303                        r->regmust = longest; 
     304                        r->regmlen = len; 
     305                } 
     306        } 
     307 
     308        return(r); 
     309} 
     310 
     311/* 
     312 - reg - regular expression, i.e. main body or parenthesized thing 
     313 * 
     314 * Caller must absorb opening parenthesis. 
     315 * 
     316 * Combining parenthesis handling with the base level of regular expression 
     317 * is a trifle forced, but the need to tie the tails of the branches to what 
     318 * follows makes it hard to avoid. 
     319 */ 
     320static char * 
     321reg(struct match_globals *g, int paren, int *flagp /* Parenthesized? */ ) 
     322{ 
     323        register char *ret; 
     324        register char *br; 
     325        register char *ender; 
     326        register int parno = 0; /* 0 makes gcc happy */ 
     327        int flags; 
     328 
     329        *flagp = HASWIDTH;      /* Tentatively. */ 
     330 
     331        /* Make an OPEN node, if parenthesized. */ 
     332        if (paren) { 
     333                if (g->regnpar >= NSUBEXP) 
     334                        FAIL("too many ()"); 
     335                parno = g->regnpar; 
     336                g->regnpar++; 
     337                ret = regnode(g, OPEN+parno); 
     338        } else 
     339                ret = NULL; 
     340 
     341        /* Pick up the branches, linking them together. */ 
     342        br = regbranch(g, &flags); 
     343        if (br == NULL) 
     344                return(NULL); 
     345        if (ret != NULL) 
     346                regtail(g, ret, br);    /* OPEN -> first. */ 
     347        else 
     348                ret = br; 
     349        if (!(flags&HASWIDTH)) 
     350                *flagp &= ~HASWIDTH; 
     351        *flagp |= flags&SPSTART; 
     352        while (*g->regparse == '|') { 
     353                g->regparse++; 
     354                br = regbranch(g, &flags); 
     355                if (br == NULL) 
     356                        return(NULL); 
     357                regtail(g, ret, br);    /* BRANCH -> BRANCH. */ 
     358                if (!(flags&HASWIDTH)) 
     359                        *flagp &= ~HASWIDTH; 
     360                *flagp |= flags&SPSTART; 
     361        } 
     362 
     363        /* Make a closing node, and hook it on the end. */ 
     364        ender = regnode(g, (paren) ? CLOSE+parno : END);         
     365        regtail(g, ret, ender); 
     366 
     367        /* Hook the tails of the branches to the closing node. */ 
     368        for (br = ret; br != NULL; br = regnext(g, br)) 
     369                regoptail(g, br, ender); 
     370 
     371        /* Check for proper termination. */ 
     372        if (paren && *g->regparse++ != ')') { 
     373                FAIL("unmatched ()"); 
     374        } else if (!paren && *g->regparse != '\0') { 
     375                if (*g->regparse == ')') { 
     376                        FAIL("unmatched ()"); 
     377                } else 
     378                        FAIL("junk on end");    /* "Can't happen". */ 
     379                /* NOTREACHED */ 
     380        } 
     381 
     382        return(ret); 
     383} 
     384 
     385/* 
     386 - regbranch - one alternative of an | operator 
     387 * 
     388 * Implements the concatenation operator. 
     389 */ 
     390static char * 
     391regbranch(struct match_globals *g, int *flagp) 
     392{ 
     393        register char *ret; 
     394        register char *chain; 
     395        register char *latest; 
     396        int flags; 
     397 
     398        *flagp = WORST;         /* Tentatively. */ 
     399 
     400        ret = regnode(g, BRANCH); 
     401        chain = NULL; 
     402        while (*g->regparse != '\0' && *g->regparse != '|' && *g->regparse != ')') { 
     403                latest = regpiece(g, &flags); 
     404                if (latest == NULL) 
     405                        return(NULL); 
     406                *flagp |= flags&HASWIDTH; 
     407                if (chain == NULL)      /* First piece. */ 
     408                        *flagp |= flags&SPSTART; 
     409                else 
     410                        regtail(g, chain, latest); 
     411                chain = latest; 
     412        } 
     413        if (chain == NULL)      /* Loop ran zero times. */ 
     414                (void) regnode(g, NOTHING); 
     415 
     416        return(ret); 
     417} 
     418 
     419/* 
     420 - regpiece - something followed by possible [*+?] 
     421 * 
     422 * Note that the branching code sequences used for ? and the general cases 
     423 * of * and + are somewhat optimized:  they use the same NOTHING node as 
     424 * both the endmarker for their branch list and the body of the last branch. 
     425 * It might seem that this node could be dispensed with entirely, but the 
     426 * endmarker role is not redundant. 
     427 */ 
     428static char * 
     429regpiece(struct match_globals *g, int *flagp) 
     430{ 
     431        register char *ret; 
     432        register char op; 
     433        register char *next; 
     434        int flags; 
     435 
     436        ret = regatom(g, &flags); 
     437        if (ret == NULL) 
     438                return(NULL); 
     439 
     440        op = *g->regparse; 
     441        if (!ISMULT(op)) { 
     442                *flagp = flags; 
     443                return(ret); 
     444        } 
     445 
     446        if (!(flags&HASWIDTH) && op != '?') 
     447                FAIL("*+ operand could be empty"); 
     448        *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); 
     449 
     450        if (op == '*' && (flags&SIMPLE)) 
     451                reginsert(g, STAR, ret); 
     452        else if (op == '*') { 
     453                /* Emit x* as (x&|), where & means "self". */ 
     454                reginsert(g, BRANCH, ret);                      /* Either x */ 
     455                regoptail(g, ret, regnode(g, BACK));            /* and loop */ 
     456                regoptail(g, ret, ret);                 /* back */ 
     457                regtail(g, ret, regnode(g, BRANCH));            /* or */ 
     458                regtail(g, ret, regnode(g, NOTHING));           /* null. */ 
     459        } else if (op == '+' && (flags&SIMPLE)) 
     460                reginsert(g, PLUS, ret); 
     461        else if (op == '+') { 
     462                /* Emit x+ as x(&|), where & means "self". */ 
     463                next = regnode(g, BRANCH);                      /* Either */ 
     464                regtail(g, ret, next); 
     465                regtail(g, regnode(g, BACK), ret);              /* loop back */ 
     466                regtail(g, next, regnode(g, BRANCH));           /* or */ 
     467                regtail(g, ret, regnode(g, NOTHING));           /* null. */ 
     468        } else if (op == '?') { 
     469                /* Emit x? as (x|) */ 
     470                reginsert(g, BRANCH, ret);                      /* Either x */ 
     471                regtail(g, ret, regnode(g, BRANCH));            /* or */ 
     472                next = regnode(g, NOTHING);             /* null. */ 
     473                regtail(g, ret, next); 
     474                regoptail(g, ret, next); 
     475        } 
     476        g->regparse++; 
     477        if (ISMULT(*g->regparse)) 
     478                FAIL("nested *?+"); 
     479 
     480        return(ret); 
     481} 
     482 
     483/* 
     484 - regatom - the lowest level 
     485 * 
     486 * Optimization:  gobbles an entire sequence of ordinary characters so that 
     487 * it can turn them into a single node, which is smaller to store and 
     488 * faster to run.  Backslashed characters are exceptions, each becoming a 
     489 * separate node; the code is simpler that way and it's not worth fixing. 
     490 */ 
     491static char * 
     492regatom(struct match_globals *g, int *flagp) 
     493{ 
     494        register char *ret; 
     495        int flags; 
     496 
     497        *flagp = WORST;         /* Tentatively. */ 
     498 
     499        switch (*g->regparse++) { 
     500        case '^': 
     501                ret = regnode(g, BOL); 
     502                break; 
     503        case '$': 
     504                ret = regnode(g, EOL); 
     505                break; 
     506        case '.': 
     507                ret = regnode(g, ANY); 
     508                *flagp |= HASWIDTH|SIMPLE; 
     509                break; 
     510        case '[': { 
     511                        register int class; 
     512                        register int classend; 
     513 
     514                        if (*g->regparse == '^') {      /* Complement of range. */ 
     515                                ret = regnode(g, ANYBUT); 
     516                                g->regparse++; 
     517                        } else 
     518                                ret = regnode(g, ANYOF); 
     519                        if (*g->regparse == ']' || *g->regparse == '-') 
     520                                regc(g, *g->regparse++); 
     521                        while (*g->regparse != '\0' && *g->regparse != ']') { 
     522                                if (*g->regparse == '-') { 
     523                                        g->regparse++; 
     524                                        if (*g->regparse == ']' || *g->regparse == '\0') 
     525                                                regc(g, '-'); 
     526                                        else { 
     527                                                class = UCHARAT(g->regparse-2)+1; 
     528                                                classend = UCHARAT(g->regparse); 
     529                                                if (class > classend+1) 
     530                                                        FAIL("invalid [] range"); 
     531                                                for (; class <= classend; class++) 
     532                                                        regc(g, class); 
     533                                                g->regparse++; 
     534                                        } 
     535                                } else 
     536                                        regc(g, *g->regparse++); 
     537                        } 
     538                        regc(g, '\0'); 
     539                        if (*g->regparse != ']') 
     540                                FAIL("unmatched []"); 
     541                        g->regparse++; 
     542                        *flagp |= HASWIDTH|SIMPLE; 
     543                } 
     544                break; 
     545        case '(': 
     546                ret = reg(g, 1, &flags); 
     547                if (ret == NULL) 
     548                        return(NULL); 
     549                *flagp |= flags&(HASWIDTH|SPSTART); 
     550                break; 
     551        case '\0': 
     552        case '|': 
     553        case ')': 
     554                FAIL("internal urp");   /* Supposed to be caught earlier. */ 
     555                break; 
     556        case '?': 
     557        case '+': 
     558        case '*': 
     559                FAIL("?+* follows nothing"); 
     560                break; 
     561        case '\\': 
     562                if (*g->regparse == '\0') 
     563                        FAIL("trailing \\"); 
     564                ret = regnode(g, EXACTLY); 
     565                regc(g, *g->regparse++); 
     566                regc(g, '\0'); 
     567                *flagp |= HASWIDTH|SIMPLE; 
     568                break; 
     569        default: { 
     570                        register int len; 
     571                        register char ender; 
     572 
     573                        g->regparse--; 
     574                        len = my_strcspn((const char *)g->regparse, (const char *)META); 
     575                        if (len <= 0) 
     576                                FAIL("internal disaster"); 
     577                        ender = *(g->regparse+len); 
     578                        if (len > 1 && ISMULT(ender)) 
     579                                len--;          /* Back off clear of ?+* operand. */ 
     580                        *flagp |= HASWIDTH; 
     581                        if (len == 1) 
     582                                *flagp |= SIMPLE; 
     583                        ret = regnode(g, EXACTLY); 
     584                        while (len > 0) { 
     585                                regc(g, *g->regparse++); 
     586                                len--; 
     587                        } 
     588                        regc(g, '\0'); 
     589                } 
     590                break; 
     591        } 
     592 
     593        return(ret); 
     594} 
     595 
     596/* 
     597 - regnode - emit a node 
     598 */ 
     599static char *                   /* Location. */ 
     600regnode(struct match_globals *g, char op) 
     601{ 
     602        register char *ret; 
     603        register char *ptr; 
     604 
     605        ret = g->regcode; 
     606        if (ret == &g->regdummy) { 
     607                g->regsize += 3; 
     608                return(ret); 
     609        } 
     610 
     611        ptr = ret; 
     612        *ptr++ = op; 
     613        *ptr++ = '\0';          /* Null "next" pointer. */ 
     614        *ptr++ = '\0'; 
     615        g->regcode = ptr; 
     616 
     617        return(ret); 
     618} 
     619 
     620/* 
     621 - regc - emit (if appropriate) a byte of code 
     622 */ 
     623static void 
     624regc(struct match_globals *g, char b) 
     625{ 
     626        if (g->regcode != &g->regdummy) 
     627                *g->regcode++ = b; 
     628        else 
     629                g->regsize++; 
     630} 
     631 
     632/* 
     633 - reginsert - insert an operator in front of already-emitted operand 
     634 * 
     635 * Means relocating the operand. 
     636 */ 
     637static void 
     638reginsert(struct match_globals *g, char op, char* opnd) 
     639{ 
     640        register char *src; 
     641        register char *dst; 
     642        register char *place; 
     643 
     644        if (g->regcode == &g->regdummy) { 
     645                g->regsize += 3; 
     646                return; 
     647        } 
     648 
     649        src = g->regcode; 
     650        g->regcode += 3; 
     651        dst = g->regcode; 
     652        while (src > opnd) 
     653                *--dst = *--src; 
     654 
     655        place = opnd;           /* Op node, where operand used to be. */ 
     656        *place++ = op; 
     657        *place++ = '\0'; 
     658        *place++ = '\0'; 
     659} 
     660 
     661/* 
     662 - regtail - set the next-pointer at the end of a node chain 
     663 */ 
     664static void 
     665regtail(struct match_globals *g, char *p, char *val) 
     666{ 
     667        register char *scan; 
     668        register char *temp; 
     669        register int offset; 
     670 
     671        if (p == &g->regdummy) 
     672                return; 
     673 
     674        /* Find last node. */ 
     675        scan = p; 
     676        for (;;) { 
     677                temp = regnext(g, scan); 
     678                if (temp == NULL) 
     679                        break; 
     680                scan = temp; 
     681        } 
     682 
     683        if (OP(scan) == BACK) 
     684                offset = scan - val; 
     685        else 
     686                offset = val - scan; 
     687        *(scan+1) = (offset>>8)&0377; 
     688        *(scan+2) = offset&0377; 
     689} 
     690 
     691/* 
     692 - regoptail - regtail on operand of first argument; nop if operandless 
     693 */ 
     694static void 
     695regoptail(struct match_globals *g, char *p, char *val) 
     696{ 
     697        /* "Operandless" and "op != BRANCH" are synonymous in practice. */ 
     698        if (p == NULL || p == &g->regdummy || OP(p) != BRANCH) 
     699                return; 
     700        regtail(g, OPERAND(p), val); 
     701} 
     702 
     703/* 
     704 * regexec and friends 
     705 */ 
     706 
     707 
     708/* 
     709 * Forwards. 
     710 */ 
     711STATIC int regtry(struct match_globals *g, regexp *prog, char *string); 
     712STATIC int regmatch(struct match_globals *g, char *prog); 
     713STATIC int regrepeat(struct match_globals *g, char *p); 
     714 
     715#ifdef DEBUG 
     716int regnarrate = 0; 
     717void regdump(); 
     718STATIC char *regprop(char *op); 
     719#endif 
     720 
     721/* 
     722 - regexec - match a regexp against a string 
     723 */ 
     724int 
     725regexec(regexp *prog, char *string) 
     726{ 
     727        register char *s; 
     728        struct match_globals g; 
     729 
     730        /* Be paranoid... */ 
     731        if (prog == NULL || string == NULL) { 
     732                printk("<3>Regexp: NULL parameter\n"); 
     733                return(0); 
     734        } 
     735 
     736        /* Check validity of program. */ 
     737        if (UCHARAT(prog->program) != MAGIC) { 
     738                printk("<3>Regexp: corrupted program\n"); 
     739                return(0); 
     740        } 
     741 
     742        /* If there is a "must appear" string, look for it. */ 
     743        if (prog->regmust != NULL) { 
     744                s = string; 
     745                while ((s = strchr(s, prog->regmust[0])) != NULL) { 
     746                        if (strncmp(s, prog->regmust, prog->regmlen) == 0) 
     747                                break;  /* Found it. */ 
     748                        s++; 
     749                } 
     750                if (s == NULL)  /* Not present. */ 
     751                        return(0); 
     752        } 
     753 
     754        /* Mark beginning of line for ^ . */ 
     755        g.regbol = string; 
     756 
     757        /* Simplest case:  anchored match need be tried only once. */ 
     758        if (prog->reganch) 
     759                return(regtry(&g, prog, string)); 
     760 
     761        /* Messy cases:  unanchored match. */ 
     762        s = string; 
     763        if (prog->regstart != '\0') 
     764                /* We know what char it must start with. */ 
     765                while ((s = strchr(s, prog->regstart)) != NULL) { 
     766                        if (regtry(&g, prog, s)) 
     767                                return(1); 
     768                        s++; 
     769                } 
     770        else 
     771                /* We don't -- general case. */ 
     772                do { 
     773                        if (regtry(&g, prog, s)) 
     774                                return(1); 
     775                } while (*s++ != '\0'); 
     776 
     777        /* Failure. */ 
     778        return(0); 
     779} 
     780 
     781/* 
     782 - regtry - try match at specific point 
     783 */ 
     784static int                      /* 0 failure, 1 success */ 
     785regtry(struct match_globals *g, regexp *prog, char *string) 
     786{ 
     787        register int i; 
     788        register char **sp; 
     789        register char **ep; 
     790 
     791        g->reginput = string; 
     792        g->regstartp = prog->startp; 
     793        g->regendp = prog->endp; 
     794 
     795        sp = prog->startp; 
     796        ep = prog->endp; 
     797        for (i = NSUBEXP; i > 0; i--) { 
     798                *sp++ = NULL; 
     799                *ep++ = NULL; 
     800        } 
     801        if (regmatch(g, prog->program + 1)) { 
     802                prog->startp[0] = string; 
     803                prog->endp[0] = g->reginput; 
     804                return(1); 
     805        } else 
     806                return(0); 
     807} 
     808 
     809/* 
     810 - regmatch - main matching routine 
     811 * 
     812 * Conceptually the strategy is simple:  check to see whether the current 
     813 * node matches, call self recursively to see whether the rest matches, 
     814 * and then act accordingly.  In practice we make some effort to avoid 
     815 * recursion, in particular by going through "ordinary" nodes (that don't 
     816 * need to know whether the rest of the match failed) by a loop instead of 
     817 * by recursion. 
     818 */ 
     819static int                      /* 0 failure, 1 success */ 
     820regmatch(struct match_globals *g, char *prog) 
     821{ 
     822        register char *scan = prog; /* Current node. */ 
     823        char *next;                 /* Next node. */ 
     824 
     825#ifdef DEBUG 
     826        if (scan != NULL && regnarrate) 
     827                fprintf(stderr, "%s(\n", regprop(scan)); 
     828#endif 
     829        while (scan != NULL) { 
     830#ifdef DEBUG 
     831                if (regnarrate) 
     832                        fprintf(stderr, "%s...\n", regprop(scan)); 
     833#endif 
     834                next = regnext(g, scan); 
     835 
     836                switch (OP(scan)) { 
     837                case BOL: 
     838                        if (g->reginput != g->regbol) 
     839                                return(0); 
     840                        break; 
     841                case EOL: 
     842                        if (*g->reginput != '\0') 
     843                                return(0); 
     844                        break; 
     845                case ANY: 
     846                        if (*g->reginput == '\0') 
     847                                return(0); 
     848                        g->reginput++; 
     849                        break; 
     850                case EXACTLY: { 
     851                                register int len; 
     852                                register char *opnd; 
     853 
     854                                opnd = OPERAND(scan); 
     855                                /* Inline the first character, for speed. */ 
     856                                if (*opnd != *g->reginput) 
     857                                        return(0); 
     858                                len = strlen(opnd); 
     859                                if (len > 1 && strncmp(opnd, g->reginput, len) != 0) 
     860                                        return(0); 
     861                                g->reginput += len; 
     862                        } 
     863                        break; 
     864                case ANYOF: 
     865                        if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) == NULL) 
     866                                return(0); 
     867                        g->reginput++; 
     868                        break; 
     869                case ANYBUT: 
     870                        if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) != NULL) 
     871                                return(0); 
     872                        g->reginput++; 
     873                        break; 
     874                case NOTHING: 
     875                case BACK: 
     876                        break; 
     877                case OPEN+1: 
     878                case OPEN+2: 
     879                case OPEN+3: 
     880                case OPEN+4: 
     881                case OPEN+5: 
     882                case OPEN+6: 
     883                case OPEN+7: 
     884                case OPEN+8: 
     885                case OPEN+9: { 
     886                                register int no; 
     887                                register char *save; 
     888 
     889                                no = OP(scan) - OPEN; 
     890                                save = g->reginput; 
     891 
     892                                if (regmatch(g, next)) { 
     893                                        /* 
     894                                         * Don't set startp if some later 
     895                                         * invocation of the same parentheses 
     896                                         * already has. 
     897                                         */ 
     898                                        if (g->regstartp[no] == NULL) 
     899                                                g->regstartp[no] = save; 
     900                                        return(1); 
     901                                } else 
     902                                        return(0); 
     903                        } 
     904                        break; 
     905                case CLOSE+1: 
     906                case CLOSE+2: 
     907                case CLOSE+3: 
     908                case CLOSE+4: 
     909                case CLOSE+5: 
     910                case CLOSE+6: 
     911                case CLOSE+7: 
     912                case CLOSE+8: 
     913                case CLOSE+9: 
     914                        { 
     915                                register int no; 
     916                                register char *save; 
     917 
     918                                no = OP(scan) - CLOSE; 
     919                                save = g->reginput; 
     920 
     921                                if (regmatch(g, next)) { 
     922                                        /* 
     923                                         * Don't set endp if some later 
     924                                         * invocation of the same parentheses 
     925                                         * already has. 
     926                                         */ 
     927                                        if (g->regendp[no] == NULL) 
     928                                                g->regendp[no] = save; 
     929                                        return(1); 
     930                                } else 
     931                                        return(0); 
     932                        } 
     933                        break; 
     934                case BRANCH: { 
     935                                register char *save; 
     936 
     937                                if (OP(next) != BRANCH)         /* No choice. */ 
     938                                        next = OPERAND(scan);   /* Avoid recursion. */ 
     939                                else { 
     940                                        do { 
     941                                                save = g->reginput; 
     942                                                if (regmatch(g, OPERAND(scan))) 
     943                                                        return(1); 
     944                                                g->reginput = save; 
     945                                                scan = regnext(g, scan); 
     946                                        } while (scan != NULL && OP(scan) == BRANCH); 
     947                                        return(0); 
     948                                        /* NOTREACHED */ 
     949                                } 
     950                        } 
     951                        break; 
     952                case STAR: 
     953                case PLUS: { 
     954                                register char nextch; 
     955                                register int no; 
     956                                register char *save; 
     957                                register int min; 
     958 
     959                                /* 
     960                                 * Lookahead to avoid useless match attempts 
     961                                 * when we know what character comes next. 
     962                                 */ 
     963                                nextch = '\0'; 
     964                                if (OP(next) == EXACTLY) 
     965                                        nextch = *OPERAND(next); 
     966                                min = (OP(scan) == STAR) ? 0 : 1; 
     967                                save = g->reginput; 
     968                                no = regrepeat(g, OPERAND(scan)); 
     969                                while (no >= min) { 
     970                                        /* If it could work, try it. */ 
     971                                        if (nextch == '\0' || *g->reginput == nextch) 
     972                                                if (regmatch(g, next)) 
     973                                                        return(1); 
     974                                        /* Couldn't or didn't -- back up. */ 
     975                                        no--; 
     976                                        g->reginput = save + no; 
     977                                } 
     978                                return(0); 
     979                        } 
     980                        break; 
     981                case END: 
     982                        return(1);      /* Success! */ 
     983                        break; 
     984                default: 
     985                        printk("<3>Regexp: memory corruption\n"); 
     986                        return(0); 
     987                        break; 
     988                } 
     989 
     990                scan = next; 
     991        } 
     992 
     993        /* 
     994         * We get here only if there's trouble -- normally "case END" is 
     995         * the terminating point. 
     996         */ 
     997        printk("<3>Regexp: corrupted pointers\n"); 
     998        return(0); 
     999} 
     1000 
     1001/* 
     1002 - regrepeat - repeatedly match something simple, report how many 
     1003 */ 
     1004static int 
     1005regrepeat(struct match_globals *g, char *p) 
     1006{ 
     1007        register int count = 0; 
     1008        register char *scan; 
     1009        register char *opnd; 
     1010 
     1011        scan = g->reginput; 
     1012        opnd = OPERAND(p); 
     1013        switch (OP(p)) { 
     1014        case ANY: 
     1015                count = strlen(scan); 
     1016                scan += count; 
     1017                break; 
     1018        case EXACTLY: 
     1019                while (*opnd == *scan) { 
     1020                        count++; 
     1021                        scan++; 
     1022                } 
     1023                break; 
     1024        case ANYOF: 
     1025                while (*scan != '\0' && strchr(opnd, *scan) != NULL) { 
     1026                        count++; 
     1027                        scan++; 
     1028                } 
     1029                break; 
     1030        case ANYBUT: 
     1031                while (*scan != '\0' && strchr(opnd, *scan) == NULL) { 
     1032                        count++; 
     1033                        scan++; 
     1034                } 
     1035                break; 
     1036        default:                /* Oh dear.  Called inappropriately. */ 
     1037                printk("<3>Regexp: internal foulup\n"); 
     1038                count = 0;      /* Best compromise. */ 
     1039                break; 
     1040        } 
     1041        g->reginput = scan; 
     1042 
     1043        return(count); 
     1044} 
     1045 
     1046/* 
     1047 - regnext - dig the "next" pointer out of a node 
     1048 */ 
     1049static char* 
     1050regnext(struct match_globals *g, char *p) 
     1051{ 
     1052        register int offset; 
     1053 
     1054        if (p == &g->regdummy) 
     1055                return(NULL); 
     1056 
     1057        offset = NEXT(p); 
     1058        if (offset == 0) 
     1059                return(NULL); 
     1060 
     1061        if (OP(p) == BACK) 
     1062                return(p-offset); 
     1063        else 
     1064                return(p+offset); 
     1065} 
     1066 
     1067#ifdef DEBUG 
     1068 
     1069STATIC char *regprop(); 
     1070 
     1071/* 
     1072 - regdump - dump a regexp onto stdout in vaguely comprehensible form 
     1073 */ 
     1074void 
     1075regdump(regexp *r) 
     1076{ 
     1077        register char *s; 
     1078        register char op = EXACTLY;     /* Arbitrary non-END op. */ 
     1079        register char *next; 
     1080        /* extern char *strchr(); */ 
     1081 
     1082 
     1083        s = r->program + 1; 
     1084        while (op != END) {     /* While that wasn't END last time... */ 
     1085                op = OP(s); 
     1086                printf("%2d%s", s-r->program, regprop(s));      /* Where, what. */ 
     1087                next = regnext(s); 
     1088                if (next == NULL)               /* Next ptr. */ 
     1089                        printf("(0)"); 
     1090                else 
     1091                        printf("(%d)", (s-r->program)+(next-s)); 
     1092                s += 3; 
     1093                if (op == ANYOF || op == ANYBUT || op == EXACTLY) { 
     1094                        /* Literal string, where present. */ 
     1095                        while (*s != '\0') { 
     1096                                putchar(*s); 
     1097                                s++; 
     1098                        } 
     1099                        s++; 
     1100                } 
     1101                putchar('\n'); 
     1102        } 
     1103 
     1104        /* Header fields of interest. */ 
     1105        if (r->regstart != '\0') 
     1106                printf("start `%c' ", r->regstart); 
     1107        if (r->reganch) 
     1108                printf("anchored "); 
     1109        if (r->regmust != NULL) 
     1110                printf("must have \"%s\"", r->regmust); 
     1111        printf("\n"); 
     1112} 
     1113 
     1114/* 
     1115 - regprop - printable representation of opcode 
     1116 */ 
     1117static char * 
     1118regprop(char *op) 
     1119{ 
     1120#define BUFLEN 50 
     1121        register char *p; 
     1122        static char buf[BUFLEN]; 
     1123 
     1124        strcpy(buf, ":"); 
     1125 
     1126        switch (OP(op)) { 
     1127        case BOL: 
     1128                p = "BOL"; 
     1129                break; 
     1130        case EOL: 
     1131                p = "EOL"; 
     1132                break; 
     1133        case ANY: 
     1134                p = "ANY"; 
     1135                break; 
     1136        case ANYOF: 
     1137                p = "ANYOF"; 
     1138                break; 
     1139        case ANYBUT: 
     1140                p = "ANYBUT"; 
     1141                break; 
     1142        case BRANCH: 
     1143                p = "BRANCH"; 
     1144                break; 
     1145        case EXACTLY: 
     1146                p = "EXACTLY"; 
     1147                break; 
     1148        case NOTHING: 
     1149                p = "NOTHING"; 
     1150                break; 
     1151        case BACK: 
     1152                p = "BACK"; 
     1153                break; 
     1154        case END: 
     1155                p = "END"; 
     1156                break; 
     1157        case OPEN+1: 
     1158        case OPEN+2: 
     1159        case OPEN+3: 
     1160        case OPEN+4: 
     1161        case OPEN+5: 
     1162        case OPEN+6: 
     1163        case OPEN+7: 
     1164        case OPEN+8: 
     1165        case OPEN+9: 
     1166                snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN); 
     1167                p = NULL; 
     1168                break; 
     1169        case CLOSE+1: 
     1170        case CLOSE+2: 
     1171        case CLOSE+3: 
     1172        case CLOSE+4: 
     1173        case CLOSE+5: 
     1174        case CLOSE+6: 
     1175        case CLOSE+7: 
     1176        case CLOSE+8: 
     1177        case CLOSE+9: 
     1178                snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE); 
     1179                p = NULL; 
     1180                break; 
     1181        case STAR: 
     1182                p = "STAR"; 
     1183                break; 
     1184        case PLUS: 
     1185                p = "PLUS"; 
     1186                break; 
     1187        default: 
     1188                printk("<3>Regexp: corrupted opcode\n"); 
     1189                break; 
     1190        } 
     1191        if (p != NULL) 
     1192                strncat(buf, p, BUFLEN-strlen(buf)); 
     1193        return(buf); 
     1194} 
     1195#endif 
     1196 
     1197 
  • new file net/netfilter/regexp/regexp.h

    - +  
     1/* 
     2 * Definitions etc. for regexp(3) routines. 
     3 * 
     4 * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof], 
     5 * not the System V one. 
     6 */ 
     7 
     8#ifndef REGEXP_H 
     9#define REGEXP_H 
     10 
     11 
     12/* 
     13http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h , 
     14which contains a version of this library, says: 
     15 
     16 * 
     17 * NSUBEXP must be at least 10, and no greater than 117 or the parser 
     18 * will not work properly. 
     19 * 
     20 
     21However, it looks rather like this library is limited to 10.  If you think 
     22otherwise, let us know. 
     23*/ 
     24 
     25#define NSUBEXP  10 
     26typedef struct regexp { 
     27        char *startp[NSUBEXP]; 
     28        char *endp[NSUBEXP]; 
     29        char regstart;          /* Internal use only. */ 
     30        char reganch;           /* Internal use only. */ 
     31        char *regmust;          /* Internal use only. */ 
     32        int regmlen;            /* Internal use only. */ 
     33        char program[1];        /* Unwarranted chumminess with compiler. */ 
     34} regexp; 
     35 
     36regexp * regcomp(char *exp, int *patternsize); 
     37int regexec(regexp *prog, char *string); 
     38void regsub(regexp *prog, char *source, char *dest); 
     39void regerror(char *s); 
     40 
     41#endif 
  • new file net/netfilter/regexp/regmagic.h

    - +  
     1/* 
     2 * The first byte of the regexp internal "program" is actually this magic 
     3 * number; the start node begins in the second byte. 
     4 */ 
     5#define MAGIC   0234 
  • new file net/netfilter/regexp/regsub.c

    - +  
     1/* 
     2 * regsub 
     3 * @(#)regsub.c 1.3 of 2 April 86 
     4 * 
     5 *      Copyright (c) 1986 by University of Toronto. 
     6 *      Written by Henry Spencer.  Not derived from licensed software. 
     7 * 
     8 *      Permission is granted to anyone to use this software for any 
     9 *      purpose on any computer system, and to redistribute it freely, 
     10 *      subject to the following restrictions: 
     11 * 
     12 *      1. The author is not responsible for the consequences of use of 
     13 *              this software, no matter how awful, even if they arise 
     14 *              from defects in it. 
     15 * 
     16 *      2. The origin of this software must not be misrepresented, either 
     17 *              by explicit claim or by omission. 
     18 * 
     19 *      3. Altered versions must be plainly marked as such, and must not 
     20 *              be misrepresented as being the original software. 
     21 * 
     22 * 
     23 * This code was modified by Ethan Sommer to work within the kernel 
     24 * (it now uses kmalloc etc..) 
     25 * 
     26 */ 
     27#include "regexp.h" 
     28#include "regmagic.h" 
     29#include <linux/string.h> 
     30 
     31 
     32#ifndef CHARBITS 
     33#define UCHARAT(p)      ((int)*(unsigned char *)(p)) 
     34#else 
     35#define UCHARAT(p)      ((int)*(p)&CHARBITS) 
     36#endif 
     37 
     38#if 0 
     39//void regerror(char * s) 
     40//{ 
     41//        printk("regexp(3): %s", s); 
     42//        /* NOTREACHED */ 
     43//} 
     44#endif 
     45 
     46/* 
     47 - regsub - perform substitutions after a regexp match 
     48 */ 
     49void 
     50regsub(regexp * prog, char * source, char * dest) 
     51{ 
     52        register char *src; 
     53        register char *dst; 
     54        register char c; 
     55        register int no; 
     56        register int len; 
     57         
     58        /* Not necessary and gcc doesn't like it -MLS */ 
     59        /*extern char *strncpy();*/ 
     60 
     61        if (prog == NULL || source == NULL || dest == NULL) { 
     62                regerror("NULL parm to regsub"); 
     63                return; 
     64        } 
     65        if (UCHARAT(prog->program) != MAGIC) { 
     66                regerror("damaged regexp fed to regsub"); 
     67                return; 
     68        } 
     69 
     70        src = source; 
     71        dst = dest; 
     72        while ((c = *src++) != '\0') { 
     73                if (c == '&') 
     74                        no = 0; 
     75                else if (c == '\\' && '0' <= *src && *src <= '9') 
     76                        no = *src++ - '0'; 
     77                else 
     78                        no = -1; 
     79 
     80                if (no < 0) {   /* Ordinary character. */ 
     81                        if (c == '\\' && (*src == '\\' || *src == '&')) 
     82                                c = *src++; 
     83                        *dst++ = c; 
     84                } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { 
     85                        len = prog->endp[no] - prog->startp[no]; 
     86                        (void) strncpy(dst, prog->startp[no], len); 
     87                        dst += len; 
     88                        if (len != 0 && *(dst-1) == '\0') {     /* strncpy hit NUL. */ 
     89                                regerror("damaged match string"); 
     90                                return; 
     91                        } 
     92                } 
     93        } 
     94        *dst++ = '\0'; 
     95} 
  • net/netfilter/nf_conntrack_core.c

    a b destroy_conntrack(struct nf_conntrack *n 
    213213         * too. */ 
    214214        nf_ct_remove_expectations(ct); 
    215215 
     216        #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     217        if(ct->layer7.app_proto) 
     218                kfree(ct->layer7.app_proto); 
     219        if(ct->layer7.app_data) 
     220        kfree(ct->layer7.app_data); 
     221        #endif 
     222 
     223 
    216224        /* We overload first tuple to link into unconfirmed list. */ 
    217225        if (!nf_ct_is_confirmed(ct)) { 
    218226                BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); 
  • net/netfilter/nf_conntrack_standalone.c

    a b static int ct_seq_show(struct seq_file * 
    239239        if (ct_show_delta_time(s, ct)) 
    240240                goto release; 
    241241 
     242#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     243        if(ct->layer7.app_proto && 
     244           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto)) 
     245                return -ENOSPC; 
     246#endif 
     247 
    242248        if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 
    243249                goto release; 
    244250 
  • include/net/netfilter/nf_conntrack.h

    a b struct nf_conn { 
    135135        struct net *ct_net; 
    136136#endif 
    137137 
     138#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \ 
     139    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) 
     140        struct { 
     141                /* 
     142                 * e.g. "http". NULL before decision. "unknown" after decision 
     143                 * if no match. 
     144                 */ 
     145                char *app_proto; 
     146                /* 
     147                 * application layer data so far. NULL after match decision. 
     148                 */ 
     149                char *app_data; 
     150                unsigned int app_data_len; 
     151        } layer7; 
     152#endif 
     153 
    138154        /* Storage reserved for other modules, must be the last member */ 
    139155        union nf_conntrack_proto proto; 
    140156}; 
  • new file include/linux/netfilter/xt_layer7.h

    - +  
     1#ifndef _XT_LAYER7_H 
     2#define _XT_LAYER7_H 
     3 
     4#define MAX_PATTERN_LEN 8192 
     5#define MAX_PROTOCOL_LEN 256 
     6 
     7struct xt_layer7_info { 
     8    char protocol[MAX_PROTOCOL_LEN]; 
     9    char pattern[MAX_PATTERN_LEN]; 
     10    u_int8_t invert; 
     11}; 
     12 
     13#endif /* _XT_LAYER7_H */ 
Note: See TracBrowser for help on using the repository browser.