Doing some debugging on an issue with the routes not working from gateway hosted IPs
This commit is contained in:
parent
4ca86ef88e
commit
a008fad5f4
@ -91,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).
|
||||||
|
@ -132,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;
|
||||||
@ -321,6 +336,10 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +379,8 @@ void address::load(const std::string& path)
|
|||||||
ifs.getline(buf, sizeof(buf));
|
ifs.getline(buf, sizeof(buf));
|
||||||
|
|
||||||
if (ifs.gcount() < 53) {
|
if (ifs.gcount() < 53) {
|
||||||
logger::debug() << "skipping entry (size=" << ifs.gcount() << ")";
|
if (ifs.gcount() > 0)
|
||||||
|
logger::debug() << "skipping entry (size=" << ifs.gcount() << ")";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,8 @@ public:
|
|||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
bool is_empty() const;
|
||||||
|
|
||||||
const std::string to_string() const;
|
const std::string to_string() const;
|
||||||
|
|
||||||
bool parse_string(const std::string& str);
|
bool parse_string(const std::string& str);
|
||||||
|
250
src/iface.cc
250
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
|
||||||
|
|
||||||
@ -72,6 +73,9 @@ iface::~iface()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_map_dirty = true;
|
_map_dirty = true;
|
||||||
|
|
||||||
|
_serves.clear();
|
||||||
|
_parents.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<iface> iface::open_pfd(const std::string& name, bool promiscuous)
|
ptr<iface> iface::open_pfd(const std::string& name, bool promiscuous)
|
||||||
@ -297,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;
|
||||||
@ -311,18 +315,18 @@ 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;
|
||||||
|
|
||||||
logger::debug() << "iface::read() ifa=" << name() << ", len=" << len;
|
|
||||||
|
|
||||||
if ((len = recvmsg(fd,& mhdr, 0)) < 0)
|
if ((len = recvmsg(fd,& mhdr, 0)) < 0)
|
||||||
{
|
{
|
||||||
logger::error() << "iface::read() failed! error=" << logger::err() << ", ifa=" << name();
|
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;
|
||||||
|
|
||||||
@ -369,7 +373,7 @@ 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();
|
logger::warning() << "iface::read_solicit() failed: " << logger::err();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -384,6 +388,11 @@ ssize_t iface::read_solicit(address& saddr, address& daddr, address& taddr)
|
|||||||
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() << ", taddr=" << taddr.to_string() << ", len=" << len;
|
<< ", daddr=" << daddr.to_string() << ", taddr=" << taddr.to_string() << ", len=" << len;
|
||||||
|
|
||||||
@ -466,13 +475,22 @@ ssize_t iface::read_advert(address& saddr, address& taddr)
|
|||||||
uint8_t msg[256];
|
uint8_t msg[256];
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
if ((len = read(_ifd, (struct sockaddr* )&t_saddr, msg, sizeof(msg))) < 0) {
|
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, sizeof(struct sockaddr_in6), msg, sizeof(msg))) < 0) {
|
||||||
logger::warning() << "iface::read_advert() failed: " << logger::err();
|
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;
|
||||||
|
|
||||||
@ -483,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);
|
||||||
@ -505,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();
|
||||||
@ -579,58 +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
|
||||||
{
|
if (ifa->handle_local(saddr, taddr) == true) {
|
||||||
// Setup the reverse path
|
continue;
|
||||||
if (saddr.is_unicast()) {
|
}
|
||||||
ptr<session> se = ifa->_pr->find_or_create_session(saddr);
|
|
||||||
if (se) {
|
|
||||||
se->add_iface(ifa);
|
|
||||||
se->handle_advert(ifa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now process the solicit
|
// We have to handle all the parents who may be interested in
|
||||||
ifa->_pr->handle_solicit(saddr, taddr);
|
// 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) {
|
||||||
bool found = false;
|
logger::debug() << "iface::read_advert() loopback received and ignored";
|
||||||
for (std::list<weak_ptr<session> >::iterator s_it = ifa->_sessions.begin();
|
continue;
|
||||||
s_it != ifa->_sessions.end(); s_it++) {
|
|
||||||
assert(!s_it->is_null());
|
|
||||||
|
|
||||||
const ptr<session> sess = *s_it;
|
|
||||||
|
|
||||||
if ((sess->taddr() == taddr)) {
|
|
||||||
sess->handle_advert(ifa);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found == false) {
|
// Process the NDP advert
|
||||||
if (ifa->owner()) {
|
bool handled = false;
|
||||||
ifa->owner()->handle_advert(taddr, ifa);
|
for (std::list<weak_ptr<proxy> >::iterator pit = ifa->parents_begin(); pit != ifa->parents_end(); pit++) {
|
||||||
} else {
|
ptr<proxy> pr = (*pit);
|
||||||
logger::debug() << "iface::poll_all - ignoring advert on proxy iface=" << ifa->name();
|
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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -721,24 +833,34 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
void iface::owner(const ptr<proxy>& pr)
|
std::list<weak_ptr<proxy> >::iterator iface::serves_end()
|
||||||
{
|
{
|
||||||
_owner = pr;
|
return _serves.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ptr<proxy>& iface::owner() const
|
void iface::add_parent(const ptr<proxy>& pr)
|
||||||
{
|
{
|
||||||
return _owner;
|
_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
|
||||||
|
32
src/iface.h
32
src/iface.h
@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
static int poll_all();
|
static int poll_all();
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -58,24 +58,30 @@ 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);
|
|
||||||
|
|
||||||
void remove_session(const ptr<session>& se);
|
std::list<weak_ptr<proxy> >::iterator serves_end();
|
||||||
|
|
||||||
void pr(const ptr<proxy>& pr);
|
void add_serves(const ptr<proxy>& proxy);
|
||||||
|
|
||||||
const ptr<proxy>& pr() const;
|
std::list<weak_ptr<proxy> >::iterator parents_begin();
|
||||||
|
|
||||||
void owner(const ptr<proxy>& pr);
|
std::list<weak_ptr<proxy> >::iterator parents_end();
|
||||||
|
|
||||||
const ptr<proxy>& owner() const;
|
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;
|
||||||
|
|
||||||
@ -107,13 +113,9 @@ private:
|
|||||||
// 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;
|
|
||||||
|
|
||||||
weak_ptr<proxy> _pr;
|
std::list<weak_ptr<proxy> > _parents;
|
||||||
|
|
||||||
weak_ptr<proxy> _owner;
|
|
||||||
|
|
||||||
// The link-layer address of this interface.
|
// The link-layer address of this interface.
|
||||||
struct ether_addr hwaddr;
|
struct ether_addr hwaddr;
|
||||||
|
57
src/ndppd.cc
57
src/ndppd.cc
@ -147,6 +147,8 @@ static bool configure(ptr<conf>& cf)
|
|||||||
else
|
else
|
||||||
address::ttl(*x_cf);
|
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;
|
||||||
|
|
||||||
std::vector<ptr<conf> > proxies(cf->find_all("proxy"));
|
std::vector<ptr<conf> > proxies(cf->find_all("proxy"));
|
||||||
@ -213,23 +215,70 @@ static bool configure(ptr<conf>& cf)
|
|||||||
|
|
||||||
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"))
|
||||||
{
|
{
|
||||||
ptr<iface> ifa = iface::open_ifd(*x_cf);
|
ptr<iface> ifa = iface::open_ifd(*x_cf);
|
||||||
if (!ifa || ifa.is_null() == true) {
|
if (!ifa || ifa.is_null() == true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ifa->owner(pr);
|
|
||||||
|
|
||||||
pr->add_rule(addr, ifa);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
121
src/proxy.cc
121
src/proxy.cc
@ -36,6 +36,34 @@ proxy::proxy() :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> proxy::create(const ptr<iface>& ifa, bool promiscuous)
|
||||||
{
|
{
|
||||||
ptr<proxy> pr(new proxy());
|
ptr<proxy> pr(new proxy());
|
||||||
@ -45,7 +73,7 @@ ptr<proxy> proxy::create(const ptr<iface>& ifa, bool 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();
|
||||||
|
|
||||||
@ -99,11 +127,11 @@ ptr<session> proxy::find_or_create_session(const address& taddr)
|
|||||||
} 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();
|
||||||
@ -111,7 +139,7 @@ ptr<session> proxy::find_or_create_session(const address& taddr)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ptr<iface> ifa = (*it)->ifa();
|
ptr<iface> ifa = ru->daughter();
|
||||||
se->add_iface(ifa);
|
se->add_iface(ifa);
|
||||||
|
|
||||||
#ifdef WITH_ND_NETLINK
|
#ifdef WITH_ND_NETLINK
|
||||||
@ -132,64 +160,67 @@ ptr<session> proxy::find_or_create_session(const address& taddr)
|
|||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
|
|
||||||
void proxy::handle_advert(const address& taddr, const ptr<iface>& receiver)
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void proxy::handle_stateless_advert(const address& saddr, const address& taddr, const std::string& ifname, bool use_via)
|
||||||
{
|
{
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "proxy::handle_advert() proxy=" << (ifa() ? ifa()->name() : "null") << ", receiver=" << (receiver ? receiver->name() : "null");
|
<< "proxy::handle_stateless_advert() proxy=" << (ifa() ? ifa()->name() : "null") << ", taddr=" << taddr.to_string() << ", ifname=" << ifname;
|
||||||
|
|
||||||
ptr<session> se = find_or_create_session(taddr);
|
ptr<session> se = find_or_create_session(taddr);
|
||||||
if (!se) return;
|
if (!se) return;
|
||||||
|
|
||||||
se->handle_advert(receiver);
|
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)
|
void proxy::handle_solicit(const address& saddr, const address& taddr, const std::string& ifname)
|
||||||
{
|
{
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "proxy::handle_solicit() ifa=" << ((_ifa) ? _ifa->name() : "null");
|
<< "proxy::handle_solicit()";
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
for (std::list<ptr<rule> >::iterator it = _rules.begin(); it != _rules.end(); it++) {
|
|
||||||
ptr<rule> ru = *it;
|
|
||||||
|
|
||||||
if (ru->ifa() && ru->ifa()->name() == (*ad)->ifname())
|
|
||||||
{
|
|
||||||
logger::debug() << "proxy::handle_solicit() found local taddr=" << taddr;
|
|
||||||
|
|
||||||
if (_ifa)
|
|
||||||
_ifa->write_advert(saddr, taddr, router());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise find or create a session to scan for this address
|
// Otherwise find or create a session to scan for this address
|
||||||
ptr<session> se = find_or_create_session(taddr);
|
ptr<session> se = find_or_create_session(taddr);
|
||||||
if (!se) return;
|
if (!se) return;
|
||||||
|
|
||||||
|
// Touching the session will cause an NDP advert to be transmitted to all
|
||||||
|
// the daughters
|
||||||
se->touch();
|
se->touch();
|
||||||
|
|
||||||
switch (se->status()) {
|
// If our session is confirmed then we can respoond with an advert otherwise
|
||||||
case session::WAITING:
|
// subscribe so that if it does become active we can notify everyone
|
||||||
case session::INVALID:
|
if (saddr != taddr) {
|
||||||
se->add_pending(saddr);
|
switch (se->status()) {
|
||||||
|
case session::WAITING:
|
||||||
|
case session::INVALID:
|
||||||
|
se->add_pending(saddr);
|
||||||
|
break;
|
||||||
|
|
||||||
case session::VALID:
|
case session::VALID:
|
||||||
case session::RENEWING:
|
case session::RENEWING:
|
||||||
se->send_advert(saddr);
|
se->send_advert(saddr);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<rule> proxy::add_rule(const address& addr, const ptr<iface>& ifa)
|
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;
|
||||||
}
|
}
|
||||||
@ -201,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);
|
||||||
|
14
src/proxy.h
14
src/proxy.h
@ -32,20 +32,28 @@ class proxy {
|
|||||||
public:
|
public:
|
||||||
static ptr<proxy> create(const ptr<iface>& ifa, bool promiscuous);
|
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, bool promiscuous);
|
static ptr<proxy> open(const std::string& ifn, bool promiscuous);
|
||||||
|
|
||||||
ptr<session> find_or_create_session(const address& taddr);
|
ptr<session> find_or_create_session(const address& taddr);
|
||||||
|
|
||||||
void handle_advert(const address& taddr, const ptr<iface>& receiver);
|
void handle_advert(const address& saddr, const address& taddr, const std::string& ifname, bool use_via);
|
||||||
|
|
||||||
void handle_solicit(const address& saddr, const address& taddr);
|
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 promiscuous() const;
|
||||||
|
26
src/rule.cc
26
src/rule.cc
@ -31,6 +31,8 @@ bool rule::_any_aut = false;
|
|||||||
|
|
||||||
bool rule::_any_iface = false;
|
bool rule::_any_iface = false;
|
||||||
|
|
||||||
|
bool rule::_any_static = false;
|
||||||
|
|
||||||
rule::rule()
|
rule::rule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -40,7 +42,7 @@ 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;
|
_any_iface = true;
|
||||||
@ -69,6 +71,9 @@ ptr<rule> rule::create(const ptr<proxy>& pr, const address& addr, bool aut)
|
|||||||
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
|
||||||
<< ", auto=" << (aut ? "yes" : "no");
|
<< ", auto=" << (aut ? "yes" : "no");
|
||||||
@ -81,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
|
||||||
@ -91,6 +96,16 @@ 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;
|
||||||
@ -101,6 +116,11 @@ bool rule::any_iface()
|
|||||||
return _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;
|
||||||
|
14
src/rule.h
14
src/rule.h
@ -37,7 +37,7 @@ 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;
|
||||||
|
|
||||||
@ -45,14 +45,20 @@ public:
|
|||||||
|
|
||||||
static bool any_auto();
|
static bool any_auto();
|
||||||
|
|
||||||
|
static bool any_static();
|
||||||
|
|
||||||
static bool any_iface();
|
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;
|
||||||
|
|
||||||
@ -60,8 +66,12 @@ private:
|
|||||||
|
|
||||||
static bool _any_aut;
|
static bool _any_aut;
|
||||||
|
|
||||||
|
static bool _any_static;
|
||||||
|
|
||||||
static bool _any_iface;
|
static bool _any_iface;
|
||||||
|
|
||||||
|
bool _autovia;
|
||||||
|
|
||||||
rule();
|
rule();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
143
src/session.cc
143
src/session.cc
@ -45,15 +45,18 @@ 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 [taddr=" << se->_taddr << "]";
|
|
||||||
|
|
||||||
if (se->_fails < se->_retries) {
|
if (se->_fails < se->_retries) {
|
||||||
|
logger::debug() << "session will keep trying [taddr=" << se->_taddr << "]";
|
||||||
|
|
||||||
se->_ttl = se->_pr->timeout();
|
se->_ttl = se->_pr->timeout();
|
||||||
se->_fails++;
|
se->_fails++;
|
||||||
|
|
||||||
// Send another solicit
|
// Send another solicit
|
||||||
se->send_solicit();
|
se->send_solicit();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
logger::debug() << "session is now invalid [taddr=" << se->_taddr << "]";
|
||||||
|
|
||||||
se->_status = session::INVALID;
|
se->_status = session::INVALID;
|
||||||
se->_ttl = se->_pr->deadtime();
|
se->_ttl = se->_pr->deadtime();
|
||||||
}
|
}
|
||||||
@ -103,15 +106,9 @@ session::~session()
|
|||||||
if (_wired == true) {
|
if (_wired == true) {
|
||||||
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
||||||
it != _ifaces.end(); it++) {
|
it != _ifaces.end(); it++) {
|
||||||
handle_auto_unwire((*it));
|
handle_auto_unwire((*it)->name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::list<ptr<iface> >::iterator it = _ifaces.begin();
|
|
||||||
it != _ifaces.end(); it++)
|
|
||||||
{
|
|
||||||
(*it)->remove_session(_ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr<session> session::create(const ptr<proxy>& pr, const address& taddr, bool auto_wire, bool keepalive, int retries)
|
ptr<session> session::create(const ptr<proxy>& pr, const address& taddr, bool auto_wire, bool keepalive, int retries)
|
||||||
@ -125,7 +122,7 @@ ptr<session> session::create(const ptr<proxy>& pr, const address& taddr, bool au
|
|||||||
se->_keepalive = keepalive;
|
se->_keepalive = keepalive;
|
||||||
se->_retries = retries;
|
se->_retries = retries;
|
||||||
se->_wired = false;
|
se->_wired = false;
|
||||||
se->_ttl = pr->timeout();
|
se->_ttl = pr->ttl();
|
||||||
se->_touched = false;
|
se->_touched = false;
|
||||||
|
|
||||||
_sessions.push_back(se);
|
_sessions.push_back(se);
|
||||||
@ -142,7 +139,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,8 +169,13 @@ void session::touch()
|
|||||||
{
|
{
|
||||||
_touched = true;
|
_touched = true;
|
||||||
|
|
||||||
if (status() == session::WAITING || status() == session::INVALID)
|
if (status() == session::WAITING || status() == session::INVALID) {
|
||||||
|
_ttl = _pr->timeout();
|
||||||
|
|
||||||
|
logger::debug() << "session is now probing [taddr=" << _taddr << "]";
|
||||||
|
|
||||||
send_solicit();
|
send_solicit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,57 +184,110 @@ void session::send_advert(const address& daddr)
|
|||||||
_pr->ifa()->write_advert(daddr, _taddr, _pr->router());
|
_pr->ifa()->write_advert(daddr, _taddr, _pr->router());
|
||||||
}
|
}
|
||||||
|
|
||||||
void session::handle_auto_wire(const ptr<iface>& ifa)
|
void session::handle_auto_wire(const address& saddr, const std::string& ifname, bool use_via)
|
||||||
{
|
{
|
||||||
if (_wired == true)
|
if (_wired == true && (_wired_via.is_empty() || _wired_via == saddr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "session::handle_auto_wire() taddr=" << _taddr << ", ifa=" << ifa->name();
|
<< "session::handle_auto_wire() taddr=" << _taddr << ", ifname=" << ifname;
|
||||||
|
|
||||||
std::stringstream route_cmd;
|
if (use_via == true &&
|
||||||
route_cmd << "ip";
|
_taddr != saddr &&
|
||||||
route_cmd << " " << "-6";
|
saddr.is_unicast() == true &&
|
||||||
route_cmd << " " << "route";
|
saddr.is_multicast() == false)
|
||||||
route_cmd << " " << "replace";
|
{
|
||||||
route_cmd << " " << std::string(_taddr);
|
std::stringstream route_cmd;
|
||||||
route_cmd << " " << "dev";
|
route_cmd << "ip";
|
||||||
route_cmd << " " << ifa->name();
|
route_cmd << " " << "-6";
|
||||||
|
route_cmd << " " << "route";
|
||||||
|
route_cmd << " " << "replace";
|
||||||
|
route_cmd << " " << std::string(saddr);
|
||||||
|
route_cmd << " " << "dev";
|
||||||
|
route_cmd << " " << ifname;
|
||||||
|
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "session::system(" << route_cmd.str() << ")";
|
<< "session::system(" << route_cmd.str() << ")";
|
||||||
|
|
||||||
system(route_cmd.str().c_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;
|
_wired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void session::handle_auto_unwire(const ptr<iface>& ifa)
|
void session::handle_auto_unwire(const std::string& ifname)
|
||||||
{
|
{
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "session::handle_auto_unwire() taddr=" << _taddr << ", ifa=" << ifa->name();
|
<< "session::handle_auto_unwire() taddr=" << _taddr << ", ifname=" << ifname;
|
||||||
|
|
||||||
std::stringstream route_cmd;
|
{
|
||||||
route_cmd << "ip";
|
std::stringstream route_cmd;
|
||||||
route_cmd << " " << "-6";
|
route_cmd << "ip";
|
||||||
route_cmd << " " << "route";
|
route_cmd << " " << "-6";
|
||||||
route_cmd << " " << "flush";
|
route_cmd << " " << "route";
|
||||||
route_cmd << " " << std::string(_taddr);
|
route_cmd << " " << "flush";
|
||||||
route_cmd << " " << "dev";
|
route_cmd << " " << std::string(_taddr);
|
||||||
route_cmd << " " << ifa->name();
|
if (_wired_via.is_empty() == false) {
|
||||||
|
route_cmd << " " << "via";
|
||||||
|
route_cmd << " " << std::string(_wired_via);
|
||||||
|
}
|
||||||
|
route_cmd << " " << "dev";
|
||||||
|
route_cmd << " " << ifname;
|
||||||
|
|
||||||
logger::debug()
|
logger::debug()
|
||||||
<< "session::system(" << route_cmd.str() << ")";
|
<< "session::system(" << route_cmd.str() << ")";
|
||||||
|
|
||||||
system(route_cmd.str().c_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 = false;
|
||||||
|
_wired_via.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void session::handle_advert(const ptr<iface>& ifa)
|
void session::handle_advert(const address& saddr, const std::string& ifname, bool use_via)
|
||||||
{
|
{
|
||||||
if (_autowire == true && _status == WAITING) {
|
if (_autowire == true && _status == WAITING) {
|
||||||
handle_auto_wire(ifa);
|
handle_auto_wire(saddr, ifname, use_via);
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_advert();
|
handle_advert();
|
||||||
@ -245,7 +299,12 @@ void session::handle_advert()
|
|||||||
logger::debug()
|
logger::debug()
|
||||||
<< "session::handle_advert() taddr=" << _taddr << ", ttl=" << _pr->ttl();
|
<< "session::handle_advert() taddr=" << _taddr << ", ttl=" << _pr->ttl();
|
||||||
|
|
||||||
_status = VALID;
|
if (_status != VALID) {
|
||||||
|
_status = VALID;
|
||||||
|
|
||||||
|
logger::debug() << "session is active [taddr=" << _taddr << "]";
|
||||||
|
}
|
||||||
|
|
||||||
_ttl = _pr->ttl();
|
_ttl = _pr->ttl();
|
||||||
_fails = 0;
|
_fails = 0;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "ndppd.h"
|
#include "ndppd.h"
|
||||||
|
|
||||||
@ -38,6 +39,8 @@ private:
|
|||||||
|
|
||||||
bool _wired;
|
bool _wired;
|
||||||
|
|
||||||
|
address _wired_via;
|
||||||
|
|
||||||
bool _touched;
|
bool _touched;
|
||||||
|
|
||||||
// An array of interfaces this session is monitoring for
|
// An array of interfaces this session is monitoring for
|
||||||
@ -102,11 +105,11 @@ public:
|
|||||||
|
|
||||||
void handle_advert();
|
void handle_advert();
|
||||||
|
|
||||||
void handle_advert(const ptr<iface>& ifa);
|
void handle_advert(const address& saddr, const std::string& ifname, bool use_via);
|
||||||
|
|
||||||
void handle_auto_wire(const ptr<iface>& ifa);
|
void handle_auto_wire(const address& saddr, const std::string& ifname, bool use_via);
|
||||||
|
|
||||||
void handle_auto_unwire(const ptr<iface>& ifa);
|
void handle_auto_unwire(const std::string& ifname);
|
||||||
|
|
||||||
void touch();
|
void touch();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user