📄 100-netfilter_layer7_2.17.patch
字号:
+ printk(KERN_ERR "layer7: out of memory in "+ "match, bailing.\n");+ spin_unlock_bh(&l7_lock);+ return info->invert;+ }++ master_conntrack->layer7.app_data[0] = '\0';+ }++ /* Can be here, but unallocated, if numpackets is increased near+ the beginning of a connection */+ if(master_conntrack->layer7.app_data == NULL){+ spin_unlock_bh(&l7_lock);+ return (info->invert); /* unmatched */+ }++ if(!skb->cb[0]){+ int newbytes;+ newbytes = add_data(master_conntrack, app_data, appdatalen);++ if(newbytes == 0) { /* didn't add any data */+ skb->cb[0] = 1;+ /* Didn't match before, not going to match now */+ spin_unlock_bh(&l7_lock);+ return info->invert;+ }+ }++ /* If looking for "unknown", then never match. "Unknown" means that+ we've given up; we're still trying with these packets. */+ if(!strcmp(info->protocol, "unknown")) {+ pattern_result = 0;+ /* If looking for "unset", then always match. "Unset" means that we+ haven't yet classified the connection. */+ } else if(!strcmp(info->protocol, "unset")) {+ pattern_result = 2;+ DPRINTK("layer7: matched unset: not yet classified "+ "(%d/%d packets)\n", TOTAL_PACKETS, num_packets);+ /* If the regexp failed to compile, don't bother running it */+ } else if(comppattern && + regexec(comppattern, master_conntrack->layer7.app_data)){+ DPRINTK("layer7: matched %s\n", info->protocol);+ pattern_result = 1;+ } else pattern_result = 0;++ if(pattern_result == 1) {+ master_conntrack->layer7.app_proto = + kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);+ if(!master_conntrack->layer7.app_proto){+ if (net_ratelimit())+ printk(KERN_ERR "layer7: out of memory in "+ "match, bailing.\n");+ spin_unlock_bh(&l7_lock);+ return (pattern_result ^ info->invert);+ }+ strcpy(master_conntrack->layer7.app_proto, info->protocol);+ } else if(pattern_result > 1) { /* cleanup from "unset" */+ pattern_result = 1;+ }++ /* mark the packet seen */+ skb->cb[0] = 1;++ spin_unlock_bh(&l7_lock);+ return (pattern_result ^ info->invert);+}++static int check(const char *tablename,+ const void *inf,+ const struct xt_match *match,+ void *matchinfo,+ unsigned int hook_mask)++{+ // load nf_conntrack_ipv4+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {+ printk(KERN_WARNING "can't load conntrack support for "+ "proto=%d\n", match->family);+ return false;+ }+ return true;+}++static void+destroy(const struct xt_match *match, void *matchinfo)+{+ nf_ct_l3proto_module_put(match->family);+}++static struct xt_match xt_layer7_match[] = {+{+ .name = "layer7",+ .family = AF_INET,+ .checkentry = check,+ .match = match,+ .destroy = destroy,+ .matchsize = sizeof(struct xt_layer7_info),+ .me = THIS_MODULE+}+};++static void layer7_cleanup_proc(void)+{+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)+ remove_proc_entry("layer7_numpackets", proc_net);+#else+ remove_proc_entry("layer7_numpackets", init_net.proc_net);+#endif+}++/* register the proc file */+static void layer7_init_proc(void)+{+ struct proc_dir_entry* entry;+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)+ entry = create_proc_entry("layer7_numpackets", 0644, proc_net);+#else+ entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net);+#endif+ entry->read_proc = layer7_read_proc;+ entry->write_proc = layer7_write_proc;+}++static int __init xt_layer7_init(void)+{+ need_conntrack();++ layer7_init_proc();+ if(maxdatalen < 1) {+ printk(KERN_WARNING "layer7: maxdatalen can't be < 1, "+ "using 1\n");+ maxdatalen = 1;+ }+ /* This is not a hard limit. It's just here to prevent people from+ bringing their slow machines to a grinding halt. */+ else if(maxdatalen > 65536) {+ printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "+ "using 65536\n");+ maxdatalen = 65536;+ }+ return xt_register_matches(xt_layer7_match,+ ARRAY_SIZE(xt_layer7_match));+}++static void __exit xt_layer7_fini(void)+{+ layer7_cleanup_proc();+ xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match));+}++module_init(xt_layer7_init);+module_exit(xt_layer7_fini);Index: linux-2.6.21.7/net/netfilter/regexp/regexp.c===================================================================--- /dev/null+++ linux-2.6.21.7/net/netfilter/regexp/regexp.c@@ -0,0 +1,1197 @@+/*+ * regcomp and regexec -- regsub and regerror are elsewhere+ * @(#)regexp.c 1.3 of 18 April 87+ *+ * Copyright (c) 1986 by University of Toronto.+ * Written by Henry Spencer. Not derived from licensed software.+ *+ * Permission is granted to anyone to use this software for any+ * purpose on any computer system, and to redistribute it freely,+ * subject to the following restrictions:+ *+ * 1. The author is not responsible for the consequences of use of+ * this software, no matter how awful, even if they arise+ * from defects in it.+ *+ * 2. The origin of this software must not be misrepresented, either+ * by explicit claim or by omission.+ *+ * 3. Altered versions must be plainly marked as such, and must not+ * be misrepresented as being the original software.+ *+ * Beware that some of this code is subtly aware of the way operator+ * precedence is structured in regular expressions. Serious changes in+ * regular-expression syntax might require a total rethink.+ *+ * This code was modified by Ethan Sommer to work within the kernel+ * (it now uses kmalloc etc..)+ *+ * Modified slightly by Matthew Strait to use more modern C.+ */++#include "regexp.h"+#include "regmagic.h"++/* added by ethan and matt. Lets it work in both kernel and user space.+(So iptables can use it, for instance.) Yea, it goes both ways... */+#if __KERNEL__+ #define malloc(foo) kmalloc(foo,GFP_ATOMIC)+#else+ #define printk(format,args...) printf(format,##args)+#endif++void regerror(char * s)+{+ printk("<3>Regexp: %s\n", s);+ /* NOTREACHED */+}++/*+ * The "internal use only" fields in regexp.h are present to pass info from+ * compile to execute that permits the execute phase to run lots faster on+ * simple cases. They are:+ *+ * regstart char that must begin a match; '\0' if none obvious+ * reganch is the match anchored (at beginning-of-line only)?+ * regmust string (pointer into program) that match must include, or NULL+ * regmlen length of regmust string+ *+ * Regstart and reganch permit very fast decisions on suitable starting points+ * for a match, cutting down the work a lot. Regmust permits fast rejection+ * of lines that cannot possibly match. The regmust tests are costly enough+ * that regcomp() supplies a regmust only if the r.e. contains something+ * potentially expensive (at present, the only such thing detected is * or ++ * at the start of the r.e., which can involve a lot of backup). Regmlen is+ * supplied because the test in regexec() needs it and regcomp() is computing+ * it anyway.+ */++/*+ * Structure for regexp "program". This is essentially a linear encoding+ * of a nondeterministic finite-state machine (aka syntax charts or+ * "railroad normal form" in parsing technology). Each node is an opcode+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of+ * all nodes except BRANCH implement concatenation; a "next" pointer with+ * a BRANCH on both ends of it is connecting two alternatives. (Here we+ * have one of the subtle syntax dependencies: an individual BRANCH (as+ * opposed to a collection of them) is never concatenated with anything+ * because of operator precedence.) The operand of some types of node is+ * a literal string; for others, it is a node leading into a sub-FSM. In+ * particular, the operand of a BRANCH node is the first node of the branch.+ * (NB this is *not* a tree structure: the tail of the branch connects+ * to the thing following the set of BRANCHes.) The opcodes are:+ */++/* definition number opnd? meaning */+#define END 0 /* no End of program. */+#define BOL 1 /* no Match "" at beginning of line. */+#define EOL 2 /* no Match "" at end of line. */+#define ANY 3 /* no Match any one character. */+#define ANYOF 4 /* str Match any character in this string. */+#define ANYBUT 5 /* str Match any character not in this string. */+#define BRANCH 6 /* node Match this alternative, or the next... */+#define BACK 7 /* no Match "", "next" ptr points backward. */+#define EXACTLY 8 /* str Match this string. */+#define NOTHING 9 /* no Match empty string. */+#define STAR 10 /* node Match this (simple) thing 0 or more times. */+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */+#define OPEN 20 /* no Mark this point in input as start of #n. */+ /* OPEN+1 is number 1, etc. */+#define CLOSE 30 /* no Analogous to OPEN. */++/*+ * Opcode notes:+ *+ * BRANCH The set of branches constituting a single choice are hooked+ * together with their "next" pointers, since precedence prevents+ * anything being concatenated to any individual branch. The+ * "next" pointer of the last BRANCH in a choice points to the+ * thing following the whole choice. This is also where the+ * final "next" pointer of each individual branch points; each+ * branch starts with the operand node of a BRANCH node.+ *+ * BACK Normal "next" pointers all implicitly point forward; BACK+ * exists to make loop structures possible.+ *+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular+ * BRANCH structures using BACK. Simple cases (one character+ * per match) are implemented with STAR and PLUS for speed+ * and to minimize recursive plunges.+ *+ * OPEN,CLOSE ...are numbered at compile time.+ */++/*+ * A node is one char of opcode followed by two chars of "next" pointer.+ * "Next" pointers are stored as two 8-bit pieces, high order first. The+ * value is a positive offset from the opcode of the node containing it.+ * An operand, if any, simply follows the node. (Note that much of the+ * code generation knows about this implicit relationship.)+ *+ * Using two bytes for the "next" pointer is vast overkill for most things,+ * but allows patterns to get big without disasters.+ */+#define OP(p) (*(p))+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))+#define OPERAND(p) ((p) + 3)++/*+ * See regmagic.h for one further detail of program structure.+ */+++/*+ * Utility definitions.+ */+#ifndef CHARBITS+#define UCHARAT(p) ((int)*(unsigned char *)(p))+#else+#define UCHARAT(p) ((int)*(p)&CHARBITS)+#endif++#define FAIL(m) { regerror(m); return(NULL); }+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')+#define META "^$.[()|?+*\\"++/*+ * Flags to be passed up and down.+ */+#define HASWIDTH 01 /* Known never to match null string. */+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */+#define SPSTART 04 /* Starts with * or +. */+#define WORST 0 /* Worst case. */++/*+ * Global work variables for regcomp().+ */+struct match_globals {+char *reginput; /* String-input pointer. */+char *regbol; /* Beginning of input, for ^ check. */+char **regstartp; /* Pointer to startp array. */+char **regendp; /* Ditto for endp. */+char *regparse; /* Input-scan pointer. */+int regnpar; /* () count. */+char regdummy;+char *regcode; /* Code-emit pointer; ®dummy = don't. */+long regsize; /* Code size. */+};++/*+ * Forward declarations for regcomp()'s friends.+ */+#ifndef STATIC+#define STATIC static+#endif+STATIC char *reg(struct match_globals *g, int paren,int *flagp);+STATIC char *regbranch(struct match_globals *g, int *flagp);+STATIC char *regpiece(struct match_globals *g, int *flagp);+STATIC char *regatom(struct match_globals *g, int *flagp);+STATIC char *regnode(struct match_globals *g, char op);+STATIC char *regnext(struct match_globals *g, char *p);+STATIC void regc(struct match_globals *g, char b);+STATIC void reginsert(struct match_globals *g, char op, char *opnd);+STATIC void regtail(struct match_globals *g, char *p, char *val);+STATIC void regoptail(struct match_globals *g, char *p, char *val);+++__kernel_size_t my_strcspn(const char *s1,const char *s2)+{+ char *scan1;+ char *scan2;+ int count;++ count = 0;+ for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {+ for (scan2 = (char *)s2; *scan2 != '\0';) /* ++ moved down. */+ if (*scan1 == *scan2++)+ return(count);+ count++;+ }+ return(count);+}++/*+ - regcomp - compile a regular expression into internal code+ *+ * We can't allocate space until we know how big the compiled form will be,+ * but we can't compile it (and thus know how big it is) until we've got a+ * place to put the code. So we cheat: we compile it twice, once with code+ * generation turned off and size counting turned on, and once "for real".+ * This also means that we don't allocate space until we are sure that the+ * thing really will compile successfully, and we never have to move the+ * code and thus invalidate pointers into it. (Note that it has to be in+ * one piece because free() must be able to free it all.)+ *+ * Beware that the optimization-preparation code in here knows about some+ * of the structure of the compiled regexp.+ */+regexp *+regcomp(char *exp,int *patternsize)+{+ register regexp *r;+ register char *scan;+ register char *longest;+ register int len;+ int flags;+ struct match_globals g;+ + /* commented out by ethan+ extern char *malloc();+ */++ if (exp == NULL)+ FAIL("NULL argument");++ /* First pass: determine size, legality. */+ g.regparse = exp;+ g.regnpar = 1;+ g.regsize = 0L;+ g.regcode = &g.regdummy;+ regc(&g, MAGIC);+ if (reg(&g, 0, &flags) == NULL)+ return(NULL);++ /* Small enough for pointer-storage convention? */+ if (g.regsize >= 32767L) /* Probably could be 65535L. */+ FAIL("regexp too big");++ /* Allocate space. */+ *patternsize=sizeof(regexp) + (unsigned)g.regsize;+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)g.regsize);+ if (r == NULL)+ FAIL("out of space");++ /* Second pass: emit code. */+ g.regparse = exp;+ g.regnpar = 1;+ g.regcode = r->program;+ regc(&g, MAGIC);+ if (reg(&g, 0, &flags) == NULL)+ return(NULL);++ /* Dig out information for optimizations. */+ r->regstart = '\0'; /* Worst-case defaults. */+ r->reganch = 0;+ r->regmust = NULL;+ r->regmlen = 0;+ scan = r->program+1; /* First BRANCH. */+ if (OP(regnext(&g, scan)) == END) { /* Only one top-level choice. */+ scan = OPERAND(scan);++ /* Starting-point info. */+ if (OP(scan) == EXACTLY)+ r->regstart = *OPERAND(scan);+ else if (OP(scan) == BOL)+ r->reganch++;++ /*+ * If there's something expensive in the r.e., find the+ * longest literal string that must appear and make it the+ * regmust. Resolve ties in favor of later strings, since+ * the regstart check works with the beginning of the r.e.+ * and avoiding duplication strengthens checking. Not a+ * strong reason, but sufficient in the absence of others.+ */+ if (flags&SPSTART) {+ longest = NULL;+ len = 0;+ for (; scan != NULL; scan = regnext(&g, scan))+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {+ longest = OPERAND(scan);+ len = strlen(OPERAND(scan));+ }+ r->regmust = longest;+ r->regmlen = len;+ }+ }++ return(r);+}++/*+ - reg - regular expression, i.e. main body or parenthesized thing+ *+ * Caller must absorb opening parenthesis.+ *+ * Combining parenthesis handling with the base level of regular expression+ * is a trifle forced, but the need to tie the tails of the branches to what+ * follows makes it hard to avoid.+ */+static char *+reg(struct match_globals *g, int paren, int *flagp /* Parenthesized? */ )+{+ register char *ret;+ register char *br;+ register char *ender;+ register int parno = 0; /* 0 makes gcc happy */+ int flags;++ *flagp = HASWIDTH; /* Tentatively. */++ /* Make an OPEN node, if parenthesized. */+ if (paren) {+ if (g->regnpar >= NSUBEXP)+ FAIL("too many ()");+ parno = g->regnpar;+ g->regnpar++;+ ret = regnode(g, OPEN+parno);+ } else+ ret = NULL;++ /* Pick up the branches, linking them together. */+ br = regbranch(g, &flags);+ if (br == NULL)+ return(NULL);+ if (ret != NULL)+ regtail(g, ret, br); /* OPEN -> first. */+ else+ ret = br;+ if (!(flags&HASWIDTH))+ *flagp &= ~HASWIDTH;+ *flagp |= flags&SPSTART;+ while (*g->regparse == '|') {+ g->regparse++;+ br = regbranch(g, &flags);+ if (br == NULL)+ return(NULL);+ regtail(g, ret, br); /* BRANCH -> BRANCH. */+ if (!(flags&HASWIDTH))+ *flagp &= ~HASWIDTH;+ *flagp |= flags&SPSTART;+ }++ /* Make a closing node, and hook it on the end. */+ ender = regnode(g, (paren) ? CLOSE+parno : END); + regtail(g, ret, ender);++ /* Hook the tails of the branches to the closing node. */+ for (br = ret; br != NULL; br = regnext(g, br))+ regoptail(g, br, ender);++ /* Check for proper termination. */+ if (paren && *g->regparse++ != ')') {+ FAIL("unmatched ()");+ } else if (!paren && *g->regparse != '\0') {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -