Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Daniel Adolfsson <daniel@priv.nu>
289 lines
5.8 KiB
C++
289 lines
5.8 KiB
C++
// ndppd - NDP Proxy Daemon
|
|
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
|
|
//
|
|
// 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 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#include <cstdio>
|
|
#include <cstdarg>
|
|
#include <cstring>
|
|
#include <cctype>
|
|
#include <cstdlib>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <netinet/ip6.h>
|
|
|
|
#include "ndppd.h"
|
|
|
|
NDPPD_NS_BEGIN
|
|
|
|
conf::conf() :
|
|
_is_block(false)
|
|
{
|
|
|
|
}
|
|
|
|
conf::operator int() const
|
|
{
|
|
return as_int();
|
|
}
|
|
|
|
conf::operator const std::string&() const
|
|
{
|
|
return as_str();
|
|
}
|
|
|
|
conf::operator bool() const
|
|
{
|
|
return as_bool();
|
|
}
|
|
|
|
bool conf::as_bool() const
|
|
{
|
|
if (!strcasecmp(_value.c_str(), "true") || !strcasecmp(_value.c_str(), "yes"))
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
const std::string& conf::as_str() const
|
|
{
|
|
return _value;
|
|
}
|
|
|
|
int conf::as_int() const
|
|
{
|
|
return atoi(_value.c_str());
|
|
}
|
|
|
|
bool conf::empty() const
|
|
{
|
|
return _value == "";
|
|
}
|
|
|
|
ptr<conf> conf::load(const std::string& path)
|
|
{
|
|
try {
|
|
std::ifstream ifs;
|
|
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
ifs.open(path.c_str(), std::ios::in);
|
|
ifs.exceptions(std::ifstream::badbit);
|
|
std::string buf((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
|
|
|
const char* c_buf = buf.c_str();
|
|
|
|
ptr<conf> cf(new conf);
|
|
|
|
if (cf->parse_block(&c_buf)) {
|
|
cf->dump(LOG_DEBUG);
|
|
return cf;
|
|
}
|
|
|
|
logger::error() << "Could not parse configuration file";
|
|
} catch (std::ifstream::failure e) {
|
|
logger::error() << "Failed to load configuration file '" << path << "'";
|
|
}
|
|
|
|
return ptr<conf>();
|
|
}
|
|
|
|
bool conf::is_block() const
|
|
{
|
|
return _is_block;
|
|
}
|
|
|
|
const char* conf::skip(const char* str, bool newlines)
|
|
{
|
|
while (*str) {
|
|
while (*str && isspace(*str) && ((*str != '\n') || newlines))
|
|
str++;
|
|
|
|
if ((*str == '#') || ((*str == '/') && (*(str + 1) == '/'))) {
|
|
while (*str && (*str != '\n')) {
|
|
str++;
|
|
}
|
|
} else if ((*str == '/') && (*(str + 1) == '*')) {
|
|
while (*str) {
|
|
if ((*str == '*') && (*(str + 1) == '/')) {
|
|
str += 2;
|
|
break;
|
|
}
|
|
str++;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
bool conf::parse_block(const char** str)
|
|
{
|
|
const char* p = *str;
|
|
|
|
_is_block = true;
|
|
|
|
while (*p) {
|
|
std::stringstream ss;
|
|
|
|
p = skip(p, true);
|
|
|
|
if ((*p == '}') || !*p) {
|
|
*str = p;
|
|
return true;
|
|
}
|
|
|
|
while (isalnum(*p) || (*p == '_') || (*p == '-')) {
|
|
ss << *p++;
|
|
}
|
|
|
|
p = skip(p, false);
|
|
|
|
if (*p == '=') {
|
|
p++;
|
|
p = skip(p, false);
|
|
}
|
|
|
|
ptr<conf> cf(new conf);
|
|
|
|
if (cf->parse(&p)) {
|
|
_map.insert(std::pair<std::string, ptr<conf> >(ss.str(), cf));
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
*str = p;
|
|
return true;
|
|
}
|
|
|
|
bool conf::parse(const char** str)
|
|
{
|
|
const char* p = *str;
|
|
std::stringstream ss;
|
|
|
|
p = skip(p, false);
|
|
|
|
if ((*p == '\'') || (*p == '"')) {
|
|
for (char e = *p++; *p && (*p != e) && (*p != '\n'); p++)
|
|
ss << *p;
|
|
p = skip(p, false);
|
|
} else {
|
|
while (*p && isgraph(*p) && (*p != '{') && (*p != '}')) {
|
|
ss << *p++;
|
|
}
|
|
}
|
|
|
|
_value = ss.str();
|
|
|
|
p = skip(p, false);
|
|
|
|
if (*p == '{') {
|
|
p++;
|
|
|
|
if (!parse_block(&p)) {
|
|
return false;
|
|
}
|
|
|
|
if (*p != '}') {
|
|
return false;
|
|
}
|
|
|
|
p++;
|
|
}
|
|
|
|
*str = p;
|
|
return true;
|
|
}
|
|
|
|
void conf::dump(int pri) const
|
|
{
|
|
logger l(pri);
|
|
dump(l, 0);
|
|
}
|
|
|
|
void conf::dump(logger& l, int level) const
|
|
{
|
|
std::string pfx;
|
|
for (int i = 0; i < level; i++) {
|
|
pfx += " ";
|
|
}
|
|
|
|
if (_value != "") {
|
|
l << _value << " ";
|
|
}
|
|
|
|
if (_is_block) {
|
|
l << "{" << logger::endl;
|
|
|
|
std::multimap<std::string, ptr<conf> >::const_iterator it;
|
|
|
|
for (it = _map.begin(); it != _map.end(); it++) {
|
|
l << pfx << " " << it->first << " ";
|
|
it->second->dump(l, level + 1);
|
|
}
|
|
|
|
l << pfx << "}" << logger::endl;
|
|
}
|
|
|
|
l << logger::endl;
|
|
}
|
|
|
|
ptr<conf> conf::operator()(const std::string& name, int index) const
|
|
{
|
|
return find(name, index);
|
|
}
|
|
|
|
ptr<conf> conf::find(const std::string& name, int index) const
|
|
{
|
|
std::multimap<std::string, ptr<conf> >::const_iterator it;
|
|
for (it = _map.find(name); it != _map.end(); it++) {
|
|
if (index-- <= 0)
|
|
return it->second;
|
|
}
|
|
|
|
return ptr<conf>();
|
|
}
|
|
|
|
ptr<conf> conf::operator[](const std::string& name) const
|
|
{
|
|
return find(name, 0);
|
|
}
|
|
|
|
std::vector<ptr<conf> > conf::find_all(const std::string& name) const
|
|
{
|
|
std::vector<ptr<conf> > vec;
|
|
|
|
std::multimap<std::string, ptr<conf> >::const_iterator it;
|
|
|
|
std::pair<std::multimap<std::string, ptr<conf> >::const_iterator,
|
|
std::multimap<std::string, ptr<conf> >::const_iterator> ret;
|
|
|
|
ret = _map.equal_range(name);
|
|
|
|
for (it = ret.first; it != ret.second; it++) {
|
|
vec.push_back(it->second);
|
|
}
|
|
|
|
return vec;
|
|
}
|
|
|
|
conf::operator const std::string&()
|
|
{
|
|
return _value;
|
|
}
|
|
|
|
NDPPD_NS_END
|