diff --git a/src/conf.cc b/src/conf.cc
index 13bd109..e885756 100644
--- a/src/conf.cc
+++ b/src/conf.cc
@@ -15,136 +15,251 @@
// along with this program. If not, see .
#include
#include
+#include
+#include
+#include
+#include
+#include
#include
-#include
#include "ndppd.h"
NDPPD_NS_BEGIN
-void conf::error_printf(cfg_t *cfg, const char *fmt, va_list ap)
+conf::conf() :
+ _is_block(false)
{
- char buf[256];
- if (vsnprintf(buf, sizeof(buf), fmt, ap) <= 0)
- return;
-
- logger::error() << "[Config] " << buf;
}
-int conf::validate_rule(cfg_t *cfg, cfg_opt_t *opt)
+const std::string &conf::value() const
{
- struct in6_addr addr, mask;
-
- cfg_t *rule_cfg = cfg_opt_getnsec(opt, cfg_opt_size(opt) - 1);
-
- if (!rule_cfg)
- return -1;
-
- // TODO: Maybe we should validate IP here?
-
- return 0;
+ return _value;
}
-bool conf::setup(cfg_t *cfg)
+bool conf::bool_value() const
{
- int i;
+ if (!strcasecmp(_value.c_str(), "true") || !strcasecmp(_value.c_str(), "yes"))
+ return true;
+ else
+ return false;
+}
- for (i = 0; i < cfg_size(cfg, "proxy"); i++) {
- cfg_t *proxy_cfg = cfg_getnsec(cfg, "proxy", i);
+int conf::int_value() const
+{
+ return atoi(_value.c_str());
+}
- if (proxy_cfg) {
- cfg_t *rule_cfg;
- int i2;
+void conf::value(const std::string &value)
+{
+ _value = value;
+}
- std::shared_ptr pr = proxy::open(cfg_title(proxy_cfg));
+std::shared_ptr conf::load(const std::string &path)
+{
+ std::ifstream ifs;
+ ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
- if (!pr)
- continue;
+ try {
+ ifs.open(path, std::ios::in);
+ std::string buf((std::istreambuf_iterator(ifs)), std::istreambuf_iterator());
+ ifs.close();
+ const char *c_buf = buf.c_str();
- pr->router(cfg_getbool(proxy_cfg, "router"));
+ std::shared_ptr cf(new conf);
- pr->ttl(cfg_getint(proxy_cfg, "ttl"));
+ if (cf->parse_block(&c_buf)) {
+ logger l(LOG_DEBUG);
+ cf->dump(l, 0);
+ return cf;
+ }
- pr->timeout(cfg_getint(proxy_cfg, "timeout"));
+ logger::error() << "Could not parse configuration file";
+ } catch (std::ifstream::failure e) {
+ logger::error() << "Failed to load configuration file '" << path << "'";
+ }
- for (i2 = 0; i2 < cfg_size(proxy_cfg, "rule"); i2++) {
- cfg_t *rule_cfg;
+ return std::shared_ptr();
+}
- if (!(rule_cfg = cfg_getnsec(proxy_cfg, "rule", i2)))
- continue;
+bool conf::is_block() const
+{
+ return _is_block;
+}
- address addr(cfg_title(rule_cfg));
+const char *conf::skip(const char *str, bool all)
+{
+ if (!all) {
+ while (*str && (*str != '\n') && isspace(*str))
+ str++;
- std::string ifname(cfg_getstr(rule_cfg, "iface"));
+ return str;
+ }
- if (ifname.empty()) {
- if (addr.prefix() <= 120) {
- logger::warning() << "Static rule prefix /" << addr.prefix() << " <= 120 - is this what you want?";
- }
+ while (*str) {
+ while (*str && isspace(*str))
+ str++;
- pr->add_rule(addr);
- }
- else
- {
- pr->add_rule(addr, iface::open_ifd(ifname));
+ if (!*str)
+ break;
+
+ if ((*str == '#') || ((*str == '/') && (*(str + 1) == '/'))) {
+ while (*str && (*str != '\n'))
+ str++;
+ continue;
+ }
+
+ if ((*str == '/') && (*(str + 1) == '*')) {
+ while (*str) {
+ if ((*str == '*') && (*(str + 1) == '/')) {
+ str += 2;
+ break;
}
+ str++;
}
+ continue;
+ }
+
+ 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);
+
+ if (*p == '}') {
+ *str = p;
+ return true;
+ }
+
+ while (*p && isalpha(*p)) {
+ ss << *p++;
+ }
+
+ p = skip(p);
+
+ if (*p == '=') {
+ p++;
+ }
+
+ std::shared_ptr cf(new conf);
+
+ if (cf->parse(&p)) {
+ _map.insert(std::pair >(ss.str(), cf));
}
}
- return 0;
-}
-
-bool conf::load(const std::string& path)
-{
- cfg_t *cfg;
- int i, sz;
-
- #define _S (char *)
-
- static cfg_opt_t rule_opts[] =
- {
- CFG_STR (_S "iface", _S "", CFGF_NONE),
- CFG_END ()
- };
-
- static cfg_opt_t proxy_opts[] =
- {
- CFG_SEC (_S "rule", rule_opts, CFGF_MULTI | CFGF_TITLE),
- CFG_BOOL (_S "router", cfg_true, CFGF_NONE),
- CFG_INT (_S "ttl", 30000, CFGF_NONE),
- CFG_INT (_S "timeout", 500, CFGF_NONE),
- CFG_END ()
- };
-
- static cfg_opt_t opts[] =
- {
- CFG_SEC (_S "proxy", proxy_opts, CFGF_MULTI | CFGF_TITLE),
- CFG_FUNC (_S "include", &cfg_include),
- CFG_END()
- };
-
- cfg = cfg_init(opts, CFGF_NOCASE);
-
- cfg_set_error_function(cfg, &error_printf);
-
- cfg_set_validate_func(cfg, "proxy|rule", &validate_rule);
-
- switch (cfg_parse(cfg, path.c_str())) {
- case CFG_SUCCESS:
- break;
-
- default:
- logger::error() << "Failed to load configuration file '" << path << "'";
- return false;
- }
-
- setup(cfg);
-
- cfg_free(cfg);
-
+ *str = p;
return true;
}
+bool conf::parse(const char **str)
+{
+ const char *p = *str;
+ std::stringstream ss;
+
+ p = skip(p, false);
+
+ if (!*p) {
+ return false;
+ } else if ((*p == '\'') || (*p == '"')) {
+ for (char e = *p++; *p && (*p != e); p++)
+ ss << *p;
+ } else if (isalnum(*p)) {
+ while (*p && (isalnum(*p) || strchr(":/.", *p)))
+ ss << *p++;
+ } else {
+ return false;
+ }
+
+ _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() const
+{
+ logger l(LOG_ERR);
+ dump(l, 0);
+}
+
+void conf::dump(logger &l, int level) const
+{
+ int i;
+
+ std::string pfx;
+ for (int i = 0; i < level; i++) {
+ pfx += " ";
+ }
+
+ if (_value != "") {
+ l << _value << " ";
+ }
+
+ if (_is_block) {
+ l << "{" << logger::endl;
+
+ std::multimap >::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;
+}
+
+std::shared_ptr conf::operator[](const std::string& name) const
+{
+ std::multimap >::const_iterator it;
+
+ if ((it = _map.find(name)) == _map.end())
+ return std::shared_ptr();
+ else
+ return it->second;
+}
+
+std::vector > conf::find(const std::string& name) const
+{
+ std::vector > vec;
+ std::multimap >::const_iterator it;
+ for (it = _map.find(name); it != _map.end(); it++) {
+ vec.push_back(it->second);
+ }
+ return vec;
+}
+
+conf::operator const std::string&()
+{
+ return _value;
+}
+
NDPPD_NS_END
diff --git a/src/conf.h b/src/conf.h
index bda8c8e..9b72ab3 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -16,23 +16,56 @@
#pragma once
#include
+#include