Merge pull request #30 from john-sharratt/master
Feature to automatically wire the routes for a gateway
This commit is contained in:
commit
6ef7a57b2e
41
ChangeLog
41
ChangeLog
@ -1,3 +1,44 @@
|
|||||||
|
2017-01-07 Johnathan Sharratt <johnathan.sharratt@gmail.com>
|
||||||
|
|
||||||
|
* Version 0.2.6
|
||||||
|
|
||||||
|
* Added a new configuration setting named "deadtime" which allows
|
||||||
|
sessions that never made it the VALID to have a different (i.e.
|
||||||
|
shorter) life before they are removed (and potentially retried)
|
||||||
|
(defauilt is the same value as usual TTL for backwards compatibility)
|
||||||
|
|
||||||
|
* Added a new configuration setting named "autowire" in the proxy
|
||||||
|
section (default is off)
|
||||||
|
|
||||||
|
* If the "autowire" setting is on, then upon receiving a NDP
|
||||||
|
Neighbor Advertisment from one of the rule interfaces, a route will
|
||||||
|
be automatically added into the linux IP routing tables thus allowing
|
||||||
|
for a full featured gateway when IPv6 forwarding is turned on.
|
||||||
|
Note: Be careful as "accept_ra" may need to be set to 2 on the
|
||||||
|
interface during testing for the routing tables to retain their
|
||||||
|
default route (unrelated to this patch but took me a while to
|
||||||
|
discover).
|
||||||
|
|
||||||
|
* When a session ends then anything that was "autowired" will be
|
||||||
|
automatically removed thus ensuring the routing tables are in a
|
||||||
|
similar state to before the daemon (or session) made any changes
|
||||||
|
|
||||||
|
* Added a feature where the session will attempt to renew itself
|
||||||
|
(with a new NDP Solicitation) before it self-terminates, this is
|
||||||
|
required otherwise packets could be lost when the session terminates
|
||||||
|
triggering the automatically removal of the route table entry.
|
||||||
|
|
||||||
|
* Ensured that renew operations only take place if the session has
|
||||||
|
been recently touched by an external solicitation - this ensures
|
||||||
|
that sessions that become IDLE are cleaned up quickly
|
||||||
|
|
||||||
|
* Moved the daemonizing step till after the system executed the
|
||||||
|
configure step so that the error exit codes are returned to the daemon
|
||||||
|
caller.
|
||||||
|
|
||||||
|
* No longer continuing to load the daemon if any of the interfaces fail
|
||||||
|
to load which should give a more predictable behaviour and better user experience.
|
||||||
|
|
||||||
2016-04-18 Daniel Adolfsson <daniel@priv.nu>
|
2016-04-18 Daniel Adolfsson <daniel@priv.nu>
|
||||||
|
|
||||||
* Version 0.2.5
|
* Version 0.2.5
|
||||||
|
@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
route-ttl 30000
|
route-ttl 30000
|
||||||
|
|
||||||
|
# address-ttl <integer> (NEW)
|
||||||
|
# This tells 'ndppd' how often to reload the IP address file /proc/net/if_inet6
|
||||||
|
# Default value is '30000' (30 seconds).
|
||||||
|
|
||||||
|
address-ttl 30000
|
||||||
|
|
||||||
# proxy <interface>
|
# proxy <interface>
|
||||||
# This sets up a listener, that will listen for any Neighbor Solicitation
|
# This sets up a listener, that will listen for any Neighbor Solicitation
|
||||||
# messages, and respond to them according to a set of rules (see below).
|
# messages, and respond to them according to a set of rules (see below).
|
||||||
@ -22,6 +28,36 @@ proxy eth0 {
|
|||||||
# invalidating the entry, in milliseconds. Default value is '500'.
|
# invalidating the entry, in milliseconds. Default value is '500'.
|
||||||
|
|
||||||
timeout 500
|
timeout 500
|
||||||
|
|
||||||
|
# autowire <yes|no|true|false>
|
||||||
|
# Controls whether ndppd will automatically create host entries
|
||||||
|
# in the routing tables when it receives Neighbor Advertisements on a
|
||||||
|
# listening interface. The the default value is no.
|
||||||
|
# Note: Autowire will ignore all rules with 'auto' or 'static' given it
|
||||||
|
# is expected that the routes are already defined for these paths
|
||||||
|
|
||||||
|
autowire no
|
||||||
|
|
||||||
|
# keepalive <yes|no|true|false>
|
||||||
|
# Controls whether ndppd will automatically attempt to keep routing
|
||||||
|
# sessions alive by actively sending out NDP Solicitations before the the
|
||||||
|
# session is expired. The the default value is yes.
|
||||||
|
|
||||||
|
keepalive yes
|
||||||
|
|
||||||
|
# retries <integer>
|
||||||
|
# Number of times a NDP Solicitation will be sent out before the daemon
|
||||||
|
# considers a route unreachable. The default value is 3
|
||||||
|
|
||||||
|
retries 3
|
||||||
|
|
||||||
|
# promiscuous <yes|no|true|false>
|
||||||
|
# Controls whether ndppd will put the proxy listening interface into promiscuous
|
||||||
|
# mode and hence will react to inbound and outbound NDP commands. This is
|
||||||
|
# required for machines behind the gateway to talk to each other in more
|
||||||
|
# complex topology scenarios. The the default value is no.
|
||||||
|
|
||||||
|
promiscuous no
|
||||||
|
|
||||||
# ttl <integer>
|
# ttl <integer>
|
||||||
# Controls how long a valid or invalid entry remains in the cache, in
|
# Controls how long a valid or invalid entry remains in the cache, in
|
||||||
@ -55,6 +91,13 @@ proxy eth0 {
|
|||||||
|
|
||||||
auto
|
auto
|
||||||
|
|
||||||
|
# autovia <yes|no|true|false>
|
||||||
|
# Any addresses updated using NDP advertisments will use a gateway to
|
||||||
|
# route traffic on this particular interface (only works wiith the iface
|
||||||
|
# rule type). Default is no
|
||||||
|
|
||||||
|
autovia no
|
||||||
|
|
||||||
# Note that before version 0.2.2 of 'ndppd', if you didn't choose a
|
# Note that before version 0.2.2 of 'ndppd', if you didn't choose a
|
||||||
# method, it defaulted to 'static'. For compatibility reasons we choose
|
# method, it defaulted to 'static'. For compatibility reasons we choose
|
||||||
# to keep this behavior - for now (it may be removed in a future version).
|
# to keep this behavior - for now (it may be removed in a future version).
|
||||||
|
14
ndppd.conf.5
14
ndppd.conf.5
@ -48,6 +48,20 @@ Controls how long
|
|||||||
.B ndppd
|
.B ndppd
|
||||||
will cache an entry. This is in milliseconds, and the default value
|
will cache an entry. This is in milliseconds, and the default value
|
||||||
is 30000 (30 seconds).
|
is 30000 (30 seconds).
|
||||||
|
.IP "autowire <yes|no>"
|
||||||
|
Controls whether
|
||||||
|
.B ndppd
|
||||||
|
will automatically create host entries in the routing tables when
|
||||||
|
.B ndppd receives Neighbor Advertisements on a listening interface.
|
||||||
|
The default value is no.
|
||||||
|
.IP "promiscuous <yes|no>"
|
||||||
|
Controls whether
|
||||||
|
.B ndppd
|
||||||
|
will put the proxy listening interface into promiscuous mode and
|
||||||
|
hence will react to inbound and outbound NDP commands. This is
|
||||||
|
required for machines behind the gateway to talk to each other in
|
||||||
|
more complex topology scenarios.
|
||||||
|
The the default value is no.
|
||||||
.IP "timeout <value>"
|
.IP "timeout <value>"
|
||||||
Controls how long
|
Controls how long
|
||||||
.B ndppd
|
.B ndppd
|
||||||
|
123
src/address.cc
123
src/address.cc
@ -15,6 +15,8 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <fstream>
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -27,9 +29,16 @@
|
|||||||
|
|
||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
#include "address.h"
|
#include "address.h"
|
||||||
|
#include "route.h"
|
||||||
|
|
||||||
NDPPD_NS_BEGIN
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
std::list<ptr<route> > address::_addresses;
|
||||||
|
|
||||||
|
int address::_ttl;
|
||||||
|
|
||||||
|
int address::_c_ttl;
|
||||||
|
|
||||||
address::address()
|
address::address()
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
@ -48,6 +57,19 @@ address::address(const address& addr)
|
|||||||
_mask.s6_addr32[3] = addr._mask.s6_addr32[3];
|
_mask.s6_addr32[3] = addr._mask.s6_addr32[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address::address(const ptr<address>& addr)
|
||||||
|
{
|
||||||
|
_addr.s6_addr32[0] = addr->_addr.s6_addr32[0];
|
||||||
|
_addr.s6_addr32[1] = addr->_addr.s6_addr32[1];
|
||||||
|
_addr.s6_addr32[2] = addr->_addr.s6_addr32[2];
|
||||||
|
_addr.s6_addr32[3] = addr->_addr.s6_addr32[3];
|
||||||
|
|
||||||
|
_mask.s6_addr32[0] = addr->_mask.s6_addr32[0];
|
||||||
|
_mask.s6_addr32[1] = addr->_mask.s6_addr32[1];
|
||||||
|
_mask.s6_addr32[2] = addr->_mask.s6_addr32[2];
|
||||||
|
_mask.s6_addr32[3] = addr->_mask.s6_addr32[3];
|
||||||
|
}
|
||||||
|
|
||||||
address::address(const std::string& str)
|
address::address(const std::string& str)
|
||||||
{
|
{
|
||||||
parse_string(str);
|
parse_string(str);
|
||||||
@ -110,6 +132,21 @@ bool address::operator!=(const address& addr) const
|
|||||||
((_addr.s6_addr32[3] ^ addr._addr.s6_addr32[3]) & _mask.s6_addr32[3]));
|
((_addr.s6_addr32[3] ^ addr._addr.s6_addr32[3]) & _mask.s6_addr32[3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool address::is_empty() const
|
||||||
|
{
|
||||||
|
if (_addr.s6_addr32[0] == 0 &&
|
||||||
|
_addr.s6_addr32[1] == 0 &&
|
||||||
|
_addr.s6_addr32[2] == 0 &&
|
||||||
|
_addr.s6_addr32[3] == 0 &&
|
||||||
|
_mask.s6_addr32[0] == 0xffffffff &&
|
||||||
|
_mask.s6_addr32[1] == 0xffffffff &&
|
||||||
|
_mask.s6_addr32[2] == 0xffffffff &&
|
||||||
|
_mask.s6_addr32[3] == 0xffffffff)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void address::reset()
|
void address::reset()
|
||||||
{
|
{
|
||||||
_addr.s6_addr32[0] = 0;
|
_addr.s6_addr32[0] = 0;
|
||||||
@ -299,7 +336,93 @@ bool address::is_multicast() const
|
|||||||
|
|
||||||
bool address::is_unicast() const
|
bool address::is_unicast() const
|
||||||
{
|
{
|
||||||
|
if (_addr.s6_addr32[2] == 0 &&
|
||||||
|
_addr.s6_addr32[3] == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
return _addr.s6_addr[0] != 0xff;
|
return _addr.s6_addr[0] != 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void address::add(const address& addr, const std::string& ifname)
|
||||||
|
{
|
||||||
|
ptr<route> rt(new route(addr, ifname));
|
||||||
|
// logger::debug() << "address::create() addr=" << addr << ", ifname=" << ifname;
|
||||||
|
_addresses.push_back(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<ptr<route> >::iterator address::addresses_begin()
|
||||||
|
{
|
||||||
|
return _addresses.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<ptr<route> >::iterator address::addresses_end()
|
||||||
|
{
|
||||||
|
return _addresses.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void address::load(const std::string& path)
|
||||||
|
{
|
||||||
|
// Hack to make sure the addresses are not freed prematurely.
|
||||||
|
std::list<ptr<route> > tmp_addresses(_addresses);
|
||||||
|
_addresses.clear();
|
||||||
|
|
||||||
|
logger::debug() << "reading IP addresses";
|
||||||
|
|
||||||
|
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() < 53) {
|
||||||
|
if (ifs.gcount() > 0)
|
||||||
|
logger::debug() << "skipping entry (size=" << ifs.gcount() << ")";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
address addr;
|
||||||
|
|
||||||
|
if (route::hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) {
|
||||||
|
logger::warning() << "failed to load address (" << buf << ")";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.prefix(128);
|
||||||
|
|
||||||
|
std::string iface = route::token(buf + 45);
|
||||||
|
|
||||||
|
address::add(addr, iface);
|
||||||
|
|
||||||
|
logger::debug() << "found local addr=" << addr << ", iface=" << iface;
|
||||||
|
}
|
||||||
|
} catch (std::ifstream::failure e) {
|
||||||
|
logger::warning() << "Failed to parse IPv6 address data from '" << path << "'";
|
||||||
|
logger::error() << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger::debug() << "completed IP addresses load";
|
||||||
|
}
|
||||||
|
|
||||||
|
void address::update(int elapsed_time)
|
||||||
|
{
|
||||||
|
if ((_c_ttl -= elapsed_time) <= 0) {
|
||||||
|
load("/proc/net/if_inet6");
|
||||||
|
_c_ttl = _ttl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int address::ttl()
|
||||||
|
{
|
||||||
|
return _ttl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void address::ttl(int ttl)
|
||||||
|
{
|
||||||
|
_ttl = ttl;
|
||||||
|
}
|
||||||
|
|
||||||
NDPPD_NS_END
|
NDPPD_NS_END
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <list>
|
||||||
#include <netinet/ip6.h>
|
#include <netinet/ip6.h>
|
||||||
|
|
||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
@ -24,15 +25,24 @@ NDPPD_NS_BEGIN
|
|||||||
|
|
||||||
class iface;
|
class iface;
|
||||||
|
|
||||||
|
class route;
|
||||||
|
|
||||||
class address {
|
class address {
|
||||||
public:
|
public:
|
||||||
address();
|
address();
|
||||||
address(const address& addr);
|
address(const address& addr);
|
||||||
|
address(const ptr<address>& addr);
|
||||||
address(const std::string& str);
|
address(const std::string& str);
|
||||||
address(const char* str);
|
address(const char* str);
|
||||||
address(const in6_addr& addr);
|
address(const in6_addr& addr);
|
||||||
address(const in6_addr& addr, const in6_addr& mask);
|
address(const in6_addr& addr, const in6_addr& mask);
|
||||||
address(const in6_addr& addr, int prefix);
|
address(const in6_addr& addr, int prefix);
|
||||||
|
|
||||||
|
static void update(int elapsed_time);
|
||||||
|
|
||||||
|
static int ttl();
|
||||||
|
|
||||||
|
static void ttl(int ttl);
|
||||||
|
|
||||||
struct in6_addr& addr();
|
struct in6_addr& addr();
|
||||||
|
|
||||||
@ -46,6 +56,8 @@ public:
|
|||||||
bool operator!=(const address& addr) const;
|
bool operator!=(const address& addr) const;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
bool is_empty() const;
|
||||||
|
|
||||||
const std::string to_string() const;
|
const std::string to_string() const;
|
||||||
|
|
||||||
@ -60,8 +72,22 @@ public:
|
|||||||
bool is_multicast() const;
|
bool is_multicast() const;
|
||||||
|
|
||||||
operator std::string() const;
|
operator std::string() const;
|
||||||
|
|
||||||
|
static void add(const address& addr, const std::string& ifname);
|
||||||
|
|
||||||
|
static void load(const std::string& path);
|
||||||
|
|
||||||
|
static std::list<ptr<route> >::iterator addresses_begin();
|
||||||
|
|
||||||
|
static std::list<ptr<route> >::iterator addresses_end();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static int _ttl;
|
||||||
|
|
||||||
|
static int _c_ttl;
|
||||||
|
|
||||||
|
static std::list<ptr<route> > _addresses;
|
||||||
|
|
||||||
struct in6_addr _addr, _mask;
|
struct in6_addr _addr, _mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
310
src/iface.cc
310
src/iface.cc
@ -40,6 +40,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
|
#include "route.h"
|
||||||
|
|
||||||
NDPPD_NS_BEGIN
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
@ -65,13 +66,19 @@ iface::~iface()
|
|||||||
if (_prev_allmulti >= 0) {
|
if (_prev_allmulti >= 0) {
|
||||||
allmulti(_prev_allmulti);
|
allmulti(_prev_allmulti);
|
||||||
}
|
}
|
||||||
|
if (_prev_promiscuous >= 0) {
|
||||||
|
promiscuous(_prev_promiscuous);
|
||||||
|
}
|
||||||
close(_pfd);
|
close(_pfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
_map_dirty = true;
|
_map_dirty = true;
|
||||||
|
|
||||||
|
_serves.clear();
|
||||||
|
_parents.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<iface> iface::open_pfd(const std::string& name)
|
ptr<iface> iface::open_pfd(const std::string& name, bool promiscuous)
|
||||||
{
|
{
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
|
|
||||||
@ -169,6 +176,13 @@ ptr<iface> iface::open_pfd(const std::string& name)
|
|||||||
|
|
||||||
// Eh. Allmulti.
|
// Eh. Allmulti.
|
||||||
ifa->_prev_allmulti = ifa->allmulti(1);
|
ifa->_prev_allmulti = ifa->allmulti(1);
|
||||||
|
|
||||||
|
// Eh. Promiscuous
|
||||||
|
if (promiscuous == true) {
|
||||||
|
ifa->_prev_promiscuous = ifa->promiscuous(1);
|
||||||
|
} else {
|
||||||
|
ifa->_prev_promiscuous = -1;
|
||||||
|
}
|
||||||
|
|
||||||
_map_dirty = true;
|
_map_dirty = true;
|
||||||
|
|
||||||
@ -287,7 +301,7 @@ ptr<iface> iface::open_ifd(const std::string& name)
|
|||||||
return ifa;
|
return ifa;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t iface::read(int fd, struct sockaddr* saddr, uint8_t* msg, size_t size)
|
ssize_t iface::read(int fd, struct sockaddr* saddr, ssize_t saddr_size, uint8_t* msg, size_t size)
|
||||||
{
|
{
|
||||||
struct msghdr mhdr;
|
struct msghdr mhdr;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
@ -301,18 +315,21 @@ ssize_t iface::read(int fd, struct sockaddr* saddr, uint8_t* msg, size_t size)
|
|||||||
|
|
||||||
memset(&mhdr, 0, sizeof(mhdr));
|
memset(&mhdr, 0, sizeof(mhdr));
|
||||||
mhdr.msg_name = (caddr_t)saddr;
|
mhdr.msg_name = (caddr_t)saddr;
|
||||||
mhdr.msg_namelen = sizeof(struct sockaddr);
|
mhdr.msg_namelen = saddr_size;
|
||||||
mhdr.msg_iov =& iov;
|
mhdr.msg_iov =& iov;
|
||||||
mhdr.msg_iovlen = 1;
|
mhdr.msg_iovlen = 1;
|
||||||
|
|
||||||
if ((len = recvmsg(fd,& mhdr, 0)) < 0)
|
if ((len = recvmsg(fd,& mhdr, 0)) < 0)
|
||||||
|
{
|
||||||
|
logger::error() << "iface::read() failed! error=" << logger::err() << ", ifa=" << name();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger::debug() << "iface::read() ifa=" << name() << ", len=" << len;
|
||||||
|
|
||||||
if (len < sizeof(struct icmp6_hdr))
|
if (len < sizeof(struct icmp6_hdr))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
logger::debug() << "iface::read() len=" << len;
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,15 +353,14 @@ ssize_t iface::write(int fd, const address& daddr, const uint8_t* msg, size_t si
|
|||||||
mhdr.msg_iov =& iov;
|
mhdr.msg_iov =& iov;
|
||||||
mhdr.msg_iovlen = 1;
|
mhdr.msg_iovlen = 1;
|
||||||
|
|
||||||
logger::debug() << "iface::write() daddr=" << daddr.to_string() << ", len="
|
logger::debug() << "iface::write() ifa=" << name() << ", daddr=" << daddr.to_string() << ", len="
|
||||||
<< size;
|
<< size;
|
||||||
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if ((len = sendmsg(fd,& mhdr, 0)) < 0)
|
if ((len = sendmsg(fd,& mhdr, 0)) < 0)
|
||||||
{
|
{
|
||||||
int e = errno;
|
logger::error() << "iface::write() failed! error=" << logger::err() << ", ifa=" << name() << ", daddr=" << daddr.to_string();
|
||||||
logger::error() << "iface::write() failed! errno=" << e;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,8 +373,10 @@ ssize_t iface::read_solicit(address& saddr, address& daddr, address& taddr)
|
|||||||
uint8_t msg[256];
|
uint8_t msg[256];
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
if ((len = read(_pfd, (struct sockaddr*)&t_saddr, msg, sizeof(msg))) < 0)
|
if ((len = read(_pfd, (struct sockaddr*)&t_saddr, sizeof(struct sockaddr_ll), msg, sizeof(msg))) < 0) {
|
||||||
|
logger::warning() << "iface::read_solicit() failed: " << logger::err();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
struct ip6_hdr* ip6h =
|
struct ip6_hdr* ip6h =
|
||||||
(struct ip6_hdr* )(msg + ETH_HLEN);
|
(struct ip6_hdr* )(msg + ETH_HLEN);
|
||||||
@ -369,9 +387,14 @@ ssize_t iface::read_solicit(address& saddr, address& daddr, address& taddr)
|
|||||||
taddr = ns->nd_ns_target;
|
taddr = ns->nd_ns_target;
|
||||||
daddr = ip6h->ip6_dst;
|
daddr = ip6h->ip6_dst;
|
||||||
saddr = ip6h->ip6_src;
|
saddr = ip6h->ip6_src;
|
||||||
|
|
||||||
|
// Ignore packets sent from this machine
|
||||||
|
if (iface::is_local(saddr) == true) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
logger::debug() << "iface::read_solicit() saddr=" << saddr.to_string()
|
logger::debug() << "iface::read_solicit() saddr=" << saddr.to_string()
|
||||||
<< ", daddr=" << daddr.to_string() << ", len=" << len;
|
<< ", daddr=" << daddr.to_string() << ", taddr=" << taddr.to_string() << ", len=" << len;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -451,11 +474,22 @@ ssize_t iface::read_advert(address& saddr, address& taddr)
|
|||||||
struct sockaddr_in6 t_saddr;
|
struct sockaddr_in6 t_saddr;
|
||||||
uint8_t msg[256];
|
uint8_t msg[256];
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
|
memset(&t_saddr, 0, sizeof(struct sockaddr_in6));
|
||||||
|
t_saddr.sin6_family = AF_INET6;
|
||||||
|
t_saddr.sin6_port = htons(IPPROTO_ICMPV6); // Needed?
|
||||||
|
|
||||||
if ((len = read(_ifd, (struct sockaddr* )&t_saddr, msg, sizeof(msg))) < 0)
|
if ((len = read(_ifd, (struct sockaddr* )&t_saddr, sizeof(struct sockaddr_in6), msg, sizeof(msg))) < 0) {
|
||||||
|
logger::warning() << "iface::read_advert() failed: " << logger::err();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
saddr = t_saddr.sin6_addr;
|
saddr = t_saddr.sin6_addr;
|
||||||
|
|
||||||
|
// Ignore packets sent from this machine
|
||||||
|
if (iface::is_local(saddr) == true) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (((struct icmp6_hdr* )msg)->icmp6_type != ND_NEIGHBOR_ADVERT)
|
if (((struct icmp6_hdr* )msg)->icmp6_type != ND_NEIGHBOR_ADVERT)
|
||||||
return -1;
|
return -1;
|
||||||
@ -467,6 +501,79 @@ ssize_t iface::read_advert(address& saddr, address& taddr)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool iface::is_local(const address& addr)
|
||||||
|
{
|
||||||
|
// Check if the address is for an interface we own that is attached to
|
||||||
|
// one of the slave interfaces
|
||||||
|
for (std::list<ptr<route> >::iterator ad = address::addresses_begin(); ad != address::addresses_end(); ad++)
|
||||||
|
{
|
||||||
|
if ((*ad)->addr() == addr)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iface::handle_local(const address& saddr, const address& taddr)
|
||||||
|
{
|
||||||
|
// Check if the address is for an interface we own that is attached to
|
||||||
|
// one of the slave interfaces
|
||||||
|
for (std::list<ptr<route> >::iterator ad = address::addresses_begin(); ad != address::addresses_end(); ad++)
|
||||||
|
{
|
||||||
|
if ((*ad)->addr() == taddr)
|
||||||
|
{
|
||||||
|
// Loop through all the serves that are using this iface to respond to NDP solicitation requests
|
||||||
|
for (std::list<weak_ptr<proxy> >::iterator pit = serves_begin(); pit != serves_end(); pit++) {
|
||||||
|
ptr<proxy> pr = (*pit);
|
||||||
|
if (!pr) continue;
|
||||||
|
|
||||||
|
for (std::list<ptr<rule> >::iterator it = pr->rules_begin(); it != pr->rules_end(); it++) {
|
||||||
|
ptr<rule> ru = *it;
|
||||||
|
|
||||||
|
if (ru->daughter() && ru->daughter()->name() == (*ad)->ifname())
|
||||||
|
{
|
||||||
|
logger::debug() << "proxy::handle_solicit() found local taddr=" << taddr;
|
||||||
|
write_advert(saddr, taddr, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iface::handle_reverse_advert(const address& saddr, const std::string& ifname)
|
||||||
|
{
|
||||||
|
if (!saddr.is_unicast())
|
||||||
|
return;
|
||||||
|
|
||||||
|
logger::debug()
|
||||||
|
<< "proxy::handle_reverse_advert()";
|
||||||
|
|
||||||
|
// Loop through all the parents that forward new NDP soliciation requests to this interface
|
||||||
|
for (std::list<weak_ptr<proxy> >::iterator pit = parents_begin(); pit != parents_end(); pit++) {
|
||||||
|
ptr<proxy> parent = (*pit);
|
||||||
|
if (!parent || !parent->ifa()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the reverse path on any proxies that are dealing
|
||||||
|
// with the reverse direction (this helps improve connectivity and
|
||||||
|
// latency in a full duplex setup)
|
||||||
|
for (std::list<ptr<rule> >::iterator it = parent->rules_begin(); it != parent->rules_end(); it++) {
|
||||||
|
ptr<rule> ru = *it;
|
||||||
|
|
||||||
|
if (ru->addr() == saddr &&
|
||||||
|
ru->daughter()->name() == ifname)
|
||||||
|
{
|
||||||
|
logger::debug() << " - generating artifical advertisement: " << ifname;
|
||||||
|
parent->handle_stateless_advert(saddr, saddr, ifname, ru->autovia());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void iface::fixup_pollfds()
|
void iface::fixup_pollfds()
|
||||||
{
|
{
|
||||||
_pollfds.resize(_map.size()* 2);
|
_pollfds.resize(_map.size()* 2);
|
||||||
@ -489,22 +596,6 @@ void iface::fixup_pollfds()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iface::remove_session(const ptr<session>& se)
|
|
||||||
{
|
|
||||||
for (std::list<weak_ptr<session> >::iterator it = _sessions.begin();
|
|
||||||
it != _sessions.end(); it++) {
|
|
||||||
if (*it == se) {
|
|
||||||
_sessions.erase(it);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iface::add_session(const ptr<session>& se)
|
|
||||||
{
|
|
||||||
_sessions.push_back(se);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iface::cleanup()
|
void iface::cleanup()
|
||||||
{
|
{
|
||||||
for (std::map<std::string, weak_ptr<iface> >::iterator it = _map.begin();
|
for (std::map<std::string, weak_ptr<iface> >::iterator it = _map.begin();
|
||||||
@ -534,6 +625,7 @@ int iface::poll_all()
|
|||||||
int len;
|
int len;
|
||||||
|
|
||||||
if ((len = ::poll(&_pollfds[0], _pollfds.size(), 50)) < 0) {
|
if ((len = ::poll(&_pollfds[0], _pollfds.size(), 50)) < 0) {
|
||||||
|
logger::error() << "Failed to poll interfaces: " << logger::err();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -562,36 +654,95 @@ int iface::poll_all()
|
|||||||
ptr<iface> ifa = i_it->second;
|
ptr<iface> ifa = i_it->second;
|
||||||
|
|
||||||
address saddr, daddr, taddr;
|
address saddr, daddr, taddr;
|
||||||
|
ssize_t size;
|
||||||
|
|
||||||
if (is_pfd) {
|
if (is_pfd) {
|
||||||
if (ifa->read_solicit(saddr, daddr, taddr) < 0) {
|
size = ifa->read_solicit(saddr, daddr, taddr);
|
||||||
|
if (size < 0) {
|
||||||
logger::error() << "Failed to read from interface '%s'", ifa->_name.c_str();
|
logger::error() << "Failed to read from interface '%s'", ifa->_name.c_str();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (size == 0) {
|
||||||
if (!saddr.is_unicast()/* || !daddr.is_multicast()*/) {
|
logger::debug() << "iface::read_solicit() loopback received and ignored";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifa->_pr) {
|
// Process any local addresses for interfaces that we are proxying
|
||||||
ifa->_pr->handle_solicit(saddr, daddr, taddr);
|
if (ifa->handle_local(saddr, taddr) == true) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We have to handle all the parents who may be interested in
|
||||||
|
// the reverse path towards the one who sent this solicit.
|
||||||
|
// In fact, the parent need to know the source address in order
|
||||||
|
// to respond to NDP Solicitations
|
||||||
|
ifa->handle_reverse_advert(saddr, ifa->name());
|
||||||
|
|
||||||
|
// Loop through all the proxies that are using this iface to respond to NDP solicitation requests
|
||||||
|
bool handled = false;
|
||||||
|
for (std::list<weak_ptr<proxy> >::iterator pit = ifa->serves_begin(); pit != ifa->serves_end(); pit++) {
|
||||||
|
ptr<proxy> pr = (*pit);
|
||||||
|
if (!pr) continue;
|
||||||
|
|
||||||
|
// Process the solicitation request by relating it to other
|
||||||
|
// interfaces or lookup up any statics routes we have configured
|
||||||
|
handled = true;
|
||||||
|
pr->handle_solicit(saddr, taddr, ifa->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it was not handled then write an error message
|
||||||
|
if (handled == false) {
|
||||||
|
logger::debug() << " - solicit was ignored";
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (ifa->read_advert(saddr, taddr) < 0) {
|
size = ifa->read_advert(saddr, taddr);
|
||||||
|
if (size < 0) {
|
||||||
logger::error() << "Failed to read from interface '%s'", ifa->_name.c_str();
|
logger::error() << "Failed to read from interface '%s'", ifa->_name.c_str();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (size == 0) {
|
||||||
for (std::list<weak_ptr<session> >::iterator s_it = ifa->_sessions.begin();
|
logger::debug() << "iface::read_advert() loopback received and ignored";
|
||||||
s_it != ifa->_sessions.end(); s_it++) {
|
continue;
|
||||||
assert(!s_it->is_null());
|
}
|
||||||
|
|
||||||
const ptr<session> sess = *s_it;
|
// Process the NDP advert
|
||||||
|
bool handled = false;
|
||||||
if ((sess->taddr() == taddr) && (sess->status() == session::WAITING)) {
|
for (std::list<weak_ptr<proxy> >::iterator pit = ifa->parents_begin(); pit != ifa->parents_end(); pit++) {
|
||||||
sess->handle_advert();
|
ptr<proxy> pr = (*pit);
|
||||||
break;
|
if (!pr || !pr->ifa()) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The proxy must have a rule for this interface or it is not meant to receive
|
||||||
|
// any notifications and thus they must be ignored
|
||||||
|
bool autovia = false;
|
||||||
|
bool is_relevant = false;
|
||||||
|
for (std::list<ptr<rule> >::iterator it = pr->rules_begin(); it != pr->rules_end(); it++) {
|
||||||
|
ptr<rule> ru = *it;
|
||||||
|
|
||||||
|
if (ru->addr() == taddr &&
|
||||||
|
ru->daughter() &&
|
||||||
|
ru->daughter()->name() == ifa->name())
|
||||||
|
{
|
||||||
|
is_relevant = true;
|
||||||
|
autovia = ru->autovia();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_relevant == false) {
|
||||||
|
logger::debug() << "iface::read_advert() advert is not for " << ifa->name() << "...skipping";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the NDP advertisement
|
||||||
|
handled = true;
|
||||||
|
pr->handle_advert(saddr, taddr, ifa->name(), autovia);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it was not handled then write an error message
|
||||||
|
if (handled == false) {
|
||||||
|
logger::debug() << " - advert was ignored";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -638,19 +789,78 @@ int iface::allmulti(int state)
|
|||||||
return old_state;
|
return old_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iface::promiscuous(int state)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
logger::debug()
|
||||||
|
<< "iface::promiscuous() state="
|
||||||
|
<< state << ", _name=\"" << _name << "\"";
|
||||||
|
|
||||||
|
state = !!state;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
|
||||||
|
strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ);
|
||||||
|
|
||||||
|
if (ioctl(_pfd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||||
|
logger::error() << "Failed to get promiscuous: " << logger::err();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int old_state = !!(ifr.ifr_flags &IFF_PROMISC);
|
||||||
|
|
||||||
|
if (state == old_state) {
|
||||||
|
return old_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
ifr.ifr_flags |= IFF_PROMISC;
|
||||||
|
} else {
|
||||||
|
ifr.ifr_flags &= ~IFF_PROMISC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(_pfd, SIOCSIFFLAGS, &ifr) < 0) {
|
||||||
|
logger::error() << "Failed to set promiscuous: " << logger::err();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return old_state;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& iface::name() const
|
const std::string& iface::name() const
|
||||||
{
|
{
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iface::pr(const ptr<proxy>& pr)
|
void iface::add_serves(const ptr<proxy>& pr)
|
||||||
{
|
{
|
||||||
_pr = pr;
|
_serves.push_back(pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ptr<proxy>& iface::pr() const
|
std::list<weak_ptr<proxy> >::iterator iface::serves_begin()
|
||||||
{
|
{
|
||||||
return _pr;
|
return _serves.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<weak_ptr<proxy> >::iterator iface::serves_end()
|
||||||
|
{
|
||||||
|
return _serves.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void iface::add_parent(const ptr<proxy>& pr)
|
||||||
|
{
|
||||||
|
_parents.push_back(pr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<weak_ptr<proxy> >::iterator iface::parents_begin()
|
||||||
|
{
|
||||||
|
return _parents.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<weak_ptr<proxy> >::iterator iface::parents_end()
|
||||||
|
{
|
||||||
|
return _parents.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
NDPPD_NS_END
|
NDPPD_NS_END
|
||||||
|
53
src/iface.h
53
src/iface.h
@ -38,13 +38,13 @@ public:
|
|||||||
|
|
||||||
static ptr<iface> open_ifd(const std::string& name);
|
static ptr<iface> open_ifd(const std::string& name);
|
||||||
|
|
||||||
static ptr<iface> open_pfd(const std::string& name);
|
static ptr<iface> open_pfd(const std::string& name, bool promiscuous);
|
||||||
|
|
||||||
static int poll_all();
|
static int poll_all();
|
||||||
|
|
||||||
static ssize_t read(int fd, struct sockaddr* saddr, uint8_t* msg, size_t size);
|
ssize_t read(int fd, struct sockaddr* saddr, ssize_t saddr_size, uint8_t* msg, size_t size);
|
||||||
|
|
||||||
static ssize_t write(int fd, const address& daddr, const uint8_t* msg, size_t size);
|
ssize_t write(int fd, const address& daddr, const uint8_t* msg, size_t size);
|
||||||
|
|
||||||
// Writes a NB_NEIGHBOR_SOLICIT message to the _ifd socket.
|
// Writes a NB_NEIGHBOR_SOLICIT message to the _ifd socket.
|
||||||
ssize_t write_solicit(const address& taddr);
|
ssize_t write_solicit(const address& taddr);
|
||||||
@ -57,21 +57,31 @@ public:
|
|||||||
|
|
||||||
// Reads a NB_NEIGHBOR_ADVERT message from the _ifd socket;
|
// Reads a NB_NEIGHBOR_ADVERT message from the _ifd socket;
|
||||||
ssize_t read_advert(address& saddr, address& taddr);
|
ssize_t read_advert(address& saddr, address& taddr);
|
||||||
|
|
||||||
|
bool handle_local(const address& saddr, const address& taddr);
|
||||||
|
|
||||||
|
bool is_local(const address& addr);
|
||||||
|
|
||||||
|
void handle_reverse_advert(const address& saddr, const std::string& ifname);
|
||||||
|
|
||||||
// Returns the name of the interface.
|
// Returns the name of the interface.
|
||||||
const std::string& name() const;
|
const std::string& name() const;
|
||||||
|
|
||||||
// Adds a session to be monitored for ND_NEIGHBOR_ADVERT messages.
|
std::list<weak_ptr<proxy> >::iterator serves_begin();
|
||||||
void add_session(const ptr<session>& se);
|
|
||||||
|
std::list<weak_ptr<proxy> >::iterator serves_end();
|
||||||
void remove_session(const ptr<session>& se);
|
|
||||||
|
void add_serves(const ptr<proxy>& proxy);
|
||||||
void pr(const ptr<proxy>& pr);
|
|
||||||
|
std::list<weak_ptr<proxy> >::iterator parents_begin();
|
||||||
const ptr<proxy>& pr() const;
|
|
||||||
|
std::list<weak_ptr<proxy> >::iterator parents_end();
|
||||||
|
|
||||||
|
void add_parent(const ptr<proxy>& parent);
|
||||||
|
|
||||||
|
static std::map<std::string, weak_ptr<iface> > _map;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::map<std::string, weak_ptr<iface> > _map;
|
|
||||||
|
|
||||||
static bool _map_dirty;
|
static bool _map_dirty;
|
||||||
|
|
||||||
@ -96,15 +106,16 @@ private:
|
|||||||
|
|
||||||
// Previous state of ALLMULTI for the interface.
|
// Previous state of ALLMULTI for the interface.
|
||||||
int _prev_allmulti;
|
int _prev_allmulti;
|
||||||
|
|
||||||
|
// Previous state of PROMISC for the interface
|
||||||
|
int _prev_promiscuous;
|
||||||
|
|
||||||
// Name of this interface.
|
// Name of this interface.
|
||||||
std::string _name;
|
std::string _name;
|
||||||
|
|
||||||
// An array of sessions that are monitoring this interface for
|
std::list<weak_ptr<proxy> > _serves;
|
||||||
// ND_NEIGHBOR_ADVERT messages.
|
|
||||||
std::list<weak_ptr<session> > _sessions;
|
std::list<weak_ptr<proxy> > _parents;
|
||||||
|
|
||||||
weak_ptr<proxy> _pr;
|
|
||||||
|
|
||||||
// The link-layer address of this interface.
|
// The link-layer address of this interface.
|
||||||
struct ether_addr hwaddr;
|
struct ether_addr hwaddr;
|
||||||
@ -112,6 +123,10 @@ private:
|
|||||||
// Turns on/off ALLMULTI for this interface - returns the previous state
|
// Turns on/off ALLMULTI for this interface - returns the previous state
|
||||||
// or -1 if there was an error.
|
// or -1 if there was an error.
|
||||||
int allmulti(int state);
|
int allmulti(int state);
|
||||||
|
|
||||||
|
// Turns on/off PROMISC for this interface - returns the previous state
|
||||||
|
// or -1 if there was an error
|
||||||
|
int promiscuous(int state);
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
iface();
|
iface();
|
||||||
|
131
src/ndppd.cc
131
src/ndppd.cc
@ -36,9 +36,10 @@ using namespace ndppd;
|
|||||||
static int daemonize()
|
static int daemonize()
|
||||||
{
|
{
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
if (pid < 0)
|
logger::error() << "Failed to fork during daemonize: " << logger::err();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (pid > 0)
|
if (pid > 0)
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -46,12 +47,15 @@ static int daemonize()
|
|||||||
umask(0);
|
umask(0);
|
||||||
|
|
||||||
pid_t sid = setsid();
|
pid_t sid = setsid();
|
||||||
|
if (sid < 0) {
|
||||||
if (sid < 0)
|
logger::error() << "Failed to setsid during daemonize: " << logger::err();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (chdir("/") < 0)
|
if (chdir("/") < 0) {
|
||||||
|
logger::error() << "Failed to change path during daemonize: " << logger::err();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
close(STDIN_FILENO);
|
close(STDIN_FILENO);
|
||||||
close(STDOUT_FILENO);
|
close(STDOUT_FILENO);
|
||||||
@ -137,6 +141,13 @@ static bool configure(ptr<conf>& cf)
|
|||||||
route::ttl(30000);
|
route::ttl(30000);
|
||||||
else
|
else
|
||||||
route::ttl(*x_cf);
|
route::ttl(*x_cf);
|
||||||
|
|
||||||
|
if (!(x_cf = cf->find("address-ttl")))
|
||||||
|
address::ttl(30000);
|
||||||
|
else
|
||||||
|
address::ttl(*x_cf);
|
||||||
|
|
||||||
|
std::list<ptr<rule> > myrules;
|
||||||
|
|
||||||
std::vector<ptr<conf> >::const_iterator p_it;
|
std::vector<ptr<conf> >::const_iterator p_it;
|
||||||
|
|
||||||
@ -148,22 +159,47 @@ static bool configure(ptr<conf>& cf)
|
|||||||
if (pr_cf->empty()) {
|
if (pr_cf->empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool promiscuous = false;
|
||||||
|
if (!(x_cf = pr_cf->find("promiscuous")))
|
||||||
|
promiscuous = false;
|
||||||
|
else
|
||||||
|
promiscuous = *x_cf;
|
||||||
|
|
||||||
ptr<proxy> pr = proxy::open(*pr_cf);
|
ptr<proxy> pr = proxy::open(*pr_cf, promiscuous);
|
||||||
|
if (!pr || pr.is_null() == true) {
|
||||||
if (!pr) {
|
return false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(x_cf = pr_cf->find("router")))
|
if (!(x_cf = pr_cf->find("router")))
|
||||||
pr->router(true);
|
pr->router(true);
|
||||||
else
|
else
|
||||||
pr->router(*x_cf);
|
pr->router(*x_cf);
|
||||||
|
|
||||||
|
if (!(x_cf = pr_cf->find("autowire")))
|
||||||
|
pr->autowire(false);
|
||||||
|
else
|
||||||
|
pr->autowire(*x_cf);
|
||||||
|
|
||||||
|
if (!(x_cf = pr_cf->find("keepalive")))
|
||||||
|
pr->keepalive(true);
|
||||||
|
else
|
||||||
|
pr->keepalive(*x_cf);
|
||||||
|
|
||||||
|
if (!(x_cf = pr_cf->find("retries")))
|
||||||
|
pr->retries(3);
|
||||||
|
else
|
||||||
|
pr->retries(*x_cf);
|
||||||
|
|
||||||
if (!(x_cf = pr_cf->find("ttl")))
|
if (!(x_cf = pr_cf->find("ttl")))
|
||||||
pr->ttl(30000);
|
pr->ttl(30000);
|
||||||
else
|
else
|
||||||
pr->ttl(*x_cf);
|
pr->ttl(*x_cf);
|
||||||
|
|
||||||
|
if (!(x_cf = pr_cf->find("deadtime")))
|
||||||
|
pr->deadtime(pr->ttl());
|
||||||
|
else
|
||||||
|
pr->deadtime(*x_cf);
|
||||||
|
|
||||||
if (!(x_cf = pr_cf->find("timeout")))
|
if (!(x_cf = pr_cf->find("timeout")))
|
||||||
pr->timeout(500);
|
pr->timeout(500);
|
||||||
@ -178,17 +214,71 @@ static bool configure(ptr<conf>& cf)
|
|||||||
ptr<conf> ru_cf =* r_it;
|
ptr<conf> ru_cf =* r_it;
|
||||||
|
|
||||||
address addr(*ru_cf);
|
address addr(*ru_cf);
|
||||||
|
|
||||||
|
bool autovia = false;
|
||||||
|
if (!(x_cf = ru_cf->find("autovia")))
|
||||||
|
autovia = false;
|
||||||
|
else
|
||||||
|
autovia = *x_cf;
|
||||||
|
|
||||||
if (x_cf = ru_cf->find("iface")) {
|
if (x_cf = ru_cf->find("iface"))
|
||||||
pr->add_rule(addr, iface::open_ifd(*x_cf));
|
{
|
||||||
|
ptr<iface> ifa = iface::open_ifd(*x_cf);
|
||||||
|
if (!ifa || ifa.is_null() == true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifa->add_parent(pr);
|
||||||
|
|
||||||
|
myrules.push_back(pr->add_rule(addr, ifa, autovia));
|
||||||
} else if (ru_cf->find("auto")) {
|
} else if (ru_cf->find("auto")) {
|
||||||
pr->add_rule(addr, true);
|
myrules.push_back(pr->add_rule(addr, true));
|
||||||
} else {
|
} else {
|
||||||
pr->add_rule(addr, false);
|
myrules.push_back(pr->add_rule(addr, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print out all the topology
|
||||||
|
for (std::map<std::string, weak_ptr<iface> >::iterator i_it = iface::_map.begin(); i_it != iface::_map.end(); i_it++) {
|
||||||
|
ptr<iface> ifa = i_it->second;
|
||||||
|
|
||||||
|
logger::debug() << "iface " << ifa->name() << " {";
|
||||||
|
|
||||||
|
for (std::list<weak_ptr<proxy> >::iterator pit = ifa->serves_begin(); pit != ifa->serves_end(); pit++) {
|
||||||
|
ptr<proxy> pr = (*pit);
|
||||||
|
if (!pr) continue;
|
||||||
|
|
||||||
|
logger::debug() << " " << "proxy " << logger::format("%x", pr.get_pointer()) << " {";
|
||||||
|
|
||||||
|
for (std::list<ptr<rule> >::iterator rit = pr->rules_begin(); rit != pr->rules_end(); rit++) {
|
||||||
|
ptr<rule> ru = *rit;
|
||||||
|
|
||||||
|
logger::debug() << " " << "rule " << logger::format("%x", ru.get_pointer()) << " {";
|
||||||
|
logger::debug() << " " << "taddr " << ru->addr()<< ";";
|
||||||
|
if (ru->is_auto())
|
||||||
|
logger::debug() << " " << "auto;";
|
||||||
|
else if (!ru->daughter())
|
||||||
|
logger::debug() << " " << "static;";
|
||||||
|
else
|
||||||
|
logger::debug() << " " << "iface " << ru->daughter()->name() << ";";
|
||||||
|
logger::debug() << " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
logger::debug() << " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
logger::debug() << " " << "parents {";
|
||||||
|
for (std::list<weak_ptr<proxy> >::iterator pit = ifa->parents_begin(); pit != ifa->parents_end(); pit++) {
|
||||||
|
ptr<proxy> pr = (*pit);
|
||||||
|
|
||||||
|
logger::debug() << " " << "parent " << logger::format("%x", pr.get_pointer()) << ";";
|
||||||
|
}
|
||||||
|
logger::debug() << " }";
|
||||||
|
|
||||||
|
logger::debug() << "}";
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,18 +351,16 @@ int main(int argc, char* argv[], char* env[])
|
|||||||
if (cf.is_null())
|
if (cf.is_null())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (!configure(cf))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (daemon) {
|
if (daemon) {
|
||||||
logger::syslog(true);
|
logger::syslog(true);
|
||||||
|
|
||||||
if (daemonize() < 0) {
|
if (daemonize() < 0)
|
||||||
logger::error() << "Failed to daemonize process";
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!configure(cf))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!pidfile.empty()) {
|
if (!pidfile.empty()) {
|
||||||
std::ofstream pf;
|
std::ofstream pf;
|
||||||
pf.open(pidfile.c_str(), std::ios::out | std::ios::trunc);
|
pf.open(pidfile.c_str(), std::ios::out | std::ios::trunc);
|
||||||
@ -310,6 +398,9 @@ int main(int argc, char* argv[], char* env[])
|
|||||||
|
|
||||||
if (rule::any_auto())
|
if (rule::any_auto())
|
||||||
route::update(elapsed_time);
|
route::update(elapsed_time);
|
||||||
|
|
||||||
|
if (rule::any_iface())
|
||||||
|
address::update(elapsed_time);
|
||||||
|
|
||||||
session::update_all(elapsed_time);
|
session::update_all(elapsed_time);
|
||||||
}
|
}
|
||||||
|
220
src/proxy.cc
220
src/proxy.cc
@ -26,87 +26,99 @@
|
|||||||
#include "session.h"
|
#include "session.h"
|
||||||
|
|
||||||
NDPPD_NS_BEGIN
|
NDPPD_NS_BEGIN
|
||||||
|
|
||||||
|
static address all_nodes = address("ff02::1");
|
||||||
|
|
||||||
std::list<ptr<proxy> > proxy::_list;
|
std::list<ptr<proxy> > proxy::_list;
|
||||||
|
|
||||||
proxy::proxy() :
|
proxy::proxy() :
|
||||||
_router(true), _ttl(30000), _timeout(500)
|
_router(true), _ttl(30000), _deadtime(3000), _timeout(500), _autowire(false), _keepalive(true), _promiscuous(false), _retries(3)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<proxy> proxy::create(const ptr<iface>& ifa)
|
ptr<proxy> proxy::find_aunt(const std::string& ifname, const address& taddr)
|
||||||
|
{
|
||||||
|
for (std::list<ptr<proxy> >::iterator sit = _list.begin();
|
||||||
|
sit != _list.end(); sit++)
|
||||||
|
{
|
||||||
|
ptr<proxy> pr = (*sit);
|
||||||
|
|
||||||
|
bool has_addr = false;
|
||||||
|
for (std::list<ptr<rule> >::iterator it = pr->_rules.begin(); it != pr->_rules.end(); it++) {
|
||||||
|
ptr<rule> ru = *it;
|
||||||
|
|
||||||
|
if (ru->addr() == taddr) {
|
||||||
|
has_addr = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_addr == false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pr->ifa() && pr->ifa()->name() == ifname)
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr<proxy>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<proxy> proxy::create(const ptr<iface>& ifa, bool promiscuous)
|
||||||
{
|
{
|
||||||
ptr<proxy> pr(new proxy());
|
ptr<proxy> pr(new proxy());
|
||||||
pr->_ptr = pr;
|
pr->_ptr = pr;
|
||||||
pr->_ifa = ifa;
|
pr->_ifa = ifa;
|
||||||
|
pr->_promiscuous = promiscuous;
|
||||||
|
|
||||||
_list.push_back(pr);
|
_list.push_back(pr);
|
||||||
|
|
||||||
ifa->pr(pr);
|
ifa->add_serves(pr);
|
||||||
|
|
||||||
logger::debug() << "proxy::create() if=" << ifa->name();
|
logger::debug() << "proxy::create() if=" << ifa->name();
|
||||||
|
|
||||||
return pr;
|
return pr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<proxy> proxy::open(const std::string& ifname)
|
ptr<proxy> proxy::open(const std::string& ifname, bool promiscuous)
|
||||||
{
|
{
|
||||||
ptr<iface> ifa = iface::open_pfd(ifname);
|
ptr<iface> ifa = iface::open_pfd(ifname, promiscuous);
|
||||||
|
|
||||||
if (!ifa) {
|
if (!ifa) {
|
||||||
return ptr<proxy>();
|
return ptr<proxy>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return create(ifa);
|
return create(ifa, promiscuous);
|
||||||
}
|
}
|
||||||
|
|
||||||
void proxy::handle_solicit(const address& saddr, const address& daddr,
|
ptr<session> proxy::find_or_create_session(const address& taddr)
|
||||||
const address& taddr)
|
|
||||||
{
|
{
|
||||||
logger::debug()
|
|
||||||
<< "proxy::handle_solicit() saddr=" << saddr.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
|
||||||
// find one with the same target address.
|
// find one with the same target address.
|
||||||
|
|
||||||
for (std::list<ptr<session> >::iterator sit = _sessions.begin();
|
for (std::list<ptr<session> >::iterator sit = _sessions.begin();
|
||||||
sit != _sessions.end(); sit++) {
|
sit != _sessions.end(); sit++) {
|
||||||
|
|
||||||
if ((*sit)->taddr() == taddr) {
|
if ((*sit)->taddr() == taddr)
|
||||||
switch ((*sit)->status()) {
|
return (*sit);
|
||||||
case session::WAITING:
|
|
||||||
case session::INVALID:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case session::VALID:
|
|
||||||
(*sit)->send_advert();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptr<session> se;
|
||||||
|
|
||||||
// Since we couldn't find a session that matched, we'll try to find
|
// Since we couldn't find a session that matched, we'll try to find
|
||||||
// a matching rule instead, and then set up a new session.
|
// a matching rule instead, and then set up a new session.
|
||||||
|
|
||||||
ptr<session> se;
|
|
||||||
|
|
||||||
for (std::list<ptr<rule> >::iterator it = _rules.begin();
|
for (std::list<ptr<rule> >::iterator it = _rules.begin();
|
||||||
it != _rules.end(); it++) {
|
it != _rules.end(); it++) {
|
||||||
ptr<rule> ru = *it;
|
ptr<rule> ru = *it;
|
||||||
|
|
||||||
logger::debug() << "checking " << ru->addr() << " against " << taddr;
|
logger::debug() << "checking " << ru->addr() << " against " << taddr;
|
||||||
|
|
||||||
if (!daddr.is_multicast() && ru->addr() != daddr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ru->addr() == taddr) {
|
if (ru->addr() == taddr) {
|
||||||
if (!se) {
|
if (!se) {
|
||||||
se = session::create(_ptr, saddr, daddr, taddr);
|
se = session::create(_ptr, taddr, _autowire, _keepalive, _retries);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ru->is_auto()) {
|
if (ru->is_auto()) {
|
||||||
ptr<route> rt = route::find(taddr);
|
ptr<route> rt = route::find(taddr);
|
||||||
|
|
||||||
@ -115,20 +127,24 @@ void proxy::handle_solicit(const address& saddr, const address& daddr,
|
|||||||
} else {
|
} else {
|
||||||
ptr<iface> ifa = rt->ifa();
|
ptr<iface> ifa = rt->ifa();
|
||||||
|
|
||||||
if (ifa && (ifa != ru->ifa())) {
|
if (ifa && (ifa != ru->daughter())) {
|
||||||
se->add_iface(ifa);
|
se->add_iface(ifa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!ru->ifa()) {
|
} else if (!ru->daughter()) {
|
||||||
// This rule doesn't have an interface, and thus we'll consider
|
// This rule doesn't have an interface, and thus we'll consider
|
||||||
// it "static" and immediately send the response.
|
// it "static" and immediately send the response.
|
||||||
se->handle_advert();
|
se->handle_advert();
|
||||||
return;
|
return se;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
se->add_iface((*it)->ifa());
|
|
||||||
|
ptr<iface> ifa = ru->daughter();
|
||||||
|
se->add_iface(ifa);
|
||||||
|
|
||||||
#ifdef WITH_ND_NETLINK
|
#ifdef WITH_ND_NETLINK
|
||||||
if (if_addr_find((*it)->ifa()->name(), &taddr.const_addr())) {
|
if (if_addr_find(ifa->name(), &taddr.const_addr())) {
|
||||||
logger::debug() << "Sending NA out " << (*it)->ifa()->name();
|
logger::debug() << "Sending NA out " << ifa->name();
|
||||||
se->add_iface(_ifa);
|
se->add_iface(_ifa);
|
||||||
se->handle_advert();
|
se->handle_advert();
|
||||||
}
|
}
|
||||||
@ -136,16 +152,75 @@ void proxy::handle_solicit(const address& saddr, const address& daddr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (se) {
|
if (se) {
|
||||||
_sessions.push_back(se);
|
_sessions.push_back(se);
|
||||||
se->send_solicit();
|
}
|
||||||
|
|
||||||
|
return se;
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::handle_advert(const address& saddr, const address& taddr, const std::string& ifname, bool use_via)
|
||||||
|
{
|
||||||
|
// If a session exists then process the advert in the context of the session
|
||||||
|
for (std::list<ptr<session> >::iterator s_it = _sessions.begin();
|
||||||
|
s_it != _sessions.end(); s_it++)
|
||||||
|
{
|
||||||
|
const ptr<session> sess = *s_it;
|
||||||
|
|
||||||
|
if ((sess->taddr() == taddr)) {
|
||||||
|
sess->handle_advert(saddr, ifname, use_via);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<rule> proxy::add_rule(const address& addr, const ptr<iface>& ifa)
|
void proxy::handle_stateless_advert(const address& saddr, const address& taddr, const std::string& ifname, bool use_via)
|
||||||
|
{
|
||||||
|
logger::debug()
|
||||||
|
<< "proxy::handle_stateless_advert() proxy=" << (ifa() ? ifa()->name() : "null") << ", taddr=" << taddr.to_string() << ", ifname=" << ifname;
|
||||||
|
|
||||||
|
ptr<session> se = find_or_create_session(taddr);
|
||||||
|
if (!se) return;
|
||||||
|
|
||||||
|
if (_autowire == true && se->status() == session::WAITING) {
|
||||||
|
se->handle_auto_wire(saddr, ifname, use_via);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::handle_solicit(const address& saddr, const address& taddr, const std::string& ifname)
|
||||||
|
{
|
||||||
|
logger::debug()
|
||||||
|
<< "proxy::handle_solicit()";
|
||||||
|
|
||||||
|
// Otherwise find or create a session to scan for this address
|
||||||
|
ptr<session> se = find_or_create_session(taddr);
|
||||||
|
if (!se) return;
|
||||||
|
|
||||||
|
// Touching the session will cause an NDP advert to be transmitted to all
|
||||||
|
// the daughters
|
||||||
|
se->touch();
|
||||||
|
|
||||||
|
// If our session is confirmed then we can respoond with an advert otherwise
|
||||||
|
// subscribe so that if it does become active we can notify everyone
|
||||||
|
if (saddr != taddr) {
|
||||||
|
switch (se->status()) {
|
||||||
|
case session::WAITING:
|
||||||
|
case session::INVALID:
|
||||||
|
se->add_pending(saddr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case session::VALID:
|
||||||
|
case session::RENEWING:
|
||||||
|
se->send_advert(saddr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr<rule> proxy::add_rule(const address& addr, const ptr<iface>& ifa, bool autovia)
|
||||||
{
|
{
|
||||||
ptr<rule> ru(rule::create(_ptr, addr, ifa));
|
ptr<rule> ru(rule::create(_ptr, addr, ifa));
|
||||||
|
ru->autovia(autovia);
|
||||||
_rules.push_back(ru);
|
_rules.push_back(ru);
|
||||||
return ru;
|
return ru;
|
||||||
}
|
}
|
||||||
@ -157,6 +232,16 @@ ptr<rule> proxy::add_rule(const address& addr, bool aut)
|
|||||||
return ru;
|
return ru;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<ptr<rule> >::iterator proxy::rules_begin()
|
||||||
|
{
|
||||||
|
return _rules.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<ptr<rule> >::iterator proxy::rules_end()
|
||||||
|
{
|
||||||
|
return _rules.end();
|
||||||
|
}
|
||||||
|
|
||||||
void proxy::remove_session(const ptr<session>& se)
|
void proxy::remove_session(const ptr<session>& se)
|
||||||
{
|
{
|
||||||
_sessions.remove(se);
|
_sessions.remove(se);
|
||||||
@ -167,6 +252,11 @@ const ptr<iface>& proxy::ifa() const
|
|||||||
return _ifa;
|
return _ifa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool proxy::promiscuous() const
|
||||||
|
{
|
||||||
|
return _promiscuous;
|
||||||
|
}
|
||||||
|
|
||||||
bool proxy::router() const
|
bool proxy::router() const
|
||||||
{
|
{
|
||||||
return _router;
|
return _router;
|
||||||
@ -177,6 +267,36 @@ void proxy::router(bool val)
|
|||||||
_router = val;
|
_router = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool proxy::autowire() const
|
||||||
|
{
|
||||||
|
return _autowire;
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::autowire(bool val)
|
||||||
|
{
|
||||||
|
_autowire = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int proxy::retries() const
|
||||||
|
{
|
||||||
|
return _retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::retries(int val)
|
||||||
|
{
|
||||||
|
_retries = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool proxy::keepalive() const
|
||||||
|
{
|
||||||
|
return _keepalive;
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::keepalive(bool val)
|
||||||
|
{
|
||||||
|
_keepalive = val;
|
||||||
|
}
|
||||||
|
|
||||||
int proxy::ttl() const
|
int proxy::ttl() const
|
||||||
{
|
{
|
||||||
return _ttl;
|
return _ttl;
|
||||||
@ -187,6 +307,16 @@ void proxy::ttl(int val)
|
|||||||
_ttl = (val >= 0) ? val : 30000;
|
_ttl = (val >= 0) ? val : 30000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int proxy::deadtime() const
|
||||||
|
{
|
||||||
|
return _deadtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::deadtime(int val)
|
||||||
|
{
|
||||||
|
_deadtime = (val >= 0) ? val : 30000;
|
||||||
|
}
|
||||||
|
|
||||||
int proxy::timeout() const
|
int proxy::timeout() const
|
||||||
{
|
{
|
||||||
return _timeout;
|
return _timeout;
|
||||||
|
53
src/proxy.h
53
src/proxy.h
@ -29,25 +29,50 @@ class iface;
|
|||||||
class rule;
|
class rule;
|
||||||
|
|
||||||
class proxy {
|
class proxy {
|
||||||
public:
|
public:
|
||||||
static ptr<proxy> create(const ptr<iface>& ifa);
|
static ptr<proxy> create(const ptr<iface>& ifa, bool promiscuous);
|
||||||
|
|
||||||
|
static ptr<proxy> find_aunt(const std::string& ifname, const address& taddr);
|
||||||
|
|
||||||
static ptr<proxy> open(const std::string& ifn);
|
static ptr<proxy> open(const std::string& ifn, bool promiscuous);
|
||||||
|
|
||||||
void handle_solicit(const address& saddr, const address& daddr,
|
ptr<session> find_or_create_session(const address& taddr);
|
||||||
const address& taddr);
|
|
||||||
|
void handle_advert(const address& saddr, const address& taddr, const std::string& ifname, bool use_via);
|
||||||
|
|
||||||
|
void handle_stateless_advert(const address& saddr, const address& taddr, const std::string& ifname, bool use_via);
|
||||||
|
|
||||||
|
void handle_solicit(const address& saddr, const address& taddr, const std::string& ifname);
|
||||||
|
|
||||||
void remove_session(const ptr<session>& se);
|
void remove_session(const ptr<session>& se);
|
||||||
|
|
||||||
ptr<rule> add_rule(const address& addr, const ptr<iface>& ifa);
|
ptr<rule> add_rule(const address& addr, const ptr<iface>& ifa, bool autovia);
|
||||||
|
|
||||||
ptr<rule> add_rule(const address& addr, bool aut = false);
|
ptr<rule> add_rule(const address& addr, bool aut = false);
|
||||||
|
|
||||||
|
std::list<ptr<rule> >::iterator rules_begin();
|
||||||
|
|
||||||
|
std::list<ptr<rule> >::iterator rules_end();
|
||||||
|
|
||||||
const ptr<iface>& ifa() const;
|
const ptr<iface>& ifa() const;
|
||||||
|
|
||||||
|
bool promiscuous() const;
|
||||||
|
|
||||||
bool router() const;
|
bool router() const;
|
||||||
|
|
||||||
void router(bool val);
|
void router(bool val);
|
||||||
|
|
||||||
|
bool autowire() const;
|
||||||
|
|
||||||
|
void autowire(bool val);
|
||||||
|
|
||||||
|
int retries() const;
|
||||||
|
|
||||||
|
void retries(int val);
|
||||||
|
|
||||||
|
bool keepalive() const;
|
||||||
|
|
||||||
|
void keepalive(bool val);
|
||||||
|
|
||||||
int timeout() const;
|
int timeout() const;
|
||||||
|
|
||||||
@ -56,6 +81,10 @@ public:
|
|||||||
int ttl() const;
|
int ttl() const;
|
||||||
|
|
||||||
void ttl(int val);
|
void ttl(int val);
|
||||||
|
|
||||||
|
int deadtime() const;
|
||||||
|
|
||||||
|
void deadtime(int val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::list<ptr<proxy> > _list;
|
static std::list<ptr<proxy> > _list;
|
||||||
@ -67,10 +96,18 @@ private:
|
|||||||
std::list<ptr<rule> > _rules;
|
std::list<ptr<rule> > _rules;
|
||||||
|
|
||||||
std::list<ptr<session> > _sessions;
|
std::list<ptr<session> > _sessions;
|
||||||
|
|
||||||
|
bool _promiscuous;
|
||||||
|
|
||||||
bool _router;
|
bool _router;
|
||||||
|
|
||||||
|
bool _autowire;
|
||||||
|
|
||||||
|
int _retries;
|
||||||
|
|
||||||
|
bool _keepalive;
|
||||||
|
|
||||||
int _ttl, _timeout;
|
int _ttl, _deadtime, _timeout;
|
||||||
|
|
||||||
proxy();
|
proxy();
|
||||||
};
|
};
|
||||||
|
@ -105,19 +105,19 @@ void route::load(const std::string& path)
|
|||||||
|
|
||||||
unsigned char pfx;
|
unsigned char pfx;
|
||||||
|
|
||||||
if (hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) {
|
if (route::hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) {
|
||||||
// TODO: Warn here?
|
// TODO: Warn here?
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hexdec(buf + 33,& pfx, 1) != 1) {
|
if (route::hexdec(buf + 33,& pfx, 1) != 1) {
|
||||||
// TODO: Warn here?
|
// TODO: Warn here?
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.prefix((int)pfx);
|
addr.prefix((int)pfx);
|
||||||
|
|
||||||
route::create(addr, token(buf + 141));
|
route::create(addr, route::token(buf + 141));
|
||||||
}
|
}
|
||||||
} catch (std::ifstream::failure e) {
|
} catch (std::ifstream::failure e) {
|
||||||
logger::warning() << "Failed to parse IPv6 routing data from '" << path << "'";
|
logger::warning() << "Failed to parse IPv6 routing data from '" << path << "'";
|
||||||
|
12
src/route.h
12
src/route.h
@ -44,6 +44,12 @@ public:
|
|||||||
const address& addr() const;
|
const address& addr() const;
|
||||||
|
|
||||||
ptr<iface> ifa();
|
ptr<iface> ifa();
|
||||||
|
|
||||||
|
route(const address& addr, const std::string& ifname);
|
||||||
|
|
||||||
|
static size_t hexdec(const char* str, unsigned char* buf, size_t size);
|
||||||
|
|
||||||
|
static std::string token(const char* str);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static int _ttl;
|
static int _ttl;
|
||||||
@ -56,14 +62,8 @@ private:
|
|||||||
|
|
||||||
ptr<iface> _ifa;
|
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;
|
static std::list<ptr<route> > _routes;
|
||||||
|
|
||||||
route(const address& addr, const std::string& ifname);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NDPPD_NS_END
|
NDPPD_NS_END
|
||||||
|
36
src/rule.cc
36
src/rule.cc
@ -29,6 +29,10 @@ std::vector<interface> interfaces;
|
|||||||
|
|
||||||
bool rule::_any_aut = false;
|
bool rule::_any_aut = false;
|
||||||
|
|
||||||
|
bool rule::_any_iface = false;
|
||||||
|
|
||||||
|
bool rule::_any_static = false;
|
||||||
|
|
||||||
rule::rule()
|
rule::rule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -38,9 +42,10 @@ ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, const ptr<ifac
|
|||||||
ptr<rule> ru(new rule());
|
ptr<rule> ru(new rule());
|
||||||
ru->_ptr = ru;
|
ru->_ptr = ru;
|
||||||
ru->_pr = pr;
|
ru->_pr = pr;
|
||||||
ru->_ifa = ifa;
|
ru->_daughter = ifa;
|
||||||
ru->_addr = addr;
|
ru->_addr = addr;
|
||||||
ru->_aut = false;
|
ru->_aut = false;
|
||||||
|
_any_iface = true;
|
||||||
unsigned int ifindex;
|
unsigned int ifindex;
|
||||||
|
|
||||||
ifindex = if_nametoindex(pr->ifa()->name().c_str());
|
ifindex = if_nametoindex(pr->ifa()->name().c_str());
|
||||||
@ -52,7 +57,7 @@ ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, const ptr<ifac
|
|||||||
if_add_to_list(ifindex, ifa);
|
if_add_to_list(ifindex, ifa);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
logger::debug() << "rule::create() if=" << pr->ifa()->name() << ", addr=" << addr;
|
logger::debug() << "rule::create() if=" << pr->ifa()->name() << ", slave=" << ifa->name() << ", addr=" << addr;
|
||||||
|
|
||||||
return ru;
|
return ru;
|
||||||
}
|
}
|
||||||
@ -65,6 +70,9 @@ ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, bool aut)
|
|||||||
ru->_addr = addr;
|
ru->_addr = addr;
|
||||||
ru->_aut = aut;
|
ru->_aut = aut;
|
||||||
_any_aut = _any_aut || aut;
|
_any_aut = _any_aut || aut;
|
||||||
|
|
||||||
|
if (aut == false)
|
||||||
|
_any_static = true;
|
||||||
|
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "rule::create() if=" << pr->ifa()->name().c_str() << ", addr=" << addr
|
<< "rule::create() if=" << pr->ifa()->name().c_str() << ", addr=" << addr
|
||||||
@ -78,9 +86,9 @@ const address& rule::addr() const
|
|||||||
return _addr;
|
return _addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<iface> rule::ifa() const
|
ptr<iface> rule::daughter() const
|
||||||
{
|
{
|
||||||
return _ifa;
|
return _daughter;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rule::is_auto() const
|
bool rule::is_auto() const
|
||||||
@ -88,11 +96,31 @@ bool rule::is_auto() const
|
|||||||
return _aut;
|
return _aut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rule::autovia() const
|
||||||
|
{
|
||||||
|
return _autovia;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rule::autovia(bool val)
|
||||||
|
{
|
||||||
|
_autovia = val;
|
||||||
|
}
|
||||||
|
|
||||||
bool rule::any_auto()
|
bool rule::any_auto()
|
||||||
{
|
{
|
||||||
return _any_aut;
|
return _any_aut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rule::any_iface()
|
||||||
|
{
|
||||||
|
return _any_iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rule::any_static()
|
||||||
|
{
|
||||||
|
return _any_static;
|
||||||
|
}
|
||||||
|
|
||||||
bool rule::check(const address& addr) const
|
bool rule::check(const address& addr) const
|
||||||
{
|
{
|
||||||
return _addr == addr;
|
return _addr == addr;
|
||||||
|
18
src/rule.h
18
src/rule.h
@ -37,26 +37,40 @@ public:
|
|||||||
|
|
||||||
const address& addr() const;
|
const address& addr() const;
|
||||||
|
|
||||||
ptr<iface> ifa() const;
|
ptr<iface> daughter() const;
|
||||||
|
|
||||||
bool is_auto() const;
|
bool is_auto() const;
|
||||||
|
|
||||||
bool check(const address& addr) const;
|
bool check(const address& addr) const;
|
||||||
|
|
||||||
static bool any_auto();
|
static bool any_auto();
|
||||||
|
|
||||||
|
static bool any_static();
|
||||||
|
|
||||||
|
static bool any_iface();
|
||||||
|
|
||||||
|
bool autovia() const;
|
||||||
|
|
||||||
|
void autovia(bool val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
weak_ptr<rule> _ptr;
|
weak_ptr<rule> _ptr;
|
||||||
|
|
||||||
weak_ptr<proxy> _pr;
|
weak_ptr<proxy> _pr;
|
||||||
|
|
||||||
ptr<iface> _ifa;
|
ptr<iface> _daughter;
|
||||||
|
|
||||||
address _addr;
|
address _addr;
|
||||||
|
|
||||||
bool _aut;
|
bool _aut;
|
||||||
|
|
||||||
static bool _any_aut;
|
static bool _any_aut;
|
||||||
|
|
||||||
|
static bool _any_static;
|
||||||
|
|
||||||
|
static bool _any_iface;
|
||||||
|
|
||||||
|
bool _autovia;
|
||||||
|
|
||||||
rule();
|
rule();
|
||||||
};
|
};
|
||||||
|
273
src/session.cc
273
src/session.cc
@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
#include "proxy.h"
|
#include "proxy.h"
|
||||||
@ -42,10 +43,54 @@ void session::update_all(int elapsed_time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (se->_status) {
|
switch (se->_status) {
|
||||||
|
|
||||||
case session::WAITING:
|
case session::WAITING:
|
||||||
logger::debug() << "session is now invalid";
|
if (se->_fails < se->_retries) {
|
||||||
se->_status = session::INVALID;
|
logger::debug() << "session will keep trying [taddr=" << se->_taddr << "]";
|
||||||
se->_ttl = se->_pr->ttl();
|
|
||||||
|
se->_ttl = se->_pr->timeout();
|
||||||
|
se->_fails++;
|
||||||
|
|
||||||
|
// Send another solicit
|
||||||
|
se->send_solicit();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
logger::debug() << "session is now invalid [taddr=" << se->_taddr << "]";
|
||||||
|
|
||||||
|
se->_status = session::INVALID;
|
||||||
|
se->_ttl = se->_pr->deadtime();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case session::RENEWING:
|
||||||
|
logger::debug() << "session is became invalid [taddr=" << se->_taddr << "]";
|
||||||
|
|
||||||
|
if (se->_fails < se->_retries) {
|
||||||
|
se->_ttl = se->_pr->timeout();
|
||||||
|
se->_fails++;
|
||||||
|
|
||||||
|
// Send another solicit
|
||||||
|
se->send_solicit();
|
||||||
|
} else {
|
||||||
|
se->_pr->remove_session(se);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case session::VALID:
|
||||||
|
if (se->touched() == true ||
|
||||||
|
se->keepalive() == true)
|
||||||
|
{
|
||||||
|
logger::debug() << "session is renewing [taddr=" << se->_taddr << "]";
|
||||||
|
se->_status = session::RENEWING;
|
||||||
|
se->_ttl = se->_pr->timeout();
|
||||||
|
se->_fails = 0;
|
||||||
|
se->_touched = false;
|
||||||
|
|
||||||
|
// Send another solicit to make sure the route is still valid
|
||||||
|
se->send_solicit();
|
||||||
|
} else {
|
||||||
|
se->_pr->remove_session(se);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -57,30 +102,34 @@ void session::update_all(int elapsed_time)
|
|||||||
session::~session()
|
session::~session()
|
||||||
{
|
{
|
||||||
logger::debug() << "session::~session() this=" << logger::format("%x", this);
|
logger::debug() << "session::~session() this=" << logger::format("%x", this);
|
||||||
|
|
||||||
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
if (_wired == true) {
|
||||||
|
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
||||||
it != _ifaces.end(); it++) {
|
it != _ifaces.end(); it++) {
|
||||||
(*it)->remove_session(_ptr);
|
handle_auto_unwire((*it)->name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<session> session::create(const ptr<proxy>& pr, const address& saddr,
|
ptr<session> session::create(const ptr<proxy>& pr, const address& taddr, bool auto_wire, bool keepalive, int retries)
|
||||||
const address& daddr, const address& taddr)
|
|
||||||
{
|
{
|
||||||
ptr<session> se(new session());
|
ptr<session> se(new session());
|
||||||
|
|
||||||
se->_ptr = se;
|
se->_ptr = se;
|
||||||
se->_pr = pr;
|
se->_pr = pr;
|
||||||
se->_saddr = address("::") == saddr ? all_nodes : saddr;
|
se->_taddr = taddr;
|
||||||
se->_taddr = taddr;
|
se->_autowire = auto_wire;
|
||||||
se->_daddr = daddr;
|
se->_keepalive = keepalive;
|
||||||
se->_ttl = pr->timeout();
|
se->_retries = retries;
|
||||||
|
se->_wired = false;
|
||||||
|
se->_ttl = pr->ttl();
|
||||||
|
se->_touched = false;
|
||||||
|
|
||||||
_sessions.push_back(se);
|
_sessions.push_back(se);
|
||||||
|
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "session::create() pr=" << logger::format("%x", (proxy* )pr) << ", saddr=" << saddr
|
<< "session::create() pr=" << logger::format("%x", (proxy* )pr) << ", proxy=" << ((pr->ifa()) ? pr->ifa()->name() : "null")
|
||||||
<< ", daddr=" << daddr << ", taddr=" << taddr << " =" << logger::format("%x", (session* )se);
|
<< ", taddr=" << taddr << " =" << logger::format("%x", (session* )se);
|
||||||
|
|
||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
@ -90,10 +139,19 @@ void session::add_iface(const ptr<iface>& ifa)
|
|||||||
if (std::find(_ifaces.begin(), _ifaces.end(), ifa) != _ifaces.end())
|
if (std::find(_ifaces.begin(), _ifaces.end(), ifa) != _ifaces.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ifa->add_session(_ptr);
|
|
||||||
_ifaces.push_back(ifa);
|
_ifaces.push_back(ifa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
void session::send_solicit()
|
void session::send_solicit()
|
||||||
{
|
{
|
||||||
logger::debug() << "session::send_solicit() (_ifaces.size() = " << _ifaces.size() << ")";
|
logger::debug() << "session::send_solicit() (_ifaces.size() = " << _ifaces.size() << ")";
|
||||||
@ -105,17 +163,162 @@ void session::send_solicit()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void session::send_advert()
|
void session::touch()
|
||||||
{
|
{
|
||||||
_pr->ifa()->write_advert(_saddr, _taddr, _pr->router());
|
if (_touched == false)
|
||||||
|
{
|
||||||
|
_touched = true;
|
||||||
|
|
||||||
|
if (status() == session::WAITING || status() == session::INVALID) {
|
||||||
|
_ttl = _pr->timeout();
|
||||||
|
|
||||||
|
logger::debug() << "session is now probing [taddr=" << _taddr << "]";
|
||||||
|
|
||||||
|
send_solicit();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session::send_advert(const address& daddr)
|
||||||
|
{
|
||||||
|
_pr->ifa()->write_advert(daddr, _taddr, _pr->router());
|
||||||
|
}
|
||||||
|
|
||||||
|
void session::handle_auto_wire(const address& saddr, const std::string& ifname, bool use_via)
|
||||||
|
{
|
||||||
|
if (_wired == true && (_wired_via.is_empty() || _wired_via == saddr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
logger::debug()
|
||||||
|
<< "session::handle_auto_wire() taddr=" << _taddr << ", ifname=" << ifname;
|
||||||
|
|
||||||
|
if (use_via == true &&
|
||||||
|
_taddr != saddr &&
|
||||||
|
saddr.is_unicast() == true &&
|
||||||
|
saddr.is_multicast() == false)
|
||||||
|
{
|
||||||
|
std::stringstream route_cmd;
|
||||||
|
route_cmd << "ip";
|
||||||
|
route_cmd << " " << "-6";
|
||||||
|
route_cmd << " " << "route";
|
||||||
|
route_cmd << " " << "replace";
|
||||||
|
route_cmd << " " << std::string(saddr);
|
||||||
|
route_cmd << " " << "dev";
|
||||||
|
route_cmd << " " << ifname;
|
||||||
|
|
||||||
|
logger::debug()
|
||||||
|
<< "session::system(" << route_cmd.str() << ")";
|
||||||
|
|
||||||
|
system(route_cmd.str().c_str());
|
||||||
|
|
||||||
|
_wired_via = saddr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_wired_via.reset();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::stringstream route_cmd;
|
||||||
|
route_cmd << "ip";
|
||||||
|
route_cmd << " " << "-6";
|
||||||
|
route_cmd << " " << "route";
|
||||||
|
route_cmd << " " << "replace";
|
||||||
|
route_cmd << " " << std::string(_taddr);
|
||||||
|
if (_wired_via.is_empty() == false) {
|
||||||
|
route_cmd << " " << "via";
|
||||||
|
route_cmd << " " << std::string(_wired_via);
|
||||||
|
}
|
||||||
|
route_cmd << " " << "dev";
|
||||||
|
route_cmd << " " << ifname;
|
||||||
|
|
||||||
|
logger::debug()
|
||||||
|
<< "session::system(" << route_cmd.str() << ")";
|
||||||
|
|
||||||
|
system(route_cmd.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
_wired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void session::handle_auto_unwire(const std::string& ifname)
|
||||||
|
{
|
||||||
|
logger::debug()
|
||||||
|
<< "session::handle_auto_unwire() taddr=" << _taddr << ", ifname=" << ifname;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::stringstream route_cmd;
|
||||||
|
route_cmd << "ip";
|
||||||
|
route_cmd << " " << "-6";
|
||||||
|
route_cmd << " " << "route";
|
||||||
|
route_cmd << " " << "flush";
|
||||||
|
route_cmd << " " << std::string(_taddr);
|
||||||
|
if (_wired_via.is_empty() == false) {
|
||||||
|
route_cmd << " " << "via";
|
||||||
|
route_cmd << " " << std::string(_wired_via);
|
||||||
|
}
|
||||||
|
route_cmd << " " << "dev";
|
||||||
|
route_cmd << " " << ifname;
|
||||||
|
|
||||||
|
logger::debug()
|
||||||
|
<< "session::system(" << route_cmd.str() << ")";
|
||||||
|
|
||||||
|
system(route_cmd.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_wired_via.is_empty() == false) {
|
||||||
|
std::stringstream route_cmd;
|
||||||
|
route_cmd << "ip";
|
||||||
|
route_cmd << " " << "-6";
|
||||||
|
route_cmd << " " << "route";
|
||||||
|
route_cmd << " " << "flush";
|
||||||
|
route_cmd << " " << std::string(_wired_via);
|
||||||
|
route_cmd << " " << "dev";
|
||||||
|
route_cmd << " " << ifname;
|
||||||
|
|
||||||
|
logger::debug()
|
||||||
|
<< "session::system(" << route_cmd.str() << ")";
|
||||||
|
|
||||||
|
system(route_cmd.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
_wired = false;
|
||||||
|
_wired_via.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void session::handle_advert(const address& saddr, const std::string& ifname, bool use_via)
|
||||||
|
{
|
||||||
|
if (_autowire == true && _status == WAITING) {
|
||||||
|
handle_auto_wire(saddr, ifname, use_via);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_advert();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void session::handle_advert()
|
void session::handle_advert()
|
||||||
{
|
{
|
||||||
_status = VALID;
|
logger::debug()
|
||||||
|
<< "session::handle_advert() taddr=" << _taddr << ", ttl=" << _pr->ttl();
|
||||||
|
|
||||||
|
if (_status != VALID) {
|
||||||
|
_status = VALID;
|
||||||
|
|
||||||
|
logger::debug() << "session is active [taddr=" << _taddr << "]";
|
||||||
|
}
|
||||||
|
|
||||||
_ttl = _pr->ttl();
|
_ttl = _pr->ttl();
|
||||||
|
_fails = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
send_advert();
|
send_advert(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pending.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const address& session::taddr() const
|
const address& session::taddr() const
|
||||||
@ -123,14 +326,34 @@ const address& session::taddr() const
|
|||||||
return _taddr;
|
return _taddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const address& session::saddr() const
|
bool session::autowire() const
|
||||||
{
|
{
|
||||||
return _saddr;
|
return _autowire;
|
||||||
}
|
}
|
||||||
|
|
||||||
const address& session::daddr() const
|
bool session::keepalive() const
|
||||||
{
|
{
|
||||||
return _daddr;
|
return _keepalive;
|
||||||
|
}
|
||||||
|
|
||||||
|
int session::retries() const
|
||||||
|
{
|
||||||
|
return _retries;
|
||||||
|
}
|
||||||
|
|
||||||
|
int session::fails() const
|
||||||
|
{
|
||||||
|
return _fails;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool session::wired() const
|
||||||
|
{
|
||||||
|
return _wired;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool session::touched() const
|
||||||
|
{
|
||||||
|
return _touched;
|
||||||
}
|
}
|
||||||
|
|
||||||
int session::status() const
|
int session::status() const
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
|
|
||||||
@ -31,14 +32,30 @@ private:
|
|||||||
weak_ptr<proxy> _pr;
|
weak_ptr<proxy> _pr;
|
||||||
|
|
||||||
address _saddr, _daddr, _taddr;
|
address _saddr, _daddr, _taddr;
|
||||||
|
|
||||||
|
bool _autowire;
|
||||||
|
|
||||||
|
bool _keepalive;
|
||||||
|
|
||||||
|
bool _wired;
|
||||||
|
|
||||||
|
address _wired_via;
|
||||||
|
|
||||||
|
bool _touched;
|
||||||
|
|
||||||
// An array of interfaces this session is monitoring for
|
// An array of interfaces this session is monitoring for
|
||||||
// ND_NEIGHBOR_ADVERT on.
|
// ND_NEIGHBOR_ADVERT on.
|
||||||
std::list<ptr<iface> > _ifaces;
|
std::list<ptr<iface> > _ifaces;
|
||||||
|
|
||||||
|
std::list<ptr<address> > _pending;
|
||||||
|
|
||||||
// The remaining time in miliseconds the object will stay in the
|
// The remaining time in miliseconds the object will stay in the
|
||||||
// interface's session array or cache.
|
// interface's session array or cache.
|
||||||
int _ttl;
|
int _ttl;
|
||||||
|
|
||||||
|
int _fails;
|
||||||
|
|
||||||
|
int _retries;
|
||||||
|
|
||||||
int _status;
|
int _status;
|
||||||
|
|
||||||
@ -47,9 +64,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
WAITING, // Waiting for an advert response.
|
WAITING, // Waiting for an advert response.
|
||||||
VALID, // Valid;
|
RENEWING, // Renewing;
|
||||||
INVALID // Invalid;
|
VALID, // Valid;
|
||||||
|
INVALID // Invalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void update_all(int elapsed_time);
|
static void update_all(int elapsed_time);
|
||||||
@ -57,24 +75,45 @@ public:
|
|||||||
// Destructor.
|
// Destructor.
|
||||||
~session();
|
~session();
|
||||||
|
|
||||||
static ptr<session> create(const ptr<proxy>& pr, const address& saddr,
|
static ptr<session> create(const ptr<proxy>& pr, const address& taddr, bool autowire, bool keepalive, int retries);
|
||||||
const address& daddr, const address& taddr);
|
|
||||||
|
|
||||||
void add_iface(const ptr<iface>& ifa);
|
void add_iface(const ptr<iface>& ifa);
|
||||||
|
|
||||||
|
void add_pending(const address& addr);
|
||||||
|
|
||||||
const address& taddr() const;
|
const address& taddr() const;
|
||||||
|
|
||||||
const address& daddr() const;
|
const address& daddr() const;
|
||||||
|
|
||||||
const address& saddr() const;
|
const address& saddr() const;
|
||||||
|
|
||||||
|
bool autowire() const;
|
||||||
|
|
||||||
|
int retries() const;
|
||||||
|
|
||||||
|
int fails() const;
|
||||||
|
|
||||||
|
bool keepalive() const;
|
||||||
|
|
||||||
|
bool wired() const;
|
||||||
|
|
||||||
|
bool touched() const;
|
||||||
|
|
||||||
int status() const;
|
int status() const;
|
||||||
|
|
||||||
void status(int val);
|
void status(int val);
|
||||||
|
|
||||||
void handle_advert();
|
void handle_advert();
|
||||||
|
|
||||||
void send_advert();
|
void handle_advert(const address& saddr, const std::string& ifname, bool use_via);
|
||||||
|
|
||||||
|
void handle_auto_wire(const address& saddr, const std::string& ifname, bool use_via);
|
||||||
|
|
||||||
|
void handle_auto_unwire(const std::string& ifname);
|
||||||
|
|
||||||
|
void touch();
|
||||||
|
|
||||||
|
void send_advert(const address& daddr);
|
||||||
|
|
||||||
void send_solicit();
|
void send_solicit();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user