NDP proxy will now respond to Solicitation requests to gateway addresses that it holds on secondary interfaces

This commit is contained in:
John Sharratt 2017-07-03 20:12:36 +02:00
parent a690d128e7
commit 1f50dc5b5a
3 changed files with 65 additions and 13 deletions

View File

@ -318,9 +318,14 @@ void address::add(const address& addr, const std::string& ifname)
_addresses.push_back(rt);
}
std::list<ptr<route> > address::addresses()
std::list<ptr<route> >::iterator address::addresses_begin()
{
return _addresses;
return _addresses.begin();
}
std::list<ptr<route> >::iterator address::addresses_end()
{
return _addresses.end();
}
void address::load(const std::string& path)
@ -342,24 +347,31 @@ void address::load(const std::string& path)
ifs.getline(buf, sizeof(buf));
if (ifs.gcount() < 53) {
logger::debug() << "skipping entry (size=" << ifs.gcount() << ")";
continue;
}
address addr;
if (route::hexdec(buf, (unsigned char* )&addr.addr(), 32) != 32) {
// TODO: Warn here?
if (route::hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) {
logger::warning() << "failed to load address (" << buf << ")";
continue;
}
addr.prefix(128);
address::add(addr, route::token(buf + 45));
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)

View File

@ -70,12 +70,14 @@ public:
operator std::string() const;
static std::list<ptr<route> > addresses();
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:
static int _ttl;

View File

@ -75,11 +75,34 @@ ptr<session> proxy::find_or_create_session(const address& saddr, const address&
return (*sit);
}
// 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.
// Check if there is an address for this specific interface it was received
// on (if so then immediately return a notice)
ptr<session> se;
if (receiver) {
for (std::list<ptr<route> >::iterator ad = address::addresses_begin();
ad != address::addresses_end(); ad++)
{
if ((*ad)->addr() == taddr && (*ad)->ifname() == receiver->name())
{
se = session::create(_ptr, saddr, daddr, taddr, _autowire);
if (se) {
se->add_iface(receiver);
_sessions.push_back(se);
logger::debug() << "proxy::handle_advert() found local taddr=" << taddr;
se->handle_advert(receiver);
return se;
}
}
}
}
// 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.
for (std::list<ptr<rule> >::iterator it = _rules.begin();
it != _rules.end(); it++) {
ptr<rule> ru = *it;
@ -116,14 +139,29 @@ ptr<session> proxy::find_or_create_session(const address& saddr, const address&
se->handle_advert();
return se;
} else {
se->add_iface((*it)->ifa());
ptr<iface> ifa = (*it)->ifa();
se->add_iface(ifa);
#ifdef WITH_ND_NETLINK
if (if_addr_find((*it)->ifa()->name(), &taddr.const_addr())) {
logger::debug() << "Sending NA out " << (*it)->ifa()->name();
if (if_addr_find(ifa->name(), &taddr.const_addr())) {
logger::debug() << "Sending NA out " << ifa->name();
se->add_iface(_ifa);
se->handle_advert();
}
#endif
// If a local address exists and it is for the requested interface
// then we already have a valid session
for (std::list<ptr<route> >::iterator ad = address::addresses_begin();
ad != address::addresses_end(); ad++)
{
if ((*ad)->addr() == taddr && (*ad)->ifname() == ifa->name()) {
logger::debug() << "proxy::handle_advert() found local taddr=" << taddr;
se->handle_advert(ifa);
break;
}
}
}
}
}
@ -142,7 +180,7 @@ void proxy::handle_advert(const address& saddr, const address& taddr, const ptr<
<< ", saddr=" << saddr.to_string()
<< ", taddr=" << taddr.to_string();
ptr<session> se = find_or_create_session(saddr, all_nodes, taddr, receiver);
ptr<session> se = find_or_create_session(all_nodes, all_nodes, taddr, receiver);
if (!se) return;
se->handle_advert(receiver);