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();