?? l7-classify.cpp
字號:
/* Functions and classes which keep track of and use regexes to classify streams of application data. By Ethan Sommer <sommere@users.sf.net> and Matthew Strait <quadong@users.sf.net>, (C) 2006-2007 http://l7-filter.sf.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. http://www.gnu.org/licenses/gpl.txt*/using namespace std;#include <iostream>#include <fstream>#include <vector>#include <string>#include <sstream>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <signal.h>#include <dirent.h>#define MAX_SUBDIRS 128#define MAX_FN_LEN 256string l7dir = "/etc/l7-protocols";// by default, take the whole thing.// The second two are derivable from the first. They're here for convenience.unsigned int markmask = 0xffffffff; // the mask itselfunsigned int maskfirstbit = 0; // how far from the LSB does our region start?unsigned int masknbits = 32;#include "l7-classify.h"#include "l7-queue.h"#include "l7-parse-patterns.h"#include "util.h"l7_pattern::l7_pattern(string name, string pattern_string, int eflags, int cflags, int mark){ this->name = name; this->pattern_string = pattern_string; this->eflags = eflags; this->cflags = cflags; this->mark = mark; char *preprocessed = pre_process(pattern_string.c_str()); int rc = regcomp(&preg, preprocessed, cflags); if (rc != 0){ cerr << "error compiling " << name << " -- " << pattern_string << endl; exit(1); }}int l7_pattern::hex2dec(char c) { switch (c){ case '0' ... '9': return c - '0'; case 'a' ... 'f': return c - 'a' + 10; case 'A' ... 'F': return c - 'A' + 10; default: cerr << "Bad hex digit, " << c << ", in regular expression!" << endl; exit(1); }}char * l7_pattern::pre_process(const char * s) { char * result = (char *)malloc(strlen(s) + 1); int sindex = 0, rindex = 0; while( sindex < strlen(s) ) { if( sindex + 3 < strlen(s) && s[sindex] == '\\' && s[sindex+1] == 'x' && isxdigit(s[sindex + 2]) && isxdigit(s[sindex + 3]) ){ result[rindex] = hex2dec(s[sindex + 2])*16 + hex2dec(s[sindex + 3]); switch ( result[rindex] ) { case '$': case '(': case ')': case '*': case '+': case '.': case '?': case '[': case ']': case '^': case '|': case '{': case '}': case '\\': cerr << "Warning: regexp contains a regexp control character, " << result[rindex] << ", in hex (\\x" << s[sindex + 2] << s[sindex+3] << ".\nI recommend that you write this as " << result[rindex] << " or \\" << result[rindex] << " depending on what you meant.\n"; break; case '\0': cerr << "Warning: null (\\x00) in layer7 regexp. " << "A null terminates the regexp string!\n"; break; default: break; } sindex += 3; /* 4 total */ } else result[rindex] = s[sindex]; sindex++; rindex++; } result[rindex] = '\0'; return result;}bool l7_pattern::matches(char *buffer) { int rc = regexec(&preg, buffer, 0, NULL, eflags); if(rc == 0) return true; else return false;}string l7_pattern::getName() { return name;}int l7_pattern::getMark() { return mark;}static char ** readl7dir(string dirname){ DIR * scratchdir; struct dirent ** namelist; char ** subdirs = (char **)malloc(MAX_SUBDIRS * sizeof(char *)); int n, d = 1; subdirs[0] = ""; n = scandir(dirname.c_str(), &namelist, 0, alphasort); if (n < 0){ perror("scandir"); cerr << "Couldn't open " << dirname << endl; exit(1); } else{ while(n--){ char fulldirname[MAX_FN_LEN]; snprintf(fulldirname, MAX_FN_LEN, "%s/%s", dirname.c_str(), namelist[n]->d_name); if((scratchdir = opendir(fulldirname)) != NULL) { closedir(scratchdir); if(!strcmp(namelist[n]->d_name, ".") || !strcmp(namelist[n]->d_name, "..")) /* do nothing */ ; else{ subdirs[d] = (char *)malloc(strlen(namelist[n]->d_name) + 1); strcpy(subdirs[d], namelist[n]->d_name); d++; if(d >= MAX_SUBDIRS - 1) { cerr << "Too many subdirectories, skipping the rest!\n"; break; } } } free(namelist[n]); } free(namelist); } subdirs[d] = NULL; return subdirs;}static string findpatternfile(string protocol){ char filename[MAX_FN_LEN]; char ** subdirs; int n = 0; subdirs = readl7dir(l7dir); while(subdirs[n] != NULL){ int c = snprintf(filename, MAX_FN_LEN, "%s/%s/%s.pat", l7dir.c_str(), subdirs[n], protocol.c_str()); if(c > MAX_FN_LEN){ cerr << "Filename beginning with " << filename << " is too long!\n"; exit(1); } ifstream test(filename); /* read in the pattern from the file */ if(test.is_open()){ test.close(); string answer = filename; return answer; } n++; } cerr << "Couldn't find a pattern definition file for " << protocol << endl; exit(1);}// Loads in the configuration filel7_classify::l7_classify(string filename){ string line; int nrules = 0; int discussedbitusage = 0; ifstream conf(filename.c_str()); l7printf(2, "Attempting to read configuration from %s\n", filename.c_str()); if(!conf.is_open()){ cerr << "Could not read from " << filename << endl; exit(1); } while(getline(conf, line)){ stringstream sline; string proto, patternfile; int mk; bool nothingbutspaces = true; // Lines starting with # are comments if(line[0] == '#') continue; // blank lines are ignored for(unsigned int i = 0; i < line.size(); i++) if(!isspace(line[i])) nothingbutspaces = false; if(nothingbutspaces) continue; sline << line; if(!(sline >> proto) || !(sline >> mk)){ cerr << "Ignoring line because it isn't in the format 'protocol mark':" << line << endl; continue; } if(mk <= 1 || mk >= (markmask >> maskfirstbit) ){ cerr << "Ignoring line because the mark is not in the range 3-" << (markmask >> maskfirstbit) << ":\n" << line << endl; if(!discussedbitusage){ cerr << "Your mask allows me to use " << masknbits << " bits, and the values 0, 1 and 2 have special meanings.\n"; discussedbitusage = 1; } continue; } patternfile = findpatternfile(proto); if(add_pattern_from_file(patternfile, mk)){ nrules++; if(markmask == 0xffffffff) l7printf(0, "Added: %s\tmark=%d\n", proto.c_str(), mk); else l7printf(0, "Added: %s\tGiven mark=%d\t" "Actual mark (after applying mask)=%#08x\n", proto.c_str(), mk, (mk << maskfirstbit)); } } if(nrules < 1){ cerr << "No valid rules, exiting.\n"; exit(1); }}l7_classify::~l7_classify() {}// Returns 1 on sucess, 0 on failureint l7_classify::add_pattern_from_file(string filename, int mark) { int eflags, cflags; string pattern = ""; l7printf(2, "Attempting to load pattern from %s\n", filename.c_str()); if(!parse_pattern_file(cflags, eflags, pattern, filename)){ cerr << "Failed to parse pattern file " << filename << endl; return 0; } l7printf(2, "pattern='%s'\n", pattern.c_str()); l7printf(2, "eflags=%d cflags=%d\n", eflags, cflags); l7_pattern *l7p=new l7_pattern(basename(filename),pattern,eflags,cflags,mark); patterns.push_back(l7p); return 1;}int l7_classify::classify(char * buffer) { list<l7_pattern *>::iterator current = patterns.begin(); while (current != patterns.end()) { l7printf(3, "checking against %s\n", (*current)->getName().c_str()); if((*current)->matches(buffer)){ l7printf(1, "matched %s\n", (*current)->getName().c_str()); return (*current)->getMark(); } current++; } l7printf(3, "No match yet\n"); return NO_MATCH_YET;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -