1/* -------------------------------------------------------------------------------------------------------------- 2 * FILE NAME l7_filter_main.c (for Linux Platform) 3 * DATE 10/25/2007 4 * AUTHOR/S Max Ding 5 * Description Layer 7 filter 6 * -------------------------------------------------------------------------------------------------------------- 7 */ 8 9//MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>"); 10//MODULE_LICENSE("GPL"); 11//MODULE_DESCRIPTION("application layer match module"); 12 13/*******include start*******/ 14#ifdef __LINUX__ 15#include <linux/module.h> 16#include <linux/if.h> 17#include <linux/types.h> 18#include <linux/in.h> 19#include <linux/ip.h> 20#include <linux/skbuff.h> 21#include <linux/acosnatfw.h> 22#include <linux/netdevice.h> 23#include <linux/inetdevice.h> 24#include <linux/mm.h> 25 26#ifdef CONFIG_NETFILTER 27#include <linux/netfilter.h> 28#include <linux/netfilter_ipv4.h> 29#endif /* CONFIG_NETFILTER */ 30 31#include "bcmnvram.h" 32#endif /* __LINUX__ */ 33 34/* #define L7_DEBUG_ON */ 35 36#include "regexp/regexp.c" 37#include "l7_filter_main.h" 38 39/*******define start*******/ 40#ifdef L7_DEBUG_ON 41#define L7_DEBUG_PRI_0 0x00000000 42#define L7_DEBUG_PRI_1 0x00000001 43#define L7_DEBUG_PRI_2 0x00000002 44#define L7_DEBUG_PRI_3 0x00000004 45#define L7_DEBUG_PRI_4 0x00000008 46#define L7_DEBUG_PRI_5 0x00000010 47#define L7_DEBUG_PRI_6 0x00000020 48#define L7_DEBUG_PRI_7 0x00000040 49#define L7_DEBUG_PRI_a 0xffffffff 50#define L7_PRINTK_DEBUG printk 51#define L7_PRINTK_DEBUG_1 if (debug_pri & L7_DEBUG_PRI_1) printk 52#define L7_PRINTK_DEBUG_2 if (debug_pri & L7_DEBUG_PRI_2) printk 53#define L7_PRINTK_DEBUG_3 if (debug_pri & L7_DEBUG_PRI_3) printk 54#define L7_PRINTK_DEBUG_4 if (debug_pri & L7_DEBUG_PRI_4) printk 55#define L7_PRINTK_DEBUG_5 if (debug_pri & L7_DEBUG_PRI_5) printk 56#define L7_PRINTK_DEBUG_6 if (debug_pri & L7_DEBUG_PRI_6) printk 57#define L7_PRINTK_DEBUG_7 if (debug_pri & L7_DEBUG_PRI_7) printk 58 59#else/* else for #ifdef L7_DEBUG_ON */ 60 61#define L7_PRINTK_DEBUG printk 62#define L7_PRINTK_DEBUG_1 printk 63#define L7_PRINTK_DEBUG_2 printk 64#define L7_PRINTK_DEBUG_3 printk 65#define L7_PRINTK_DEBUG_4 printk 66#define L7_PRINTK_DEBUG_5 printk 67#define L7_PRINTK_DEBUG_6 printk 68#define L7_PRINTK_DEBUG_7 printk 69#endif/* end for #ifdef L7_DEBUG_ON */ 70 71/*******global and static variables start*******/ 72#ifdef L7_DEBUG_ON 73static int debug_pri = 0x00000001; 74MODULE_PARM(debug_pri, "i"); 75#endif 76 77/* Number of packets whose data we look at. */ 78static int num_packets = 20; 79 80/* Fxcn port-S Wins, 0717-09 */ 81static char tolower(char c); 82/* Fxcn port-E Wins, 0717-09 */ 83 84/* head of the link list of patterns */ 85static s_pattern_cache * first_pattern_cache = NULL; 86 87#ifdef CONFIG_NETFILTER 88int l7_filter_main(struct sk_buff *skb, int iDirection); 89static unsigned int l7_filter_hook(unsigned int hook, 90 struct sk_buff **skb, 91 const struct net_device *in, 92 const struct net_device *out, 93 int (*okfn)(struct sk_buff *)) 94{ 95 int dir; 96 97 if (hook == NF_IP_PRE_ROUTING) 98 dir = 0; 99 else if (hook == NF_IP_POST_ROUTING) 100 dir = 1; 101 else 102 return NF_ACCEPT; 103 104 local_bh_disable(); 105 l7_filter_main(*skb, dir); 106 local_bh_enable(); 107 108 return NF_ACCEPT; 109} 110 111static struct nf_hook_ops l7_filter_prerouting_ops = { 112#ifdef AG_LINUX_26 113 .owner = THIS_MODULE, 114#else 115 .list = {NULL, NULL}, 116#endif /* AG_LINUX_26 */ 117 .hook = l7_filter_hook, 118 .pf = PF_INET, 119 .hooknum = NF_IP_PRE_ROUTING, 120 .priority = NF_IP_PRI_LAST, 121}; 122static struct nf_hook_ops l7_filter_postrouting_ops = { 123#ifdef AG_LINUX_26 124 .owner = THIS_MODULE, 125#else 126 .list = {NULL, NULL}, 127#endif /* AG_LINUX_26 */ 128 .hook = l7_filter_hook, 129 .pf = PF_INET, 130 .hooknum = NF_IP_POST_ROUTING, 131 .priority = NF_IP_PRI_LAST, 132}; 133#endif /* CONFIG_NETFILTER */ 134 135/* Hard code for all expression of protocol. It's better to read them from *.pat files. */ 136static s_proto_regexp g_all_proto[] = 137{ 138 {"bittorrent", L7_ENUM_BITTORRENT, 0, "^(\\x13bittorrent protocol|azver\\x01$|get /scrape\\?info_hash=)|d1:ad2:id20:|\\x08'7P\\)[RP]"}, 139 {"fasttrack", L7_ENUM_FASTTRACK, 0, "^get (/.download/[ -~]*|/.supernode[ -~]|/.status[ -~]|/.network[ -~]*|/.files|/.hash=[0-9a-f]*/[ -~]*) http/1.1|user-agent: kazaa|x-kazaa(-username|-network|-ip|-supernodeip|-xferid|-xferuid|tag)|^give [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]?[0-9]?[0-9]?"}, 140 {"edonkey", L7_ENUM_EDONKEY, 0, "^[\\xc5\\xd4\\xe3-\\xe5].?.?.?.?([\\x01\\x02\\x05\\x14\\x15\\x16\\x18\\x19\\x1a\\x1b\\x1c\\x20\\x21\\x32\\x33\\x34\\x35\\x36\\x38\\x40\\x41\\x42\\x43\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58[\\x60\\x81\\x82\\x90\\x91\\x93\\x96\\x97\\x98\\x99\\x9a\\x9b\\x9c\\x9e\\xa0\\xa1\\xa2\\xa3\\xa4]|\\x59................?[ -~]|\\x96....$)"}, 141 {"gnutella", L7_ENUM_GNUTELLA, 0, "^(gnd[\\x01\\x02]?.?.?\\x01|gnutella connect/[012]\\.[0-9]\\x0d\\x0a|get /uri-res/n2r\\?urn:sha1:|get /.*user-agent: (gtk-gnutella|bearshare|mactella|gnucleus|gnotella|limewire|imesh)|get /.*content-type: application/x-gnutella-packets|giv [0-9]*:[0-9a-f]*/|queue [0-9a-f]* [1-9][0-9]?[0-9]?\\.[1-9][0-9]?[0-9]?\\.[1-9][0-9]?[0-9]?\\.[1-9][0-9]?[0-9]?:[1-9][0-9]?[0-9]?[0-9]?|gnutella.*content-type: application/x-gnutella|...................?lime)"}, 142 {"skypetoskype", L7_ENUM_SKYPETOSKYPE, 0, "^..\\x02............."}, 143 {"skypeout", L7_ENUM_SKYPEOUT, 0, "^(\\x01.?.?.?.?.?.?.?.?\\x01|\\x02.?.?.?.?.?.?.?.?\\x02|\\x03.?.?.?.?.?.?.?.?\\x03|\\x04.?.?.?.?.?.?.?.?\\x04|\\x05.?.?.?.?.?.?.?.?\\x05|\\x06.?.?.?.?.?.?.?.?\\x06|\\x07.?.?.?.?.?.?.?.?\\x07|\\x08.?.?.?.?.?.?.?.?\\x08|\\x09.?.?.?.?.?.?.?.?\\x09|\\x0a.?.?.?.?.?.?.?.?\\x0a|\\x0b.?.?.?.?.?.?.?.?\\x0b|\\x0c.?.?.?.?.?.?.?.?\\x0c|\\x0d.?.?.?.?.?.?.?.?\\x0d|\\x0e.?.?.?.?.?.?.?.?\\x0e|\\x0f.?.?.?.?.?.?.?.?\\x0f|\\x10.?.?.?.?.?.?.?.?\\x10|\\x11.?.?.?.?.?.?.?.?\\x11|\\x12.?.?.?.?.?.?.?.?\\x12\ 144|\\x13.?.?.?.?.?.?.?.?\\x13|\\x14.?.?.?.?.?.?.?.?\\x14|\\x15.?.?.?.?.?.?.?.?\\x15|\\x16.?.?.?.?.?.?.?.?\\x16|\\x17.?.?.?.?.?.?.?.?\\x17|\\x18.?.?.?.?.?.?.?.?\\x18|\\x19.?.?.?.?.?.?.?.?\\x19|\\x1a.?.?.?.?.?.?.?.?\\x1a|\\x1b.?.?.?.?.?.?.?.?\\x1b|\\x1c.?.?.?.?.?.?.?.?\\x1c|\\x1d.?.?.?.?.?.?.?.?\\x1d|\\x1e.?.?.?.?.?.?.?.?\\x1e|\\x1f.?.?.?.?.?.?.?.?\\x1f|\\x20.?.?.?.?.?.?.?.?\\x20|\\x21.?.?.?.?.?.?.?.?\\x21|\\x22.?.?.?.?.?.?.?.?\\x22|\\x23.?.?.?.?.?.?.?.?\\x23|\\$.?.?.?.?.?.?.?.?\\$|\\x25.?.?.?.?.?.?.?.?\\x25\ 145|\\x26.?.?.?.?.?.?.?.?\\x26|\\x27.?.?.?.?.?.?.?.?\\x27|\\(.?.?.?.?.?.?.?.?\\(|\\).?.?.?.?.?.?.?.?\\)|\\*.?.?.?.?.?.?.?.?\\*|\\+.?.?.?.?.?.?.?.?\\+|\\x2c.?.?.?.?.?.?.?.?\\x2c|\\x2d.?.?.?.?.?.?.?.?\\x2d|\\..?.?.?.?.?.?.?.?\\.|\\x2f.?.?.?.?.?.?.?.?\\x2f|\\x30.?.?.?.?.?.?.?.?\\x30|\\x31.?.?.?.?.?.?.?.?\\x31|\\x32.?.?.?.?.?.?.?.?\\x32|\\x33.?.?.?.?.?.?.?.?\\x33|\\x34.?.?.?.?.?.?.?.?\\x34|\\x35.?.?.?.?.?.?.?.?\\x35|\\x36.?.?.?.?.?.?.?.?\\x36|\\x37.?.?.?.?.?.?.?.?\\x37|\\x38.?.?.?.?.?.?.?.?\\x38\ 146|\\x39.?.?.?.?.?.?.?.?\\x39|\\x3a.?.?.?.?.?.?.?.?\\x3a|\\x3b.?.?.?.?.?.?.?.?\\x3b|\\x3c.?.?.?.?.?.?.?.?\\x3c|\\x3d.?.?.?.?.?.?.?.?\\x3d|\\x3e.?.?.?.?.?.?.?.?\\x3e|\\?.?.?.?.?.?.?.?.?\\?|\\x40.?.?.?.?.?.?.?.?\\x40|\\x41.?.?.?.?.?.?.?.?\\x41|\\x42.?.?.?.?.?.?.?.?\\x42|\\x43.?.?.?.?.?.?.?.?\\x43|\\x44.?.?.?.?.?.?.?.?\\x44|\\x45.?.?.?.?.?.?.?.?\\x45|\\x46.?.?.?.?.?.?.?.?\\x46|\\x47.?.?.?.?.?.?.?.?\\x47|\\x48.?.?.?.?.?.?.?.?\\x48|\\x49.?.?.?.?.?.?.?.?\\x49|\\x4a.?.?.?.?.?.?.?.?\\x4a|\\x4b.?.?.?.?.?.?.?.?\\x4b\ 147|\\x4c.?.?.?.?.?.?.?.?\\x4c|\\x4d.?.?.?.?.?.?.?.?\\x4d|\\x4e.?.?.?.?.?.?.?.?\\x4e|\\x4f.?.?.?.?.?.?.?.?\\x4f|\\x50.?.?.?.?.?.?.?.?\\x50|\\x51.?.?.?.?.?.?.?.?\\x51|\\x52.?.?.?.?.?.?.?.?\\x52|\\x53.?.?.?.?.?.?.?.?\\x53|\\x54.?.?.?.?.?.?.?.?\\x54|\\x55.?.?.?.?.?.?.?.?\\x55|\\x56.?.?.?.?.?.?.?.?\\x56|\\x57.?.?.?.?.?.?.?.?\\x57|\\x58.?.?.?.?.?.?.?.?\\x58|\\x59.?.?.?.?.?.?.?.?\\x59|\\x5a.?.?.?.?.?.?.?.?\\x5a|\\[.?.?.?.?.?.?.?.?\\[|\\\\.?.?.?.?.?.?.?.?\\\\|\\].?.?.?.?.?.?.?.?\\]|\\^.?.?.?.?.?.?.?.?\\^\ 148|\\x5f.?.?.?.?.?.?.?.?\\x5f|\\x60.?.?.?.?.?.?.?.?\\x60|\\x61.?.?.?.?.?.?.?.?\\x61|\\x62.?.?.?.?.?.?.?.?\\x62|\\x63.?.?.?.?.?.?.?.?\\x63|\\x64.?.?.?.?.?.?.?.?\\x64|\\x65.?.?.?.?.?.?.?.?\\x65|\\x66.?.?.?.?.?.?.?.?\\x66|\\x67.?.?.?.?.?.?.?.?\\x67|\\x68.?.?.?.?.?.?.?.?\\x68|\\x69.?.?.?.?.?.?.?.?\\x69|\\x6a.?.?.?.?.?.?.?.?\\x6a|\\x6b.?.?.?.?.?.?.?.?\\x6b|\\x6c.?.?.?.?.?.?.?.?\\x6c|\\x6d.?.?.?.?.?.?.?.?\\x6d|\\x6e.?.?.?.?.?.?.?.?\\x6e|\\x6f.?.?.?.?.?.?.?.?\\x6f|\\x70.?.?.?.?.?.?.?.?\\x70|\\x71.?.?.?.?.?.?.?.?\\x71\ 149|\\x72.?.?.?.?.?.?.?.?\\x72|\\x73.?.?.?.?.?.?.?.?\\x73|\\x74.?.?.?.?.?.?.?.?\\x74|\\x75.?.?.?.?.?.?.?.?\\x75|\\x76.?.?.?.?.?.?.?.?\\x76|\\x77.?.?.?.?.?.?.?.?\\x77|\\x78.?.?.?.?.?.?.?.?\\x78|\\x79.?.?.?.?.?.?.?.?\\x79|\\x7a.?.?.?.?.?.?.?.?\\x7a|\\{.?.?.?.?.?.?.?.?\\{|\\|.?.?.?.?.?.?.?.?\\||\\}.?.?.?.?.?.?.?.?\\}|\\x7e.?.?.?.?.?.?.?.?\\x7e|\\x7f.?.?.?.?.?.?.?.?\\x7f|\\x80.?.?.?.?.?.?.?.?\\x80|\\x81.?.?.?.?.?.?.?.?\\x81|\\x82.?.?.?.?.?.?.?.?\\x82|\\x83.?.?.?.?.?.?.?.?\\x83|\\x84.?.?.?.?.?.?.?.?\\x84|\\x85.?.?.?.?.?.?.?.?\\x85\ 150|\\x86.?.?.?.?.?.?.?.?\\x86|\\x87.?.?.?.?.?.?.?.?\\x87|\\x88.?.?.?.?.?.?.?.?\\x88|\\x89.?.?.?.?.?.?.?.?\\x89|\\x8a.?.?.?.?.?.?.?.?\\x8a|\\x8b.?.?.?.?.?.?.?.?\\x8b|\\x8c.?.?.?.?.?.?.?.?\\x8c|\\x8d.?.?.?.?.?.?.?.?\\x8d|\\x8e.?.?.?.?.?.?.?.?\\x8e|\\x8f.?.?.?.?.?.?.?.?\\x8f|\\x90.?.?.?.?.?.?.?.?\\x90|\\x91.?.?.?.?.?.?.?.?\\x91|\\x92.?.?.?.?.?.?.?.?\\x92|\\x93.?.?.?.?.?.?.?.?\\x93|\\x94.?.?.?.?.?.?.?.?\\x94|\\x95.?.?.?.?.?.?.?.?\\x95|\\x96.?.?.?.?.?.?.?.?\\x96|\\x97.?.?.?.?.?.?.?.?\\x97|\\x98.?.?.?.?.?.?.?.?\\x98|\\x99.?.?.?.?.?.?.?.?\\x99\ 151|\\x9a.?.?.?.?.?.?.?.?\\x9a|\\x9b.?.?.?.?.?.?.?.?\\x9b|\\x9c.?.?.?.?.?.?.?.?\\x9c|\\x9d.?.?.?.?.?.?.?.?\\x9d|\\x9e.?.?.?.?.?.?.?.?\\x9e|\\x9f.?.?.?.?.?.?.?.?\\x9f|\\xa0.?.?.?.?.?.?.?.?\\xa0|\\xa1.?.?.?.?.?.?.?.?\\xa1|\\xa2.?.?.?.?.?.?.?.?\\xa2|\\xa3.?.?.?.?.?.?.?.?\\xa3|\\xa4.?.?.?.?.?.?.?.?\\xa4|\\xa5.?.?.?.?.?.?.?.?\\xa5|\\xa6.?.?.?.?.?.?.?.?\\xa6|\\xa7.?.?.?.?.?.?.?.?\\xa7|\\xa8.?.?.?.?.?.?.?.?\\xa8|\\xa9.?.?.?.?.?.?.?.?\\xa9|\\xaa.?.?.?.?.?.?.?.?\\xaa|\\xab.?.?.?.?.?.?.?.?\\xab|\\xac.?.?.?.?.?.?.?.?\\xac|\\xad.?.?.?.?.?.?.?.?\\xad\ 152|\\xae.?.?.?.?.?.?.?.?\\xae|\\xaf.?.?.?.?.?.?.?.?\\xaf|\\xb0.?.?.?.?.?.?.?.?\\xb0|\\xb1.?.?.?.?.?.?.?.?\\xb1|\\xb2.?.?.?.?.?.?.?.?\\xb2|\\xb3.?.?.?.?.?.?.?.?\\xb3|\\xb4.?.?.?.?.?.?.?.?\\xb4|\\xb5.?.?.?.?.?.?.?.?\\xb5|\\xb6.?.?.?.?.?.?.?.?\\xb6|\\xb7.?.?.?.?.?.?.?.?\\xb7|\\xb8.?.?.?.?.?.?.?.?\\xb8|\\xb9.?.?.?.?.?.?.?.?\\xb9|\\xba.?.?.?.?.?.?.?.?\\xba|\\xbb.?.?.?.?.?.?.?.?\\xbb|\\xbc.?.?.?.?.?.?.?.?\\xbc|\\xbd.?.?.?.?.?.?.?.?\\xbd|\\xbe.?.?.?.?.?.?.?.?\\xbe|\\xbf.?.?.?.?.?.?.?.?\\xbf|\\xc0.?.?.?.?.?.?.?.?\\xc0|\\xc1.?.?.?.?.?.?.?.?\\xc1\ 153|\\xc2.?.?.?.?.?.?.?.?\\xc2|\\xc3.?.?.?.?.?.?.?.?\\xc3|\\xc4.?.?.?.?.?.?.?.?\\xc4|\\xc5.?.?.?.?.?.?.?.?\\xc5|\\xc6.?.?.?.?.?.?.?.?\\xc6|\\xc7.?.?.?.?.?.?.?.?\\xc7|\\xc8.?.?.?.?.?.?.?.?\\xc8|\\xc9.?.?.?.?.?.?.?.?\\xc9|\\xca.?.?.?.?.?.?.?.?\\xca|\\xcb.?.?.?.?.?.?.?.?\\xcb|\\xcc.?.?.?.?.?.?.?.?\\xcc|\\xcd.?.?.?.?.?.?.?.?\\xcd|\\xce.?.?.?.?.?.?.?.?\\xce|\\xcf.?.?.?.?.?.?.?.?\\xcf|\\xd0.?.?.?.?.?.?.?.?\\xd0|\\xd1.?.?.?.?.?.?.?.?\\xd1|\\xd2.?.?.?.?.?.?.?.?\\xd2|\\xd3.?.?.?.?.?.?.?.?\\xd3|\\xd4.?.?.?.?.?.?.?.?\\xd4|\\xd5.?.?.?.?.?.?.?.?\\xd5\ 154|\\xd6.?.?.?.?.?.?.?.?\\xd6|\\xd7.?.?.?.?.?.?.?.?\\xd7|\\xd8.?.?.?.?.?.?.?.?\\xd8|\\xd9.?.?.?.?.?.?.?.?\\xd9|\\xda.?.?.?.?.?.?.?.?\\xda|\\xdb.?.?.?.?.?.?.?.?\\xdb|\\xdc.?.?.?.?.?.?.?.?\\xdc|\\xdd.?.?.?.?.?.?.?.?\\xdd|\\xde.?.?.?.?.?.?.?.?\\xde|\\xdf.?.?.?.?.?.?.?.?\\xdf|\\xe0.?.?.?.?.?.?.?.?\\xe0|\\xe1.?.?.?.?.?.?.?.?\\xe1|\\xe2.?.?.?.?.?.?.?.?\\xe2|\\xe3.?.?.?.?.?.?.?.?\\xe3|\\xe4.?.?.?.?.?.?.?.?\\xe4|\\xe5.?.?.?.?.?.?.?.?\\xe5|\\xe6.?.?.?.?.?.?.?.?\\xe6|\\xe7.?.?.?.?.?.?.?.?\\xe7|\\xe8.?.?.?.?.?.?.?.?\\xe8|\\xe9.?.?.?.?.?.?.?.?\\xe9\ 155|\\xea.?.?.?.?.?.?.?.?\\xea|\\xeb.?.?.?.?.?.?.?.?\\xeb|\\xec.?.?.?.?.?.?.?.?\\xec|\\xed.?.?.?.?.?.?.?.?\\xed|\\xee.?.?.?.?.?.?.?.?\\xee|\\xef.?.?.?.?.?.?.?.?\\xef|\\xf0.?.?.?.?.?.?.?.?\\xf0|\\xf1.?.?.?.?.?.?.?.?\\xf1|\\xf2.?.?.?.?.?.?.?.?\\xf2|\\xf3.?.?.?.?.?.?.?.?\\xf3|\\xf4.?.?.?.?.?.?.?.?\\xf4|\\xf5.?.?.?.?.?.?.?.?\\xf5|\\xf6.?.?.?.?.?.?.?.?\\xf6|\\xf7.?.?.?.?.?.?.?.?\\xf7|\\xf8.?.?.?.?.?.?.?.?\\xf8|\\xf9.?.?.?.?.?.?.?.?\\xf9|\\xfa.?.?.?.?.?.?.?.?\\xfa|\\xfb.?.?.?.?.?.?.?.?\\xfb|\\xfc.?.?.?.?.?.?.?.?\\xfc|\\xfd.?.?.?.?.?.?.?.?\\xfd\ 156|\\xfe.?.?.?.?.?.?.?.?\\xfe|\\xff.?.?.?.?.?.?.?.?\\xff)"}, 157 {"netgeareva", L7_ENUM_NETGEAREVA, 0, "^...\\x53\\x4a\\x61\\x6d"}, /*foxconn add by pingod, 07/12/2008*/ 158 //{"ftp", 7, 0, "^220[\\x09-\\x0d -~]*ftp"}, 159 //{"http", 8, 0, "http/(0\\.9|1\\.0|1\\.1) [1-5][0-9][0-9] [\\x09-\\x0d -~]*(connection:|content-type:|content-length:|date:)|post [\\x09-\\x0d -~]* http/[01]\\.[019]"}, 160 //{"msnmessenger", 9, 0, "ver [0-9]+ msnp[1-9][0-9]? [\\x09-\\x0d -~]*cvr0\\x0d\\x0a$|usr 1 [!-~]+ [0-9. ]+\\x0d\\x0a$|ans 1 [!-~]+ [0-9. ]+\\x0d\\x0a$"}, 161 //{"xunlei", 10, 0, "^[()]...?.?.?(reg|get|query)"}, 162 //{"ares", 11, 0, "^\\x03[]Z].?.?\\x05$"}, 163}; 164 165/* temporary buffer for pre-processing expression data */ 166static char g_exp[APP_DATA_BUF_MAX_LEN]; 167 168/* temporary buffer for converting app data into lowercase */ 169static char g_app_data[APP_DATA_BUF_MAX_LEN]; 170 171#ifdef L7_DEBUG_ON 172static int all_packet_in = 0; 173static int all_packet_out = 0; 174static int packet_has_pri_in = 0; 175static int packet_has_pri_out = 0; 176#endif 177 178 179/* Foxconn added start pling 11/08/2007 */ 180#define QOS_PRIORITY_HIGHEST 3 181#define QOS_PRIORITY_HIGH 2 182#define QOS_PRIORITY_NORMAL 1 183#define QOS_PRIORITY_LOW 0 184#define QOS_PRIORITY_UNSPECIFIED -1 185 186static int qos_l7_apps_priority[L7_ENUM_TOTAL + 1]; /* Apps enum starts from 1 to L7_ENUM_TOTAL, 0 is unused */ 187 188static void load_apps_priority(void) 189{ 190 char qos_l7_appls[1024]; 191 char *temp; 192 int apps, priority, i; 193 194 /* Set default apps priority */ 195 for (i=0; i<=L7_ENUM_TOTAL; i++) 196 qos_l7_apps_priority[i] = QOS_PRIORITY_UNSPECIFIED; 197 198 strcpy(qos_l7_appls, nvram_safe_get("qos_l7_apps")); 199 200 temp = strtok(qos_l7_appls, " "); 201 while (temp) 202 { 203 sscanf(temp, "%d:%d", &apps, &priority); 204 205 /* Do Sanity check */ 206 if (apps >= 1 && apps <= L7_ENUM_TOTAL && 207 priority >= QOS_PRIORITY_LOW && priority <= QOS_PRIORITY_HIGHEST) 208 { 209 printk("L7 apps %d, priority %d\n", apps, priority); 210 qos_l7_apps_priority[apps] = priority; 211 } 212 213 temp = strtok(NULL, " "); 214 } 215} 216 217#define QOS_DSCP_VALUE_HIGHEST (0x38 << 2) 218#define QOS_DSCP_VALUE_HIGH (0x28 << 2) 219#define QOS_DSCP_VALUE_NORMAL (0x0 << 2) 220#define QOS_DSCP_VALUE_LOW (0x10 << 2) 221 222unsigned char prio_to_dscp(unsigned char prio) 223{ 224 if (prio == QOS_PRIORITY_HIGHEST) 225 return QOS_DSCP_VALUE_HIGHEST; 226 else 227 if (prio == QOS_PRIORITY_HIGH) 228 return QOS_DSCP_VALUE_HIGH; 229 else 230 if (prio == QOS_PRIORITY_LOW) 231 return QOS_DSCP_VALUE_LOW; 232 else 233 return QOS_DSCP_VALUE_NORMAL; 234} 235 236UINT16 CalcChecksum(unsigned char *pbData, int iLength) 237{ 238 int nLeft = iLength % 2; /* this addr has odd byte? */ 239 UINT16 wChecksum; 240 int iIndex; 241 UINT32 dwSum = 0; 242 243 for (iIndex=0; iIndex < iLength-1; iIndex+=2) 244 { 245 dwSum += (pbData[iIndex] << 8) | (pbData[iIndex+1]); 246 } 247 248 if (nLeft != 0) 249 dwSum += (pbData[iLength-1] << 8); 250 251 252 dwSum = (dwSum >> 16) + (dwSum & 0xffff); /* add hi 16 to low 16 */ 253 dwSum += (dwSum >> 16); /* add carry */ 254 wChecksum = ~dwSum; /* truncate to 16 bits */ 255 return (wChecksum); 256 257} 258 259static int modify_dscp(struct sk_buff *skb, int apps) 260{ 261 int pkt_prio; 262 int l7_prio; 263 int i; 264 265 pkt_prio = skb->cb[sizeof(skb->cb) - 3]; 266 l7_prio = qos_l7_apps_priority[apps]; 267 268 //printk("#### Got L7apps %d, orig prio %d, l7 prio %d\n", apps, pkt_prio, l7_prio); 269 270 if (l7_prio > pkt_prio) 271 { 272 unsigned char *ipHdr; 273 unsigned int ipHdrLen; 274 UINT16 csum; 275 276#if 0 277 printk("skb->data: "); 278 279 for (i=0; i<20; i++) 280 printk("%02X ", (unsigned char)skb->data[i]); 281 printk("\n"); 282#endif 283 /* Get start of IP header & TCP header */ 284 ipHdr = &(skb->data[0]); 285 ipHdrLen = (ipHdr[0] & 0x0F) * 4; 286 287 /* Modify the DSCP value */ 288 ipHdr[1] = prio_to_dscp(l7_prio); 289 290 /* Recompute TCP checksum */ 291 ipHdr[10] = 0; 292 ipHdr[11] = 0; 293 csum = CalcChecksum(ipHdr, ipHdrLen); 294 ipHdr[10] = (csum & 0xFF00) >> 8; 295 ipHdr[11] = (csum & 0xFF); 296 297 // printk("!!!!!! Promote L7apps %d prio from %d to %d\n", apps, pkt_prio, l7_prio); 298 } 299 return 0; 300 301} 302/* Foxconn added end pling 11/08/2007 */ 303 304/*******function start*******/ 305 306unsigned char layer7_scan_all(struct sk_buff *skb, char *app_data, int appdatalen) 307{ 308 s_pattern_cache *node = first_pattern_cache; 309 int str_len = 0; 310 int i = 0; 311 312#ifdef L7_DEBUG_ON 313 L7_PRINTK_DEBUG_3("layer7_scan_all start\n"); 314#endif 315 316 str_len = ((sizeof(g_app_data)-1) > appdatalen) ? appdatalen : (sizeof(g_app_data)-1); 317 for (i=0; i<str_len; i++) 318 g_app_data[i] = tolower(app_data[i]); 319 g_app_data[i] = 0; 320 321 while (node != NULL) 322 { 323 if (regexec(node->pattern, g_app_data)) 324 { 325#ifdef L7_DEBUG_ON 326 L7_PRINTK_DEBUG_7("layer7 filter match: expression: %s\n", node->regex_string); 327 L7_PRINTK_DEBUG_1("layer7 filter match: protocol: %s\n", node->proto_name); 328#endif 329 return node->proto_enum; 330 } 331 332 node = node->next; 333 } 334 return 0;//dismatch 335} 336/* Returns offset the into the skb->data that the application data starts */ 337static int app_data_offset(const struct sk_buff *skb) 338{ 339 /* In case we are ported somewhere (ebtables?) where skb->nh.iph 340 isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ 341/* Fxcn port-S Wins, 0717-09 */ 342#ifdef LINUX26 343 int ip_hl = 4 * ip_hdr(skb)->ihl; 344#else /* LINUX26 */ 345/* Fxcn port-E Wins, 0717-09 */ 346 int ip_hl = 4*skb->nh.iph->ihl; 347/* Fxcn port-S Wins, 0717-09 */ 348#endif 349/* Fxcn port-E Wins, 0717-09 */ 350 351/* Fxcn port-S Wins, 0717-09 */ 352#ifdef LINUX26 353 if ( ip_hdr(skb)->protocol == IPPROTO_TCP ) 354#else /* LINUX26 */ 355/* Fxcn port-E Wins, 0717-09 */ 356 if ( skb->nh.iph->protocol == IPPROTO_TCP ) 357/* Fxcn port-S Wins, 0717-09 */ 358#endif /* LINUX26 */ 359/* Fxcn port-E Wins, 0717-09 */ 360 { 361 /* 12 == offset into TCP header for the header length field. 362 Can't get this with skb->h.th->doff because the tcphdr 363 struct doesn't get set when routing (this is confirmed to be 364 true in Netfilter as well as QoS.) */ 365 int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); 366 367 return ip_hl + tcp_hl; 368 } 369/* Fxcn port-S Wins, 0717-09 */ 370#ifdef LINUX26 371 else if ( ip_hdr(skb)->protocol == IPPROTO_UDP ) 372#else /* LINUX26 */ 373/* Fxcn port-E Wins, 0717-09 */ 374 else if ( skb->nh.iph->protocol == IPPROTO_UDP ) 375/* Fxcn port-S Wins, 0717-09 */ 376#endif /* LINUX26 */ 377/* Fxcn port-E Wins, 0717-09 */ 378 { 379 return ip_hl + 8; /* UDP header is always 8 bytes */ 380 } 381/* Fxcn port-S Wins, 0717-09 */ 382#ifdef LINUX26 383 else if ( ip_hdr(skb)->protocol == IPPROTO_ICMP ) 384#else /* LINUX26 */ 385/* Fxcn port-E Wins, 0717-09 */ 386 else if ( skb->nh.iph->protocol == IPPROTO_ICMP ) 387/* Fxcn port-S Wins, 0717-09 */ 388#endif /* LINUX26 */ 389/* Fxcn port-E Wins, 0717-09 */ 390 { 391 return ip_hl + 8; /* ICMP header is 8 bytes */ 392 } 393 else 394 { 395 if (net_ratelimit()) 396 L7_PRINTK_DEBUG_3(KERN_ERR "layer7: tried to handle unknown protocol!\n"); 397 return ip_hl + 8; /* something reasonable */ 398 } 399} 400 401int l7_filter_main(struct sk_buff *skb, int iDirection) 402{ 403 unsigned char *app_data; 404 unsigned int appdatalen; 405 T_ConnEntry *pConn; 406 unsigned char proto_enum = 0; 407 int iModifyType = 0; 408#ifdef L7_DEBUG_ON 409 int i = 0; 410 int iLen = sizeof(g_all_proto)/sizeof(g_all_proto[0]); 411#endif 412 413#ifdef L7_DEBUG_ON 414 L7_PRINTK_DEBUG_2("l7_filter_main start skb: %x, all_in out: %d %d, has_pri_in out: %d %d, in or out: %d\n", 415 skb, all_packet_in, all_packet_out, packet_has_pri_in, packet_has_pri_out, iDirection); 416 if (0 == ((all_packet_out+all_packet_in)&0xff))//print per 256 packets 417 L7_PRINTK_DEBUG_1("l7_filter_main start per 256, skb: %x, all_in out: %d %d, has_pri_in out: %d %d, in or out: %d\n", 418 skb, all_packet_in, all_packet_out, packet_has_pri_in, packet_has_pri_out, iDirection); 419 if (0 == ((all_packet_out+all_packet_in)&0x03ff))//list identified packets status of every proto per 1024 packets 420 { 421 L7_PRINTK_DEBUG_1("*********************** start ************************\n"); 422 L7_PRINTK_DEBUG_1("l7_filter_main per 1024, all_out: %d, has_pri_out: %d\n", 423 all_packet_out, packet_has_pri_out); 424 for (i=0; i<iLen; i++) 425 L7_PRINTK_DEBUG_1("Proto %s identified %d packets\n", g_all_proto[i].proto_name, g_all_proto[i].proto_packet_count); 426 L7_PRINTK_DEBUG_1("************************ end *************************\n"); 427 } 428 if (iDirection) 429 all_packet_out++; 430 else 431 all_packet_in++; 432#endif 433 434 if (NULL == skb) 435 return L7_ERROR; 436 437 skb->cb[sizeof(skb->cb)-4] = L7_ENUM_INIT;//initial value: -1(0xff) 438 439/* Fxcn port-S Wins, 0717-09 */ 440#ifdef LINUX26 441 pConn = FindConnByHash(ip_hdr(skb), &iModifyType, iDirection); 442#else /* LINUX26 */ 443/* Fxcn port-E Wins, 0717-09 */ 444 pConn = FindConnByHash(skb->nh.iph, &iModifyType, iDirection); 445/* Fxcn port-S Wins, 0717-09 */ 446#endif /* LINUX26 */ 447/* Fxcn port-E Wins, 0717-09 */ 448 449 if (NULL == pConn) 450 { 451#ifdef L7_DEBUG_ON 452 if (iDirection) 453 L7_PRINTK_DEBUG_2("l7_filter_main FindConnByHash fail.\n"); 454#endif 455 return L7_SUCCESS; 456 } 457 458#ifdef L7_DEBUG_ON 459 L7_PRINTK_DEBUG_3("l7_filter_main pConn: %x, pConn->packet_count: %d\n", pConn, pConn->packet_count); 460#endif 461 if (pConn->proto_enum != 0) 462 { 463 if (iDirection) 464 { 465#ifdef L7_DEBUG_ON 466 packet_has_pri_out++; 467 g_all_proto[pConn->proto_enum-1].proto_packet_count++; 468#endif 469 skb->cb[sizeof(skb->cb)-4] = pConn->proto_enum; 470 if (skb->cb[sizeof(skb->cb)-5]) 471 modify_dscp(skb, pConn->proto_enum); 472 } 473#ifdef L7_DEBUG_ON 474 else 475 packet_has_pri_in++; 476 L7_PRINTK_DEBUG_3("l7_filter_main pConn->proto_enum: %d\n", pConn->proto_enum); 477#endif 478 return L7_SUCCESS; 479 } 480 481 if (pConn->packet_count > num_packets) 482 { 483#ifdef L7_DEBUG_ON 484 L7_PRINTK_DEBUG_3("too many packets, l7_filter_main pConn->packet_count: %d\n", pConn->packet_count); 485#endif 486 if (iDirection) 487 { 488 skb->cb[sizeof(skb->cb)-4] = pConn->proto_enum; 489 if (skb->cb[sizeof(skb->cb)-5]) 490 modify_dscp(skb, pConn->proto_enum); 491 } 492 493 return L7_SUCCESS; 494 } 495 pConn->packet_count++; 496 497 if (skb_is_nonlinear(skb)) 498 { 499/* Fxcn port-S Wins, 0717-09 */ 500#ifdef LINUX26 501 if (skb_linearize(skb) != 0) 502#else /* LINUX26 */ 503/* Fxcn port-E Wins, 0717-09 */ 504 if (skb_linearize(skb, GFP_ATOMIC) != 0) 505/* Fxcn port-S Wins, 0717-09 */ 506#endif /* LINUX26 */ 507/* Fxcn port-E Wins, 0717-09 */ 508 { 509 if (net_ratelimit()) 510 L7_PRINTK_DEBUG_1(KERN_ERR "layer7: failed to linearize packet, bailing.\n"); 511 return L7_SUCCESS; 512 } 513 } 514 515 /* now that the skb is linearized, it's safe to set these. */ 516 app_data = skb->data + app_data_offset(skb); 517 appdatalen = skb->tail - app_data; 518 519 proto_enum = layer7_scan_all(skb, app_data, appdatalen); 520 521 if (proto_enum == L7_ENUM_NETGEAREVA) 522 { 523 if ((pConn->bProtocol != UDP_PROTOCOL) 524 || ((pConn->bNatType != AG_PORT_FORWARDING) 525 && ((ntohs(pConn->wDestPort) < EVA_PORT_START) || (ntohs(pConn->wDestPort) > EVA_PORT_END))) 526 || ((pConn->bNatType == AG_PORT_FORWARDING) 527 && ((ntohs(pConn->wSourcePort) < EVA_PORT_START) || (ntohs(pConn->wSourcePort) > EVA_PORT_END)))) 528 { 529 proto_enum = 0; 530 } 531 } 532 533 if (proto_enum != 0) 534 { 535#ifdef L7_DEBUG_ON 536 L7_PRINTK_DEBUG_1("l7_filter_main identify the conn %x, in %dth packet.\n", pConn, pConn->packet_count); 537#endif 538 if (iDirection) 539 { 540#ifdef L7_DEBUG_ON 541 packet_has_pri_out++; 542 g_all_proto[proto_enum-1].proto_packet_count++; 543#endif 544 skb->cb[sizeof(skb->cb)-4] = proto_enum; 545 if (skb->cb[sizeof(skb->cb)-5]) 546 modify_dscp(skb, pConn->proto_enum); 547 } 548#ifdef L7_DEBUG_ON 549 else 550 packet_has_pri_in++; 551#endif 552 pConn->proto_enum = proto_enum; 553 return L7_SUCCESS; 554 } 555 return L7_SUCCESS; 556} 557 558static int isxdigit(char c) 559{ 560 if ((c >= '0' && c <= '9') 561 || (c >= 'a' && c <= 'f') 562 || (c >= 'A' && c <= 'F')) 563 return 1; 564 else 565 return 0; 566} 567 568static char tolower(char c) 569{ 570 if (c >= 'A' && c <= 'Z') 571 c += 0x20; 572 return c; 573} 574 575static int hex2dec(char c) 576{ 577 switch (c) 578 { 579 case '0' ... '9': 580 return c - '0'; 581 case 'a' ... 'f': 582 return c - 'a' + 10; 583 case 'A' ... 'F': 584 return c - 'A' + 10; 585 default: 586#ifdef L7_DEBUG_ON 587 L7_PRINTK_DEBUG_2("hex2dec: bad value!\n"); 588#endif 589 return 0; 590 } 591} 592 593int pre_process(char *str_out, char *str_in, int str_out_len) 594{ 595 char *result = str_out; 596 char *s = str_in; 597 int sindex = 0, rindex = 0; 598 599 while ( sindex < strlen(s) && (rindex + 1 < str_out_len)) 600 { 601 if ( sindex + 3 < strlen(s) && 602 s[sindex] == '\\' && s[sindex+1] == 'x' && 603 isxdigit(s[sindex + 2]) && isxdigit(s[sindex + 3]) ) 604 { 605 /* carefully remember to call tolower here... */ 606 result[rindex] = tolower( hex2dec(s[sindex + 2])*16 + 607 hex2dec(s[sindex + 3] ) ); 608 609 switch ( result[rindex] ) 610 { 611 case 0x24: 612 case 0x28: 613 case 0x29: 614 case 0x2a: 615 case 0x2b: 616 case 0x2e: 617 case 0x3f: 618 case 0x5b: 619 case 0x5c: 620 case 0x5d: 621 case 0x5e: 622 case 0x7c: 623#ifdef L7_DEBUG_ON 624 L7_PRINTK_DEBUG_1("Warning: layer7 regexp contains a control character, %c, in hex (\\x%c%c).\n" 625 "I recommend that you write this as %c or \\%c, depending on what you meant.\n", 626 result[rindex], s[sindex + 2], s[sindex + 3], result[rindex], result[rindex]); 627#endif 628 break; 629 case 0x00: 630#ifdef L7_DEBUG_ON 631 L7_PRINTK_DEBUG_1("Warning: null (\\x00) in layer7 regexp. A null terminates the regexp string!\n"); 632#endif 633 break; 634 default: 635 break; 636 } 637 638 sindex += 3; /* 4 total */ 639 } 640 else 641 result[rindex] = tolower(s[sindex]); 642 643 sindex++; 644 rindex++; 645 } 646 result[rindex] = '\0'; 647 648 if (rindex > 0) 649 return 0; 650 else 651 return 1; 652} 653 654int load_all_pattern(void) 655{ 656 /* establish the link list of patterns*/ 657 s_pattern_cache * node = first_pattern_cache; 658 s_pattern_cache * tmp; 659 unsigned int len; 660 unsigned int num_proto = sizeof(g_all_proto)/sizeof(s_proto_regexp); 661 int i = 0; 662 663#ifdef L7_DEBUG_ON 664 L7_PRINTK_DEBUG_1("l7 filter, load_all_pattern start, num_proto: %d\n", num_proto); 665#endif 666 667 for (i=0; i<num_proto; i++) 668 { 669#ifdef L7_DEBUG_ON 670 L7_PRINTK_DEBUG_2("load_all_pattern for loop: %d, proto_regexp: %s,\n 671 sizeof(s_pattern_cache): %d.\n", 672 i, g_all_proto[i].proto_regexp, sizeof(s_pattern_cache)); 673#endif 674 if (0 != pre_process(g_exp, g_all_proto[i].proto_regexp, sizeof(g_exp))) 675 continue; 676 677 /* Be paranoid about running out of memory to avoid list corruption. */ 678 tmp = kmalloc(sizeof(s_pattern_cache), GFP_ATOMIC); 679 if (!tmp) 680 { 681 L7_PRINTK_DEBUG_1("layer7: out of memory in compile_and_cache, bailing. 1\n"); 682 if (net_ratelimit()) 683 L7_PRINTK_DEBUG_1(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n"); 684 return NULL; 685 } 686 687 tmp->regex_string = kmalloc(strlen(g_exp) + 1, GFP_ATOMIC); 688 if (NULL == tmp->regex_string) 689 { 690 L7_PRINTK_DEBUG_1("layer7: out of memory in compile_and_cache, bailing. 2\n"); 691 if (net_ratelimit()) 692 L7_PRINTK_DEBUG_1(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n"); 693 kfree(tmp); 694 return NULL; 695 } 696 697 tmp->pattern = regcomp(g_exp, &len); 698 if (NULL == tmp->pattern) 699 { 700 L7_PRINTK_DEBUG_1("layer7: out of memory in compile_and_cache, bailing. 3\n"); 701 if (net_ratelimit()) 702 L7_PRINTK_DEBUG_1(KERN_ERR "layer7: out of memory in compile_and_cache, bailing.\n"); 703 kfree(tmp->regex_string); 704 kfree(tmp); 705 return NULL; 706 } 707 708 strcpy(tmp->regex_string, g_exp); 709 tmp->next = NULL; 710 tmp->proto_enum = g_all_proto[i].proto_enum; 711 tmp->proto_name = g_all_proto[i].proto_name; 712 713#ifdef L7_DEBUG_ON 714 L7_PRINTK_DEBUG_2("regexp: %s\n", tmp->proto_name); 715 L7_PRINTK_DEBUG_2("tmp->pattern->regstart: %d\n", tmp->pattern->regstart); 716 L7_PRINTK_DEBUG_2("tmp->pattern->reganch: %d\n", tmp->pattern->reganch); 717 if (tmp->pattern->regmust != NULL) 718 L7_PRINTK_DEBUG_2("tmp->pattern->regmust: %s\n", tmp->pattern->regmust); 719 L7_PRINTK_DEBUG_2("tmp->pattern->regmlen: %d\n", tmp->pattern->regmlen); 720 L7_PRINTK_DEBUG_2("tmp->pattern->program[0]: %d\n", tmp->pattern->program[0]); 721#endif/* end of #ifdef L7_DEBUG_ON */ 722 if (NULL == node) 723 { 724 node = tmp; 725 first_pattern_cache = tmp; 726 } 727 else 728 { 729 node->next = tmp; 730 node = tmp; 731 } 732 } 733 734 return 1; 735} 736 737void free_all_pattern(void) 738{ 739 s_pattern_cache *node = first_pattern_cache; 740 s_pattern_cache *tmp; 741 742 while (node != NULL) 743 { 744 if (node->regex_string != NULL) 745 kfree(node->regex_string); 746 if (node->pattern != NULL) 747 kfree(node->pattern); 748 749 tmp = node; 750 node = node->next; 751 kfree(tmp); 752 } 753} 754 755 756 757static int __init init(void) 758{ 759 int ret = 0; 760 761#ifdef CONFIG_NETFILTER 762 ret = nf_register_hook(&l7_filter_prerouting_ops); 763 if (ret < 0) { 764 printk("<0>Error registering l7 filter prerouting.\n"); 765 nf_unregister_hook(&l7_filter_prerouting_ops); 766 return ret; 767 } 768 ret = nf_register_hook(&l7_filter_postrouting_ops); 769 if (ret < 0) { 770 printk("<0>Error registering l7 filter postrouting.\n"); 771 return ret; 772 } 773#else /* CONFIG_NETFILTER */ 774 acosL7Filter_register_hook(l7_filter_main); 775#endif /* CONFIG_NETFILTER */ 776 777 load_all_pattern(); 778 779 load_apps_priority(); /* Foxconn added pling 11/08/2007 */ 780 781 return ret; 782} 783 784static void __exit fini(void) 785{ 786#ifdef CONFIG_NETFILTER 787 nf_unregister_hook(&l7_filter_prerouting_ops); 788 nf_unregister_hook(&l7_filter_postrouting_ops); 789#else 790 acosL7Filter_register_hook(NULL); 791#endif /* CONFIG_NETFILTER */ 792 793 free_all_pattern(); 794} 795 796module_init(init); 797module_exit(fini); 798 799EXPORT_SYMBOL(l7_filter_main); 800