Several large changes for the upcoming 0.2.2 version

- Bugfixes.

- New 'auto' configuration to be used in a 'rule' section.  When using
  this option, the routing table /proc/net/ipv6_route will be used to
  auto-detect which interface to use when forwarding solicitation messages.

- New 'route' class to resolve which interface to query when using
  'auto' configuration.

- Cleaned up the code some more.
This commit is contained in:
Daniel Adolfsson 2012-02-03 14:29:37 +01:00
parent ab0ebe09ff
commit 6723f2f4b6
19 changed files with 787 additions and 243 deletions

View File

@ -15,7 +15,7 @@ SBINDIR ?= ${DESTDIR}${PREFIX}/sbin
LIBS = LIBS =
OBJS = src/logger.o src/ndppd.o src/iface.o src/proxy.o src/address.o \ OBJS = src/logger.o src/ndppd.o src/iface.o src/proxy.o src/address.o \
src/rule.o src/session.o src/conf.o src/rule.o src/session.o src/conf.o src/route.o
all: ndppd ndppd.1.gz ndppd.conf.5.gz all: ndppd ndppd.1.gz ndppd.conf.5.gz

View File

@ -125,34 +125,54 @@ void address::reset()
int address::prefix() const int address::prefix() const
{ {
if (!_mask.s6_addr[0]) if (!_mask.s6_addr[0]) {
return 0; return 0;
}
for (int p = 0; p < 128; p++) { for (int p = 0; p < 128; p++) {
int byi = p / 8, bii = 7 - (p % 8); int byi = p / 8, bii = 7 - (p % 8);
if (!(_mask.s6_addr[byi] & (1 << bii)))
if (!(_mask.s6_addr[byi]& (1 << bii))) {
return p; return p;
} }
}
return 128; return 128;
} }
void address::prefix(int pf) void address::prefix(int pf)
{ {
if ((pf < 0) || (pf > 128)) const unsigned char maskbit[] = {
return; 0x00, 0x80, 0xc0, 0xe0, 0xf0,
0xf8, 0xfc, 0xfe, 0xff
};
if (pf >= 128) {
_mask.s6_addr32[0] = 0xffffffff;
_mask.s6_addr32[1] = 0xffffffff;
_mask.s6_addr32[2] = 0xffffffff;
_mask.s6_addr32[3] = 0xffffffff;
return;
} else {
_mask.s6_addr32[0] = 0; _mask.s6_addr32[0] = 0;
_mask.s6_addr32[1] = 0; _mask.s6_addr32[1] = 0;
_mask.s6_addr32[2] = 0; _mask.s6_addr32[2] = 0;
_mask.s6_addr32[3] = 0; _mask.s6_addr32[3] = 0;
while (pf--) { if (pf <= 0) {
int byi = pf / 8, bii = 7 - (pf % 8); return;
_mask.s6_addr[byi] |= 1 << bii;
} }
} }
int offset = pf / 8, n;
for (n = 0; n < offset; n++) {
_mask.s6_addr[n] = 0xff;
}
_mask.s6_addr[offset] = maskbit[pf % 8];
}
const std::string address::to_string() const const std::string address::to_string() const
{ {
char buf[INET6_ADDRSTRLEN + 8]; char buf[INET6_ADDRSTRLEN + 8];
@ -164,8 +184,9 @@ const std::string address::to_string() const
int p; int p;
if ((p = prefix()) < 128) if ((p = prefix()) < 128) {
sprintf(buf + strlen(buf), "/%d", p); sprintf(buf + strlen(buf), "/%d", p);
}
return buf; return buf;
} }
@ -186,14 +207,17 @@ bool address::parse_string(const std::string& str)
p++; p++;
while (*p) { while (*p) {
if ((*p == '/') || isspace(*p)) if ((*p == '/') || isspace(*p)) {
break; break;
}
if ((*p != ':') && !isxdigit(*p)) if ((*p != ':') && !isxdigit(*p)) {
return false; return false;
}
if (sz >= (INET6_ADDRSTRLEN - 1)) if (sz >= (INET6_ADDRSTRLEN - 1)) {
return false; return false;
}
* b++ =* p++; * b++ =* p++;
@ -202,11 +226,13 @@ bool address::parse_string(const std::string& str)
* b = '\0'; * b = '\0';
if (inet_pton(AF_INET6, buf, &_addr) <= 0) if (inet_pton(AF_INET6, buf,& _addr) <= 0) {
return false; return false;
}
while (*p && isspace(*p)) while (*p && isspace(*p)) {
p++; p++;
}
if (*p == '\0') { if (*p == '\0') {
_mask.s6_addr32[0] = 0xffffffff; _mask.s6_addr32[0] = 0xffffffff;

View File

@ -24,11 +24,7 @@ NDPPD_NS_BEGIN
class iface; class iface;
class address class address {
{
private:
struct in6_addr _addr, _mask;
public: public:
address(); address();
address(const address& addr); address(const address& addr);
@ -65,6 +61,8 @@ public:
operator std::string() const; operator std::string() const;
private:
struct in6_addr _addr, _mask;
}; };
NDPPD_NS_END NDPPD_NS_END

View File

@ -34,12 +34,22 @@ conf::conf() :
} }
const std::string &conf::value() const conf::operator int() const
{ {
return _value; return as_int();
} }
bool conf::bool_value() const 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")) if (!strcasecmp(_value.c_str(), "true") || !strcasecmp(_value.c_str(), "yes"))
return true; return true;
@ -47,14 +57,19 @@ bool conf::bool_value() const
return false; return false;
} }
int conf::int_value() const const std::string& conf::as_str() const
{
return _value;
}
int conf::as_int() const
{ {
return atoi(_value.c_str()); return atoi(_value.c_str());
} }
void conf::value(const std::string &value) bool conf::empty() const
{ {
_value = value; return _value == "";
} }
ptr<conf> conf::load(const std::string& path) ptr<conf> conf::load(const std::string& path)
@ -63,6 +78,7 @@ ptr<conf> conf::load(const std::string &path)
std::ifstream ifs; std::ifstream ifs;
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
ifs.open(path.c_str(), std::ios::in); 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>()); std::string buf((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
const char* c_buf = buf.c_str(); const char* c_buf = buf.c_str();
@ -70,8 +86,7 @@ ptr<conf> conf::load(const std::string &path)
ptr<conf> cf(new conf); ptr<conf> cf(new conf);
if (cf->parse_block(&c_buf)) { if (cf->parse_block(&c_buf)) {
logger l(LOG_DEBUG); cf->dump(LOG_DEBUG);
cf->dump(l, 0);
return cf; return cf;
} }
@ -136,9 +151,9 @@ bool conf::parse_block(const char **str)
while (*p) { while (*p) {
std::stringstream ss; std::stringstream ss;
p = skip(p); p = skip(p, true);
if (*p == '}') { if ((*p == '}') || !*p) {
*str = p; *str = p;
return true; return true;
} }
@ -180,7 +195,9 @@ bool conf::parse(const char **str)
while (*p && (isalnum(*p) || strchr(":/.",* p))) while (*p && (isalnum(*p) || strchr(":/.",* p)))
ss <<* p++; ss <<* p++;
} else { } else {
return false; _value = "";
*str = p;
return true;
} }
_value = ss.str(); _value = ss.str();
@ -203,9 +220,9 @@ bool conf::parse(const char **str)
return true; return true;
} }
void conf::dump() const void conf::dump(int pri) const
{ {
logger l(LOG_ERR); logger l(pri);
dump(l, 0); dump(l, 0);
} }
@ -238,23 +255,42 @@ void conf::dump(logger &l, int level) const
l << logger::endl; l << logger::endl;
} }
ptr<conf> conf::operator[](const std::string& name) const 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; std::multimap<std::string, ptr<conf> >::const_iterator it;
for (it = _map.find(name); it != _map.end(); it++) {
if ((it = _map.find(name)) == _map.end()) if (index-- <= 0)
return ptr<conf>();
else
return it->second; return it->second;
} }
std::vector<ptr<conf> > conf::find(const std::string& name) const 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::vector<ptr<conf> > vec;
std::multimap<std::string, ptr<conf> >::const_iterator it; std::multimap<std::string, ptr<conf> >::const_iterator it;
for (it = _map.find(name); it != _map.end(); 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); vec.push_back(it->second);
} }
return vec; return vec;
} }

View File

@ -25,8 +25,7 @@
NDPPD_NS_BEGIN NDPPD_NS_BEGIN
class conf class conf {
{
public: public:
private: private:
@ -47,22 +46,28 @@ private:
public: public:
conf(); conf();
const std::string &value() const;
bool bool_value() const;
int int_value() const;
void value(const std::string &value);
static ptr<conf> load(const std::string& path); static ptr<conf> load(const std::string& path);
bool is_block() const; bool is_block() const;
ptr<conf> operator[](const std::string& name) const; ptr<conf> operator[](const std::string& name) const;
std::vector<ptr<conf> > find(const std::string &name) const; ptr<conf> operator()(const std::string& name, int index = 0) const;
void dump() const; operator const std::string&() const;
operator int() const;
operator bool() const;
bool as_bool() const;
const std::string& as_str() const;
int as_int() const;
bool empty() const;
std::vector<ptr<conf> > find_all(const std::string& name) const;
ptr<conf> find(const std::string& name, int index = 0) const;
void dump(int pri = LOG_INFO) const;
operator const std::string&(); operator const std::string&();

View File

@ -506,13 +506,15 @@ int iface::poll_all()
f_it != _pollfds.end(); f_it++) { f_it != _pollfds.end(); f_it++) {
assert(i_it != _map.end()); assert(i_it != _map.end());
if (i && !(i % 2)) if (i && !(i % 2)) {
i_it++; i_it++;
}
bool is_pfd = i++ % 2; bool is_pfd = i++ % 2;
if (!(f_it->revents & POLLIN)) if (!(f_it->revents& POLLIN)) {
continue; continue;
}
ptr<iface> ifa = i_it->second; ptr<iface> ifa = i_it->second;
@ -524,8 +526,9 @@ int iface::poll_all()
continue; continue;
} }
if (!saddr.is_unicast() || !daddr.is_multicast()) if (!saddr.is_unicast() || !daddr.is_multicast()) {
continue; continue;
}
ifa->_pr->handle_solicit(saddr, daddr, taddr); ifa->_pr->handle_solicit(saddr, daddr, taddr);
} else { } else {
@ -537,6 +540,7 @@ int iface::poll_all()
for (std::list<weak_ptr<session> >::iterator s_it = ifa->_sessions.begin(); for (std::list<weak_ptr<session> >::iterator s_it = ifa->_sessions.begin();
s_it != ifa->_sessions.end(); s_it++) { s_it != ifa->_sessions.end(); s_it++) {
const ptr<session> sess =* s_it; const ptr<session> sess =* s_it;
if ((sess->taddr() == taddr) && (sess->status() == session::WAITING)) { if ((sess->taddr() == taddr) && (sess->status() == session::WAITING)) {
sess->handle_advert(); sess->handle_advert();
break; break;

View File

@ -30,8 +30,7 @@ NDPPD_NS_BEGIN
class session; class session;
class proxy; class proxy;
class iface class iface {
{
private: private:
// Weak pointer so this object can reference itself. // Weak pointer so this object can reference itself.
weak_ptr<iface> _ptr; weak_ptr<iface> _ptr;

View File

@ -30,18 +30,9 @@
# define LOG_DEBUG 7 /* debug-level messages */ # define LOG_DEBUG 7 /* debug-level messages */
#endif #endif
/*#define DBG(...) logger(logger::DEBUG) << logger::F(__VA_ARGS__) << logger::endl;
#define ERR(...) logger(logger::ERROR) << logger::F(__VA_ARGS__) << logger::endl;
#define WRN(...) logger(logger::WARNING) << logger::F(__VA_ARGS__) << logger::endl;
#define NFO(...) logger(logger::INFO) << logger::F(__VA_ARGS__) << logger::endl;*/
/* LOG_ERR; LOG_WARNING; LOG_CRIT; LOG_INFO; LOG_NOTICE */
NDPPD_NS_BEGIN NDPPD_NS_BEGIN
class logger class logger {
{
public: public:
logger(int pri = LOG_INFO); logger(int pri = LOG_INFO);

View File

@ -27,6 +27,7 @@
#include <unistd.h> #include <unistd.h>
#include "ndppd.h" #include "ndppd.h"
#include "route.h"
using namespace ndppd; using namespace ndppd;
@ -61,61 +62,65 @@ bool configure(const std::string &path)
std::vector<ptr<conf> >::const_iterator p_it; std::vector<ptr<conf> >::const_iterator p_it;
std::vector<ptr<conf> > proxies(cf->find("proxy")); std::vector<ptr<conf> > proxies(cf->find_all("proxy"));
for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) { for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) {
ptr<conf> pr_cf =* p_it, x_cf; ptr<conf> pr_cf =* p_it, x_cf;
if (pr_cf->value() == "") { if (pr_cf->empty()) {
logger::error() << "'proxy' section is missing interface name"; logger::error() << "'proxy' section is missing interface name";
return false; return false;
} }
ptr<proxy> pr = proxy::open(pr_cf->value()); ptr<proxy> pr = proxy::open(*pr_cf);
if (!pr) { if (!pr) {
logger::error() << "Configuration failed for proxy '" << pr_cf->value() << "'"; logger::error() << "Configuration failed for proxy '" << (const std::string& )*pr_cf << "'";
return false; return false;
} }
if (!(x_cf = (*pr_cf)["router"])) if (!(x_cf = pr_cf->find("router")))
pr->router(true); pr->router(true);
else else
pr->router(x_cf->bool_value()); pr->router(*x_cf);
if (!(x_cf = (*pr_cf)["ttl"])) if (!(x_cf = pr_cf->find("ttl")))
pr->ttl(30000); pr->ttl(30000);
else else
pr->ttl(x_cf->int_value()); pr->ttl(*x_cf);
if (!(x_cf = (*pr_cf)["timeout"])) if (!(x_cf = pr_cf->find("timeout")))
pr->timeout(500); pr->timeout(500);
else else
pr->timeout(x_cf->int_value()); pr->timeout(*x_cf);
std::vector<ptr<conf> >::const_iterator r_it; std::vector<ptr<conf> >::const_iterator r_it;
std::vector<ptr<conf> > rules(pr_cf->find("rule")); std::vector<ptr<conf> > rules(pr_cf->find_all("rule"));
for (r_it = rules.begin(); r_it != rules.end(); r_it++) { for (r_it = rules.begin(); r_it != rules.end(); r_it++) {
ptr<conf> ru_cf =* r_it; ptr<conf> ru_cf =* r_it;
if (ru_cf->value() == "") { if (ru_cf->empty()) {
logger::error() << "'rule' is missing an IPv6 address/net"; logger::error() << "'rule' is missing an IPv6 address/net";
return false; return false;
} }
address addr(ru_cf->value()); address addr(*ru_cf);
if (!(x_cf = (*ru_cf)["iface"])) { if (x_cf = ru_cf->find("iface")) {
if ((const std::string& )*x_cf == "") {
logger::error() << "'iface' expected an interface name";
} else {
pr->add_rule(addr, iface::open_ifd(*x_cf));
}
} else if (ru_cf->find("auto")) {
pr->add_rule(addr, true);
} else {
if (addr.prefix() <= 120) { if (addr.prefix() <= 120) {
logger::warning() << "Static rule prefix /" << addr.prefix() << " <= 120 - is this what you want?"; logger::warning() << "Static rule prefix /" << addr.prefix() << " <= 120 - is this what you want?";
pr->add_rule(addr);
} }
} else if (x_cf->value() == "") { pr->add_rule(addr, false);
logger::error() << "'iface' expected an interface name or 'auto' as argument";
} else {
pr->add_rule(addr, iface::open_ifd(x_cf->value()));
} }
} }
} }
@ -195,6 +200,8 @@ int main(int argc, char *argv[], char *env[])
if (!configure(config_path)) if (!configure(config_path))
return -1; return -1;
route::load("/proc/net/ipv6_route");
// Time stuff. // Time stuff.
struct timeval t1, t2; struct timeval t1, t2;

View File

@ -20,6 +20,7 @@
#include "ndppd.h" #include "ndppd.h"
#include "proxy.h" #include "proxy.h"
#include "route.h"
#include "iface.h" #include "iface.h"
#include "rule.h" #include "rule.h"
#include "session.h" #include "session.h"
@ -48,8 +49,9 @@ ptr<proxy> proxy::open(const std::string& ifname)
{ {
ptr<iface> ifa = iface::open_pfd(ifname); ptr<iface> ifa = iface::open_pfd(ifname);
if (!ifa) if (!ifa) {
return ptr<proxy>(); return ptr<proxy>();
}
return create(ifa); return create(ifa);
} }
@ -57,7 +59,8 @@ ptr<proxy> proxy::open(const std::string& ifname)
void proxy::handle_solicit(const address& saddr, const address& daddr, void proxy::handle_solicit(const address& saddr, const address& daddr,
const address& taddr) const address& taddr)
{ {
logger::debug() << "proxy::handle_solicit() saddr=" << saddr.to_string() logger::debug()
<< "proxy::handle_solicit() saddr=" << saddr.to_string()
<< ", taddr=" << taddr.to_string(); << ", taddr=" << taddr.to_string();
// Let's check this proxy's list of sessions to see if we can // Let's check this proxy's list of sessions to see if we can
@ -89,23 +92,30 @@ void proxy::handle_solicit(const address& saddr, const address& daddr,
it != _rules.end(); it++) { it != _rules.end(); it++) {
ptr<rule> ru =* it; ptr<rule> ru =* it;
logger::debug() << "checking " << ru->addr().to_string() << " against " << taddr; logger::debug() << "checking " << ru->addr() << " against " << taddr;
if (ru->addr() == taddr) { if (ru->addr() == taddr) {
if (!se) if (!se) {
se = session::create(_ptr, saddr, daddr, taddr); se = session::create(_ptr, saddr, daddr, taddr);
if (!ru->ifa()) {
// This rule doesn't have an interface, and thus we'll consider
// it "static" and immediately send the response.
se->handle_advert();
return;
} }
if (ru->is_auto()) {
ptr<iface> ifa = route::find_and_open(taddr);
// TODO: Check if it's a good interface.
if (ifa) {
se->add_iface(ifa);
continue;
}
} else if (!ru->ifa()) {
// This rule doesn't have an interface, and thus we'll consider
// it "static" and immediately send the response.
se->handle_advert();
return;
} else {
se->add_iface((*it)->ifa()); se->add_iface((*it)->ifa());
} }
} }
}
if (se) { if (se) {
_sessions.push_back(se); _sessions.push_back(se);
@ -120,9 +130,9 @@ ptr<rule> proxy::add_rule(const address& addr, const ptr<iface>& ifa)
return ru; return ru;
} }
ptr<rule> proxy::add_rule(const address& addr) ptr<rule> proxy::add_rule(const address& addr, bool aut)
{ {
ptr<rule> ru(rule::create(_ptr, addr)); ptr<rule> ru(rule::create(_ptr, addr, aut));
_rules.push_back(ru); _rules.push_back(ru);
return ru; return ru;
} }

View File

@ -28,8 +28,7 @@ NDPPD_NS_BEGIN
class iface; class iface;
class rule; class rule;
class proxy class proxy {
{
private: private:
weak_ptr<proxy> _ptr; weak_ptr<proxy> _ptr;
@ -57,7 +56,7 @@ public:
ptr<rule> add_rule(const address& addr, const ptr<iface>& ifa); ptr<rule> add_rule(const address& addr, const ptr<iface>& ifa);
ptr<rule> add_rule(const address& addr); ptr<rule> add_rule(const address& addr, bool aut = false);
const ptr<iface>& ifa() const; const ptr<iface>& ifa() const;

244
src/ptr.h Normal file
View File

@ -0,0 +1,244 @@
// 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/>.
#pragma once
#include <exception>
#include "ndppd.h"
NDPPD_NS_BEGIN
class invalid_pointer : public std::exception {
public:
invalid_pointer() throw() {};
};
template <class T>
class weak_ptr;
// This template class simplifies the usage of pointers. It's basically
// a reference-counting smart pointer that supports both weak and
// strong references.
template <typename T>
class ptr {
template <typename U>
friend class ptr;
struct ptr_ref {
T* ptr;
int wc, sc;
};
protected:
ptr_ref* _ref;
bool _weak;
void acquire(ptr_ref* ref)
{
if (_ref)
release();
if (_ref = ref) {
if (_weak)
_ref->wc++;
else
_ref->sc++;
}
}
void acquire(void* ptr)
{
_ref = new ptr_ref();
_ref->ptr = (T* )ptr;
_ref->wc = !!_weak;
_ref->sc = !_weak;
}
void release()
{
if (!_ref)
return;
if (_weak)
_ref->wc--;
else
_ref->sc--;
if (!_ref->sc && _ref->ptr) {
T* ptr = static_cast<T* >(_ref->ptr);
_ref->ptr = 0;
delete ptr;
}
if (!_ref->sc && !_ref->wc)
delete _ref;
_ref = 0;
}
template <class U>
void acquire(const ptr<U>& ptr)
{
T* t = static_cast<U* >(0);
acquire(ptr._ref);
}
public:
ptr(bool weak = false) :
_weak(weak), _ref(0)
{
}
ptr(T* p, bool weak = false) :
_weak(weak), _ref(0)
{
acquire(p);
}
ptr(const ptr<T>& p, bool weak = false) :
_weak(weak), _ref(0)
{
acquire(p._ref);
}
ptr(const weak_ptr<T>& p, bool weak = false) :
_weak(weak), _ref(0)
{
acquire(p._ref);
}
template <class U>
ptr(const ptr<U>& p, bool weak = false) :
_weak(weak), _ref(0)
{
T* x = (U*)0;
acquire(p._ref);
}
template <class U>
ptr(const weak_ptr<U>& p, bool weak = false) :
_weak(weak), _ref(0)
{
T* x = (U*)0;
acquire(p._ref);
}
~ptr()
{
release();
}
void operator=(T* p)
{
acquire(p);
}
ptr<T>& operator=(const ptr<T>& p)
{
acquire(p);
return* this;
}
bool operator==(const ptr<T>& other) const
{
return other._ref == _ref;
}
bool operator!=(const ptr<T>& other) const
{
return other._ref != _ref;
}
bool is_null() const
{
return !_ref || !_ref->ptr;
}
T& operator*() const
{
return* get_pointer();
}
T* operator->() const
{
return get_pointer();
}
operator T*() const
{
return get_pointer();
}
operator bool() const
{
return !is_null();
}
void reset(T* p = 0)
{
acquire(p);
}
T* get_pointer() const
{
if (!_ref || !_ref->ptr)
throw new invalid_pointer;
return static_cast<T* >(_ref->ptr);
}
};
template <typename T>
class weak_ptr : public ptr<T> {
public:
weak_ptr() :
ptr<T>(true)
{
}
weak_ptr(T* p) :
ptr<T>(p, true)
{
}
weak_ptr(const ptr<T>& p) :
ptr<T>(p, true)
{
}
weak_ptr(const weak_ptr<T>& p) :
ptr<T>(p, true)
{
}
template <class U>
weak_ptr(const ptr<U>& p) :
ptr<T>(p, true)
{
}
template <class U>
weak_ptr(const weak_ptr<U>& p) :
ptr<T>(p, true)
{
}
};
NDPPD_NS_END

165
src/route.cc Normal file
View File

@ -0,0 +1,165 @@
// 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 <list>
#include <memory>
#include <fstream>
#include "ndppd.h"
#include "route.h"
NDPPD_NS_BEGIN
std::list<ptr<route> > route::_routes;
route::route(const address& addr, const std::string& ifname) :
_addr(addr), _ifname(ifname)
{
}
size_t route::hexdec(const char* str, unsigned char* buf, size_t size)
{
for (size_t i = 0; ; i++) {
if (i >= size)
return i;
char c1 = tolower(str[i* 2]), c2 = tolower(str[i* 2 + 1]);
if (!isxdigit(c1) || !isxdigit(c2))
return i;
if ((c1 >= '0') && (c1 <= '9'))
buf[i] = (c1 - '0') << 4;
else
buf[i] = ((c1 - 'a') + 10) << 4;
if ((c2 >= '0') && (c2 <= '9'))
buf[i] |= c2 - '0';
else
buf[i] |= (c2 - 'a') + 10;
}
}
std::string route::token(const char* str)
{
while (*str && isspace(*str)) {
str++;
}
if (!*str) {
return "";
}
std::stringstream ss;
while (*str && !isspace(*str)) {
ss <<* str++;
}
return ss.str();
}
void route::load(const std::string& path)
{
_routes.clear();
try {
std::ifstream ifs;
ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit);
ifs.open(path.c_str(), std::ios::in);
ifs.exceptions(std::ifstream::badbit);
while (!ifs.eof()) {
char buf[1024];
ifs.getline(buf, sizeof(buf));
if (ifs.gcount() < 149)
continue;
address addr;
unsigned char pfx;
if (hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) {
// TODO: Warn here?
continue;
}
if (hexdec(buf + 33,& pfx, 1) != 1) {
// TODO: Warn here?
continue;
}
addr.prefix((int)pfx);
route::create(addr, token(buf + 141));
}
} catch (std::ifstream::failure e) {
logger::warning() << "Failed to parse IPv6 routing data from '" << path << "'";
logger::error() << e.what();
}
}
ptr<route> route::create(const address& addr, const std::string& ifname)
{
ptr<route> rt(new route(addr, ifname));
logger::debug() << "route::create() addr=" << addr << ", ifname=" << ifname;
_routes.push_back(rt);
return rt;
}
ptr<route> route::find(const address& addr)
{
for (std::list<ptr<route> >::iterator it = _routes.begin();
it != _routes.end(); it++) {
if ((*it)->addr() == addr)
return *it;
}
return ptr<route>();
}
ptr<iface> route::find_and_open(const address& addr)
{
ptr<route> rt;
if (rt = find(addr)) {
return rt->ifa();
}
return ptr<iface>();
}
const std::string& route::ifname() const
{
return _ifname;
}
ptr<iface> route::ifa()
{
if (!_ifa) {
return _ifa = iface::open_ifd(_ifname);
}
return ptr<iface>();
}
const address& route::addr() const
{
return _addr;
}
NDPPD_NS_END

59
src/route.h Normal file
View File

@ -0,0 +1,59 @@
// 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/>.
#pragma once
#include <string>
#include <list>
#include <memory>
#include "ndppd.h"
NDPPD_NS_BEGIN
class route {
public:
static ptr<route> create(const address& addr, const std::string& ifname);
static ptr<route> find(const address& addr);
static ptr<iface> find_and_open(const address& addr);
static void load(const std::string& path);
const std::string& ifname() const;
const address& addr() const;
ptr<iface> ifa();
private:
address _addr;
std::string _ifname;
ptr<iface> _ifa;
static size_t hexdec(const char* str, unsigned char* buf, size_t size);
static std::string token(const char* str);
static std::list<ptr<route> > _routes;
route(const address& addr, const std::string& ifname);
};
NDPPD_NS_END

View File

@ -35,20 +35,24 @@ ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, const ptr<ifac
ru->_pr = pr; ru->_pr = pr;
ru->_ifa = ifa; ru->_ifa = ifa;
ru->_addr = addr; ru->_addr = addr;
ru->_aut = false;
logger::debug() << "rule::create() if=" << pr->ifa()->name() << ", addr=" << addr; logger::debug() << "rule::create() if=" << pr->ifa()->name() << ", addr=" << addr;
return ru; return ru;
} }
ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr) ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, bool aut)
{ {
ptr<rule> ru(new rule()); ptr<rule> ru(new rule());
ru->_ptr = ru; ru->_ptr = ru;
ru->_pr = pr; ru->_pr = pr;
ru->_addr = addr; ru->_addr = addr;
ru->_aut = aut;
logger::debug() << "rule::create() if=" << pr->ifa()->name().c_str() << ", addr=" << addr; logger::debug()
<< "rule::create() if=" << pr->ifa()->name().c_str() << ", addr=" << addr
<< ", auto=" << (aut ? "yes" : "no");
return ru; return ru;
} }
@ -63,9 +67,9 @@ ptr<iface> rule::ifa() const
return _ifa; return _ifa;
} }
bool rule::is_static() const bool rule::is_auto() const
{ {
return !!_ifa; return _aut;
} }
bool rule::check(const address& addr) const bool rule::check(const address& addr) const

View File

@ -28,8 +28,20 @@ NDPPD_NS_BEGIN
class iface; class iface;
class proxy; class proxy;
class rule class rule {
{ public:
static ptr<rule> create(const ptr<proxy>& pr, const address& addr, const ptr<iface>& ifa);
static ptr<rule> create(const ptr<proxy>& pr, const address& addr, bool stc = true);
const address& addr() const;
ptr<iface> ifa() const;
bool is_auto() const;
bool check(const address& addr) const;
private: private:
weak_ptr<rule> _ptr; weak_ptr<rule> _ptr;
@ -39,21 +51,9 @@ private:
address _addr; address _addr;
bool _aut;
rule(); rule();
public:
static ptr<rule> create(const ptr<proxy>& pr, const address& addr, const ptr<iface>& ifa);
static ptr<rule> create(const ptr<proxy>& pr, const address& addr);
const address& addr() const;
ptr<iface> ifa() const;
bool is_static() const;
bool check(const address& addr) const;
}; };
NDPPD_NS_END NDPPD_NS_END

View File

@ -24,8 +24,7 @@ NDPPD_NS_BEGIN
class proxy; class proxy;
class iface; class iface;
class session class session {
{
private: private:
weak_ptr<session> _ptr; weak_ptr<session> _ptr;
@ -80,8 +79,6 @@ public:
void send_solicit(); void send_solicit();
void refesh(); void refesh();
}; };
NDPPD_NS_END NDPPD_NS_END