198 lines
4.3 KiB
C++
198 lines
4.3 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 <list>
|
|
#include <memory>
|
|
#include <fstream>
|
|
|
|
#include "ndppd.h"
|
|
#include "route.h"
|
|
|
|
NDPPD_NS_BEGIN
|
|
|
|
std::list<ptr<route> > route::_routes;
|
|
|
|
int route::_ttl;
|
|
|
|
int route::_c_ttl;
|
|
|
|
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)
|
|
{
|
|
// Hack to make sure the interfaces are not freed prematurely.
|
|
std::list<ptr<route> > tmp_routes(_routes);
|
|
_routes.clear();
|
|
|
|
logger::debug() << "reading routes";
|
|
|
|
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 (route::hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) {
|
|
// TODO: Warn here?
|
|
continue;
|
|
}
|
|
|
|
if (route::hexdec(buf + 33,& pfx, 1) != 1) {
|
|
// TODO: Warn here?
|
|
continue;
|
|
}
|
|
|
|
addr.prefix((int)pfx);
|
|
|
|
route::create(addr, route::token(buf + 141));
|
|
}
|
|
} catch (std::ifstream::failure e) {
|
|
logger::warning() << "Failed to parse IPv6 routing data from '" << path << "'";
|
|
logger::error() << e.what();
|
|
}
|
|
}
|
|
|
|
void route::update(int elapsed_time)
|
|
{
|
|
if ((_c_ttl -= elapsed_time) <= 0) {
|
|
load("/proc/net/ipv6_route");
|
|
_c_ttl = _ttl;
|
|
}
|
|
}
|
|
|
|
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) {
|
|
logger::debug() << "router::ifa() opening interface '" << _ifname << "'";
|
|
return _ifa = iface::open_ifd(_ifname);
|
|
}
|
|
|
|
return ptr<iface>();
|
|
}
|
|
|
|
const address& route::addr() const
|
|
{
|
|
return _addr;
|
|
}
|
|
|
|
int route::ttl()
|
|
{
|
|
return _ttl;
|
|
}
|
|
|
|
void route::ttl(int ttl)
|
|
{
|
|
_ttl = ttl;
|
|
}
|
|
|
|
NDPPD_NS_END
|
|
|