2  *    This program is free software; you can redistribute it and/or modify
 
   3  *    it under the terms of the GNU General Public License as published by
 
   4  *    the Free Software Foundation; either version 2 of the License, or
 
   5  *    (at your option) any later version.
 
   7  *    This program is distributed in the hope that it will be useful,
 
   8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  10  *    GNU General Public License for more details.
 
  12  *    You should have received a copy of the GNU General Public License
 
  13  *    along with this program; if not, write to the Free Software
 
  14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
  18  *    Author : Maxim Mamontov <faust@stargazer.dp.ua>
 
  23  $Date: 2009/02/24 08:13:03 $
 
  34 #include <arpa/inet.h>
 
  42 STG::RULES_PARSER::RULES_PARSER()
 
  48 error = InitProtocols();
 
  51 STG::RULES_PARSER::RULES_PARSER(const string & fileName)
 
  57 error = InitProtocols();
 
  61 void STG::RULES_PARSER::SetFile(const string & fileName)
 
  65 ifstream rulesFile(fileName.c_str());
 
  72     errorStream << "RULES_PARSER::SetFile - Error opening file '" << fileName << "'\n";
 
  78 rules.erase(rules.begin(), rules.end());
 
  80 while (getline(rulesFile, line))
 
  86         errorStream << "RULES_PARSER::SetFile - Error parsing line at '" << fileName << ":" << lineNumber << "'\n";
 
  93 // Adding lastest rule: ALL 0.0.0.0/0 NULL
 
  95 rule.ip = 0;  //0.0.0.0
 
 101 rules.push_back(rule);
 
 108 bool STG::RULES_PARSER::ParseLine(string line)
 
 112 pos = line.find('#');
 
 113 if (pos != string::npos)
 
 115     line = line.substr(0, pos);
 
 123 size_t lpos = line.find_first_not_of("\t ", 0, 2);
 
 125 if (lpos == string::npos)
 
 130 size_t rpos = line.find_first_of("\t ", lpos, 2);
 
 132 if (rpos == string::npos)
 
 137 string proto(line.begin() + lpos, line.begin() + rpos);
 
 139 lpos = line.find_first_not_of("\t ", rpos, 2);
 
 141 if (lpos == string::npos)
 
 146 rpos = line.find_first_of("\t ", lpos, 2);
 
 148 if (rpos == string::npos)
 
 153 string address(line.begin() + lpos, line.begin() + rpos);
 
 155 lpos = line.find_first_not_of("\t ", rpos, 2);
 
 157 if (lpos == string::npos)
 
 161 string direction(line.begin() + lpos, line.end());
 
 170 map<string, int>::const_iterator it(protocols.find(proto));
 
 172 if (it == protocols.end())
 
 174     errorStream << "RULES_PARSER::ParseLine - Invalid protocol\n";
 
 180 rule.proto = it->second;
 
 182 if (direction.length() < 4)
 
 184     errorStream << "RULES_PARSER::ParseLine - Invalid direction\n";
 
 188 if (direction == "NULL")
 
 194     string prefix(direction.begin(), direction.begin() + 3);
 
 195     direction = direction.substr(3, direction.length() - 3);
 
 198         errorStream << "RULES_PARSER::ParseLine - Invalid direction prefix\n";
 
 203      * 'cause strtol don't change errno on success
 
 204      * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
 
 207     rule.dir = strtol(direction.c_str(), &endptr, 10);
 
 209     // Code from strtol(3) release 3.10
 
 210     if ((errno == ERANGE && (rule.dir == numeric_limits<int>::max() ||
 
 211                              rule.dir == numeric_limits<int>::min()))
 
 212         || (errno != 0 && rule.dir == 0))
 
 214             errorStream << "RULES_PARSER::ParseLine - Direction out of range\n";
 
 217     if (endptr == direction.c_str())
 
 219             errorStream << "RULES_PARSER::ParseLine - Invalid direction\n";
 
 224 if (ParseAddress(address, &rule))
 
 226     errorStream << "RULES_PARSER::ParseLine - Invalid address\n";
 
 230 rules.push_back(rule);
 
 235 bool STG::RULES_PARSER::ParseAddress(const string & address, RULE * rule) const
 
 237 // Format: <address>[/<mask>[:<port1>[-<port2>]]]
 
 238 size_t pos = address.find('/');
 
 243 if (pos != string::npos)
 
 245     ip = address.substr(0, pos);
 
 246     mask = address.substr(pos + 1, address.length() - pos - 1);
 
 247     pos = mask.find(':');
 
 248     if (pos != string::npos)
 
 250         ports = mask.substr(pos + 1, mask.length() - pos - 1);
 
 251         mask = mask.substr(0, pos);
 
 261     pos = address.find(':');
 
 262     if (pos != string::npos)
 
 264         ip = address.substr(0, pos);
 
 265         ports = address.substr(pos + 1, address.length() - pos - 1);
 
 274 struct in_addr ipaddr;
 
 276 if (!inet_aton(ip.c_str(), &ipaddr))
 
 278     errorStream << "RULES_PARSER::ParseAddress - Invalid IP\n";
 
 282 rule->ip = ntohl(ipaddr.s_addr);
 
 284 if (ParseMask(mask, rule))
 
 286     errorStream << "RULES_PARSER::ParseAddress - Error parsing mask\n";
 
 290 pos = ports.find('-');
 
 294 if (pos != string::npos)
 
 296     port1 = ports.substr(0, pos);
 
 297     port2 = ports.substr(pos + 1, ports.length() - pos - 1);
 
 301     port1 = port2 = ports;
 
 304 if (ParsePorts(port1, port2, rule))
 
 306     errorStream << "RULES_PARSER::ParseAddress - Error pasing ports\n";
 
 313 bool STG::RULES_PARSER::ParseMask(const string & mask, RULE * rule) const
 
 319  * 'cause strtol don't change errno on success
 
 320  * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
 
 322 rule->mask = strtol(mask.c_str(), &endptr, 10);
 
 324 if ((errno == ERANGE && (rule->mask == numeric_limits<uint32_t>::max() ||
 
 325                          rule->mask == numeric_limits<uint32_t>::min()))
 
 326     || (errno != 0 && rule->mask == 0))
 
 328     errorStream << "RULES_PARSER::ParseMask - Mask is out of range\n";
 
 334     errorStream << "RULES_PARSER::ParseMask - NULL endptr\n";
 
 340     errorStream << "RULES_PARSER::ParseMask - Invalid mask\n";
 
 346     errorStream << "RULES_PARSER::ParseMask - Mask is greater than 32\n";
 
 350 rule->mask = 0xffFFffFF >> (32 - rule->mask);
 
 355 bool STG::RULES_PARSER::ParsePorts(const string & port1,
 
 356                               const string & port2,
 
 363  * 'cause strtol don't change errno on success
 
 364  * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
 
 366 rule->port1 = strtol(port1.c_str(), &endptr, 10);
 
 368 if ((errno == ERANGE && (rule->port1 == numeric_limits<uint16_t>::max() ||
 
 369                          rule->port1 == numeric_limits<uint16_t>::min()))
 
 370     || (errno != 0 && rule->port1 == 0))
 
 372     errorStream << "RULES_PARSER::ParsePorts - Min port is out of range\n";
 
 378     errorStream << "RULES_PARSER::ParsePorts - NULL endptr on min port\n";
 
 384     errorStream << "RULES_PARSER::ParsePorts - Invalid min port\n";
 
 390  * 'cause strtol don't change errno on success
 
 391  * according to: http://www.opengroup.org/onlinepubs/000095399/functions/strtol.html
 
 393 rule->port2 = strtol(port2.c_str(), &endptr, 10);
 
 395 if ((errno == ERANGE && (rule->port2 == numeric_limits<uint16_t>::max() ||
 
 396                          rule->port2 == numeric_limits<uint16_t>::min()))
 
 397     || (errno != 0 && rule->port2 == 0))
 
 399         errorStream << "RULES_PARSER::ParseAddress - Max port is out of range\n";
 
 405     errorStream << "RULES_PARSER::ParsePorts - NULL endptr on max port\n";
 
 411     errorStream << "RULES_PARSER::ParsePorts - Invalid max port\n";
 
 418 bool STG::RULES_PARSER::InitProtocols()
 
 420 struct protoent * pe;
 
 424 protocols.erase(protocols.begin(), protocols.end());
 
 426 setprotoent(true); // Open link to /etc/protocols
 
 428 while ((pe = getprotoent()) != NULL)
 
 430     string proto(pe->p_name);
 
 431     protocols.insert(make_pair(STG::ToUpper(pe->p_name, loc), pe->p_proto));
 
 436 protocols["ALL"] = -1;
 
 437 protocols["TCP_UDP"] = -2;
 
 441 return protocols.empty();