1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/*
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
This file is synced between the userspace source code and the test suite
source code. I don't think it's worth the effort to make it a proper library.
*/
using namespace std;
#include <iostream>
#include <fstream>
#include <string>
#include "l7-parse-patterns.h"
// Returns true if the line (from a pattern file) is a comment
static int is_comment(string line)
{
// blank lines are comments
if(line.size() == 0) return 1;
// lines starting with # are comments
if(line[0] == '#') return 1;
// lines with only whitespace are comments
for(unsigned int i = 0; i < line.size(); i++)
if(!isspace(line[i]))
return 0;
return 1;
}
// Extracts the protocol name from a line
// This line should be exactly the name of the file without the .pat extension
// However, we also allow junk after whitespace
static string get_protocol_name(string line)
{
string name = "";
for(unsigned int i = 0; i < line.size(); i++)
{
if(!isspace(line[i]))
name += line[i];
else break;
}
return name;
}
// Returns the given file name from the last slash to the next dot
string basename(string filename)
{
int lastslash = filename.find_last_of('/');
int nextdot = filename.find_first_of('.', lastslash);
return filename.substr(lastslash+1, nextdot - (lastslash+1));
}
// Returns, e.g. "userspace pattern" if the line is "userspace pattern=.*foo"
static string attribute(string line)
{
return line.substr(0, line.find_first_of('='));
}
// Returns, e.g. ".*foo" if the line is "userspace pattern=.*foo"
static string value(string line)
{
return line.substr(line.find_first_of('=')+1);
}
// parse the regexec and regcomp flags
// Returns 1 on sucess, 0 if any unrecognized flags were encountered
static int parseflags(int & cflags, int & eflags, string line)
{
string flag = "";
cflags = 0;
eflags = 0;
for(unsigned int i = 0; i < line.size(); i++){
if(!isspace(line[i]))
flag += line[i];
if(isspace(line[i]) || i == line.size()-1){
if(flag == "REG_EXTENDED") cflags |= REG_EXTENDED;
else if(flag == "REG_ICASE") cflags |= REG_ICASE;
else if(flag == "REG_NOSUB") cflags |= REG_NOSUB;
else if(flag == "REG_NEWLINE") cflags |= REG_NEWLINE;
else if(flag == "REG_NOTBOL") eflags |= REG_NOTBOL;
else if(flag == "REG_NOTEOL") eflags |= REG_NOTEOL;
else{
cerr<<"Error: encountered unknown flag in pattern file " <<flag <<endl;
return 0;
}
flag = "";
}
}
return 1;
}
// Returns 1 on sucess, 0 on failure.
// Takes a filename and "returns" the pattern and flags
int parse_pattern_file(int & cflags, int & eflags, string & pattern,
string filename)
{
ifstream the_file(filename.c_str());
if(!the_file.is_open()){
cerr << "couldn't read file.\n";
return 0;
}
// What we're looking for. It's either the protocol name, the kernel pattern,
// which we'll use if no other is present, or any of various (ok, two)
// userspace config lines.
enum { protocol, kpattern, userspace } state = protocol;
string name = "", line;
cflags = REG_EXTENDED | REG_ICASE | REG_NOSUB;
eflags = 0;
while (!the_file.eof()){
getline(the_file, line);
if(is_comment(line)) continue;
if(state == protocol){
name = get_protocol_name(line);
if(name != basename(filename)){
cerr << "Error: Protocol declared in file does not match file name.\n"
<< "File name is " << basename(filename)
<< ", but the file says " << name << endl;
return 0;
}
state = kpattern;
continue;
}
if(state == kpattern){
pattern = line;
state = userspace;
continue;
}
if(state == userspace){
if(line.find_first_of('=') == string::npos){
cerr<<"Warning: ignored bad line in pattern file:\n\t"<<line<<endl;
continue;
}
if(attribute(line) == "userspace pattern"){
pattern = value(line);
}
else if(attribute(line) == "userspace flags"){
if(!parseflags(cflags, eflags, value(line)))
return 0;
}
else
cerr << "Warning: ignored unknown pattern file attribute \""
<< attribute(line) << "\"\n";
}
}
return 1;
}
|