2011-09-13 21:26:12 +02:00
|
|
|
// ndppd - NDP Proxy Daemon
|
2012-01-26 11:21:07 +01:00
|
|
|
// Copyright (C) 2011 Daniel Adolfsson <daniel@priv.nu>
|
2011-09-13 21:26:12 +02:00
|
|
|
//
|
|
|
|
// 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 <algorithm>
|
2017-07-01 10:55:41 +02:00
|
|
|
#include <sstream>
|
2011-09-13 21:26:12 +02:00
|
|
|
|
|
|
|
#include "ndppd.h"
|
|
|
|
#include "proxy.h"
|
|
|
|
#include "iface.h"
|
|
|
|
#include "session.h"
|
|
|
|
|
2012-01-31 20:17:19 +01:00
|
|
|
NDPPD_NS_BEGIN
|
2011-09-13 21:26:12 +02:00
|
|
|
|
2012-02-02 20:35:09 +01:00
|
|
|
std::list<weak_ptr<session> > session::_sessions;
|
2011-09-14 10:53:21 +02:00
|
|
|
|
2016-09-21 14:53:28 +12:00
|
|
|
static address all_nodes = address("ff02::1");
|
|
|
|
|
2011-09-14 10:53:21 +02:00
|
|
|
void session::update_all(int elapsed_time)
|
2011-09-13 21:26:12 +02:00
|
|
|
{
|
2012-02-02 20:35:09 +01:00
|
|
|
for (std::list<weak_ptr<session> >::iterator it = _sessions.begin();
|
2012-02-04 11:01:25 +01:00
|
|
|
it != _sessions.end(); ) {
|
2012-02-04 09:41:41 +01:00
|
|
|
if (!*it) {
|
2012-02-04 11:01:25 +01:00
|
|
|
_sessions.erase(it++);
|
2012-02-04 09:41:41 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-02-04 11:01:25 +01:00
|
|
|
ptr<session> se = *it++;
|
2012-01-28 20:25:57 +01:00
|
|
|
|
2012-02-04 09:41:41 +01:00
|
|
|
if ((se->_ttl -= elapsed_time) >= 0) {
|
2012-01-28 20:25:57 +01:00
|
|
|
continue;
|
2012-02-04 09:41:41 +01:00
|
|
|
}
|
2012-01-28 20:25:57 +01:00
|
|
|
|
|
|
|
switch (se->_status) {
|
2017-07-01 11:40:48 +02:00
|
|
|
|
2012-01-28 20:25:57 +01:00
|
|
|
case session::WAITING:
|
2017-07-01 12:06:25 +02:00
|
|
|
logger::debug() << "session is now invalid [taddr=" << se->_taddr << "]";
|
2017-07-04 22:00:03 +02:00
|
|
|
|
|
|
|
if (se->_fails < se->_retries) {
|
|
|
|
se->_ttl = se->_pr->timeout();
|
|
|
|
se->_fails++;
|
|
|
|
|
|
|
|
// Send another solicit
|
|
|
|
se->send_solicit();
|
|
|
|
} else {
|
|
|
|
se->_status = session::INVALID;
|
|
|
|
se->_ttl = se->_pr->deadtime();
|
|
|
|
}
|
2012-01-28 20:25:57 +01:00
|
|
|
break;
|
2017-07-01 11:31:50 +02:00
|
|
|
|
2017-07-01 11:40:48 +02:00
|
|
|
case session::RENEWING:
|
2017-07-01 12:06:25 +02:00
|
|
|
logger::debug() << "session is became invalid [taddr=" << se->_taddr << "]";
|
2017-07-04 22:00:03 +02:00
|
|
|
|
|
|
|
if (se->_fails < se->_retries) {
|
|
|
|
se->_ttl = se->_pr->timeout();
|
|
|
|
se->_fails++;
|
|
|
|
|
|
|
|
// Send another solicit
|
|
|
|
se->send_solicit();
|
|
|
|
} else {
|
|
|
|
se->_pr->remove_session(se);
|
|
|
|
}
|
2017-07-01 11:40:48 +02:00
|
|
|
break;
|
|
|
|
|
2017-07-01 11:31:50 +02:00
|
|
|
case session::VALID:
|
2017-07-04 22:00:03 +02:00
|
|
|
if (se->touched() == true ||
|
|
|
|
se->keepalive() == true)
|
|
|
|
{
|
2017-07-01 12:06:25 +02:00
|
|
|
logger::debug() << "session is renewing [taddr=" << se->_taddr << "]";
|
2017-07-01 11:31:50 +02:00
|
|
|
se->_status = session::RENEWING;
|
|
|
|
se->_ttl = se->_pr->timeout();
|
2017-07-04 22:00:03 +02:00
|
|
|
se->_fails = 0;
|
2017-07-01 11:31:50 +02:00
|
|
|
se->_touched = false;
|
|
|
|
|
|
|
|
// Send another solicit to make sure the route is still valid
|
|
|
|
se->send_solicit();
|
|
|
|
} else {
|
|
|
|
se->_pr->remove_session(se);
|
|
|
|
}
|
|
|
|
break;
|
2012-01-28 20:25:57 +01:00
|
|
|
|
|
|
|
default:
|
|
|
|
se->_pr->remove_session(se);
|
|
|
|
}
|
|
|
|
}
|
2011-09-14 10:53:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
session::~session()
|
|
|
|
{
|
2012-01-31 20:17:19 +01:00
|
|
|
logger::debug() << "session::~session() this=" << logger::format("%x", this);
|
2017-07-01 12:25:19 +02:00
|
|
|
|
|
|
|
if (_wired == true) {
|
|
|
|
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
|
|
|
it != _ifaces.end(); it++) {
|
|
|
|
handle_auto_unwire((*it));
|
|
|
|
}
|
|
|
|
}
|
2012-01-28 20:25:57 +01:00
|
|
|
|
2012-02-04 11:01:25 +01:00
|
|
|
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
2017-07-01 11:14:51 +02:00
|
|
|
it != _ifaces.end(); it++)
|
|
|
|
{
|
2012-02-04 11:01:25 +01:00
|
|
|
(*it)->remove_session(_ptr);
|
|
|
|
}
|
2011-09-13 21:26:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-04 23:52:43 +02:00
|
|
|
ptr<session> session::create(const ptr<proxy>& pr, const address& taddr, bool auto_wire, bool keepalive, int retries)
|
2011-09-13 21:26:12 +02:00
|
|
|
{
|
2012-02-02 20:35:09 +01:00
|
|
|
ptr<session> se(new session());
|
2011-09-13 21:26:12 +02:00
|
|
|
|
2017-07-01 12:25:19 +02:00
|
|
|
se->_ptr = se;
|
|
|
|
se->_pr = pr;
|
|
|
|
se->_taddr = taddr;
|
|
|
|
se->_autowire = auto_wire;
|
2017-07-04 22:00:03 +02:00
|
|
|
se->_keepalive = keepalive;
|
|
|
|
se->_retries = retries;
|
2017-07-02 22:38:23 +02:00
|
|
|
se->_wired = false;
|
2017-07-01 12:25:19 +02:00
|
|
|
se->_ttl = pr->timeout();
|
2017-07-02 22:38:23 +02:00
|
|
|
se->_touched = false;
|
2011-09-14 10:53:21 +02:00
|
|
|
|
2012-01-28 20:25:57 +01:00
|
|
|
_sessions.push_back(se);
|
2011-09-13 21:26:12 +02:00
|
|
|
|
2012-02-02 20:35:09 +01:00
|
|
|
logger::debug()
|
2017-07-04 23:52:43 +02:00
|
|
|
<< "session::create() pr=" << logger::format("%x", (proxy* )pr) << ", proxy=" << ((pr->ifa()) ? pr->ifa()->name() : "null")
|
|
|
|
<< ", taddr=" << taddr << " =" << logger::format("%x", (session* )se);
|
2011-09-13 21:26:12 +02:00
|
|
|
|
2012-01-28 20:25:57 +01:00
|
|
|
return se;
|
2011-09-13 21:26:12 +02:00
|
|
|
}
|
|
|
|
|
2012-02-02 20:35:09 +01:00
|
|
|
void session::add_iface(const ptr<iface>& ifa)
|
2011-09-13 21:26:12 +02:00
|
|
|
{
|
2012-01-28 20:25:57 +01:00
|
|
|
if (std::find(_ifaces.begin(), _ifaces.end(), ifa) != _ifaces.end())
|
|
|
|
return;
|
2011-09-13 21:26:12 +02:00
|
|
|
|
2012-02-02 20:35:09 +01:00
|
|
|
ifa->add_session(_ptr);
|
2012-01-28 20:25:57 +01:00
|
|
|
_ifaces.push_back(ifa);
|
2011-09-13 21:26:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-04 23:52:43 +02:00
|
|
|
void session::add_pending(const address& addr)
|
|
|
|
{
|
|
|
|
for (std::list<ptr<address> >::iterator ad = _pending.begin(); ad != _pending.end(); ad++) {
|
|
|
|
if (addr == (*ad))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_pending.push_back(new address(addr));
|
|
|
|
}
|
|
|
|
|
2011-09-13 21:26:12 +02:00
|
|
|
void session::send_solicit()
|
|
|
|
{
|
2012-02-03 22:25:00 +01:00
|
|
|
logger::debug() << "session::send_solicit() (_ifaces.size() = " << _ifaces.size() << ")";
|
2012-01-28 20:25:57 +01:00
|
|
|
|
2012-02-02 20:35:09 +01:00
|
|
|
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
2012-01-28 20:25:57 +01:00
|
|
|
it != _ifaces.end(); it++) {
|
2012-02-03 22:25:00 +01:00
|
|
|
logger::debug() << " - " << (*it)->name();
|
2012-01-28 20:25:57 +01:00
|
|
|
(*it)->write_solicit(_taddr);
|
|
|
|
}
|
2011-09-13 21:26:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-01 11:31:50 +02:00
|
|
|
void session::touch()
|
|
|
|
{
|
2017-07-02 22:38:23 +02:00
|
|
|
if (_touched == false)
|
|
|
|
{
|
|
|
|
_touched = true;
|
|
|
|
|
|
|
|
if (status() == session::WAITING || status() == session::INVALID)
|
|
|
|
send_solicit();
|
|
|
|
}
|
2017-07-01 11:31:50 +02:00
|
|
|
}
|
|
|
|
|
2017-07-04 23:52:43 +02:00
|
|
|
void session::send_advert(const address& daddr)
|
2011-09-13 21:26:12 +02:00
|
|
|
{
|
2017-07-04 23:52:43 +02:00
|
|
|
_pr->ifa()->write_advert(daddr, _taddr, _pr->router());
|
2011-09-16 17:06:36 +02:00
|
|
|
}
|
2011-09-13 21:26:12 +02:00
|
|
|
|
2017-07-01 09:28:39 +02:00
|
|
|
void session::handle_auto_wire(const ptr<iface>& ifa)
|
|
|
|
{
|
2017-07-04 23:52:43 +02:00
|
|
|
if (_wired == true)
|
|
|
|
return;
|
|
|
|
|
2017-07-01 09:28:39 +02:00
|
|
|
logger::debug()
|
|
|
|
<< "session::handle_auto_wire() taddr=" << _taddr << ", ifa=" << ifa->name();
|
|
|
|
|
2017-07-01 10:55:41 +02:00
|
|
|
std::stringstream route_cmd;
|
|
|
|
route_cmd << "ip";
|
|
|
|
route_cmd << " " << "-6";
|
2017-07-01 11:14:51 +02:00
|
|
|
route_cmd << " " << "route";
|
2017-07-01 10:55:41 +02:00
|
|
|
route_cmd << " " << "replace";
|
|
|
|
route_cmd << " " << std::string(_taddr);
|
|
|
|
route_cmd << " " << "dev";
|
|
|
|
route_cmd << " " << ifa->name();
|
|
|
|
|
|
|
|
logger::debug()
|
|
|
|
<< "session::system(" << route_cmd.str() << ")";
|
|
|
|
|
|
|
|
system(route_cmd.str().c_str());
|
2017-07-01 12:25:19 +02:00
|
|
|
|
|
|
|
_wired = true;
|
2017-07-01 09:28:39 +02:00
|
|
|
}
|
|
|
|
|
2017-07-01 11:14:51 +02:00
|
|
|
void session::handle_auto_unwire(const ptr<iface>& ifa)
|
|
|
|
{
|
|
|
|
logger::debug()
|
|
|
|
<< "session::handle_auto_unwire() taddr=" << _taddr << ", ifa=" << ifa->name();
|
|
|
|
|
|
|
|
std::stringstream route_cmd;
|
|
|
|
route_cmd << "ip";
|
|
|
|
route_cmd << " " << "-6";
|
|
|
|
route_cmd << " " << "route";
|
|
|
|
route_cmd << " " << "flush";
|
|
|
|
route_cmd << " " << std::string(_taddr);
|
|
|
|
route_cmd << " " << "dev";
|
|
|
|
route_cmd << " " << ifa->name();
|
|
|
|
|
|
|
|
logger::debug()
|
|
|
|
<< "session::system(" << route_cmd.str() << ")";
|
|
|
|
|
|
|
|
system(route_cmd.str().c_str());
|
2017-07-01 12:25:19 +02:00
|
|
|
|
|
|
|
_wired = false;
|
2017-07-01 11:14:51 +02:00
|
|
|
}
|
|
|
|
|
2017-07-01 09:28:39 +02:00
|
|
|
void session::handle_advert(const ptr<iface>& ifa)
|
|
|
|
{
|
2017-07-02 22:38:23 +02:00
|
|
|
if (_autowire == true && _status == WAITING) {
|
2017-07-01 09:28:39 +02:00
|
|
|
handle_auto_wire(ifa);
|
|
|
|
}
|
|
|
|
|
|
|
|
handle_advert();
|
|
|
|
}
|
|
|
|
|
2017-07-02 22:38:23 +02:00
|
|
|
|
2011-09-13 21:26:12 +02:00
|
|
|
void session::handle_advert()
|
|
|
|
{
|
2017-07-01 10:42:38 +02:00
|
|
|
logger::debug()
|
|
|
|
<< "session::handle_advert() taddr=" << _taddr << ", ttl=" << _pr->ttl();
|
|
|
|
|
2012-01-28 20:25:57 +01:00
|
|
|
_status = VALID;
|
|
|
|
_ttl = _pr->ttl();
|
2017-07-04 22:00:03 +02:00
|
|
|
_fails = 0;
|
2017-07-04 23:52:43 +02:00
|
|
|
|
|
|
|
if (!_pending.empty()) {
|
|
|
|
for (std::list<ptr<address> >::iterator ad = _pending.begin();
|
|
|
|
ad != _pending.end(); ad++) {
|
|
|
|
ptr<address> addr = (*ad);
|
|
|
|
logger::debug() << " - forward to " << addr;
|
2011-09-13 21:26:12 +02:00
|
|
|
|
2017-07-04 23:52:43 +02:00
|
|
|
send_advert(addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
_pending.clear();
|
|
|
|
}
|
2011-09-13 21:26:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const address& session::taddr() const
|
|
|
|
{
|
2012-01-28 20:25:57 +01:00
|
|
|
return _taddr;
|
2011-09-13 21:26:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-01 09:28:39 +02:00
|
|
|
bool session::autowire() const
|
|
|
|
{
|
|
|
|
return _autowire;
|
|
|
|
}
|
|
|
|
|
2017-07-04 22:00:03 +02:00
|
|
|
bool session::keepalive() const
|
|
|
|
{
|
|
|
|
return _keepalive;
|
|
|
|
}
|
|
|
|
|
|
|
|
int session::retries() const
|
|
|
|
{
|
|
|
|
return _retries;
|
|
|
|
}
|
|
|
|
|
|
|
|
int session::fails() const
|
|
|
|
{
|
|
|
|
return _fails;
|
|
|
|
}
|
|
|
|
|
2017-07-01 12:25:19 +02:00
|
|
|
bool session::wired() const
|
|
|
|
{
|
|
|
|
return _wired;
|
|
|
|
}
|
|
|
|
|
2017-07-01 11:31:50 +02:00
|
|
|
bool session::touched() const
|
|
|
|
{
|
|
|
|
return _touched;
|
|
|
|
}
|
|
|
|
|
2011-09-13 21:26:12 +02:00
|
|
|
int session::status() const
|
|
|
|
{
|
2012-01-28 20:25:57 +01:00
|
|
|
return _status;
|
2011-09-13 21:26:12 +02:00
|
|
|
}
|
|
|
|
|
2011-09-18 02:46:51 +02:00
|
|
|
void session::status(int val)
|
|
|
|
{
|
2012-01-28 20:25:57 +01:00
|
|
|
_status = val;
|
2011-09-18 02:46:51 +02:00
|
|
|
}
|
|
|
|
|
2012-01-31 20:17:19 +01:00
|
|
|
NDPPD_NS_END
|