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); _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) void address::load(const std::string& path)
@ -342,24 +347,31 @@ 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() << ")";
continue; continue;
} }
address addr; address addr;
if (route::hexdec(buf, (unsigned char* )&addr.addr(), 32) != 32) { if (route::hexdec(buf, (unsigned char* )&addr.addr(), 16) != 16) {
// TODO: Warn here? logger::warning() << "failed to load address (" << buf << ")";
continue; continue;
} }
addr.prefix(128); addr.prefix(128);
std::string iface = route::token(buf + 45);
address::add(addr, route::token(buf + 45)); address::add(addr, iface);
logger::debug() << "found local addr=" << addr << ", iface=" << iface;
} }
} catch (std::ifstream::failure e) { } catch (std::ifstream::failure e) {
logger::warning() << "Failed to parse IPv6 address data from '" << path << "'"; logger::warning() << "Failed to parse IPv6 address data from '" << path << "'";
logger::error() << e.what(); logger::error() << e.what();
} }
logger::debug() << "completed IP addresses load";
} }
void address::update(int elapsed_time) void address::update(int elapsed_time)

View File

@ -70,11 +70,13 @@ public:
operator std::string() const; operator std::string() const;
static std::list<ptr<route> > addresses();
static void add(const address& addr, const std::string& ifname); static void add(const address& addr, const std::string& ifname);
static void load(const std::string& path); 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 _ttl;

View File

@ -75,11 +75,34 @@ ptr<session> proxy::find_or_create_session(const address& saddr, const address&
return (*sit); return (*sit);
} }
// Since we couldn't find a session that matched, we'll try to find // Check if there is an address for this specific interface it was received
// a matching rule instead, and then set up a new session. // on (if so then immediately return a notice)
ptr<session> se; 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(); 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;
@ -116,14 +139,29 @@ ptr<session> proxy::find_or_create_session(const address& saddr, const address&
se->handle_advert(); se->handle_advert();
return se; return se;
} else { } else {
se->add_iface((*it)->ifa());
ptr<iface> ifa = (*it)->ifa();
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();
} }
#endif #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() << ", saddr=" << saddr.to_string()
<< ", taddr=" << taddr.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; if (!se) return;
se->handle_advert(receiver); se->handle_advert(receiver);