From 1f50dc5b5a56e8493183d360e6c91641e66c1665 Mon Sep 17 00:00:00 2001 From: John Sharratt Date: Mon, 3 Jul 2017 20:12:36 +0200 Subject: [PATCH] NDP proxy will now respond to Solicitation requests to gateway addresses that it holds on secondary interfaces --- src/address.cc | 22 +++++++++++++++++----- src/address.h | 6 ++++-- src/proxy.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/address.cc b/src/address.cc index 49f082e..f0298d7 100644 --- a/src/address.cc +++ b/src/address.cc @@ -318,9 +318,14 @@ void address::add(const address& addr, const std::string& ifname) _addresses.push_back(rt); } -std::list > address::addresses() +std::list >::iterator address::addresses_begin() { - return _addresses; + return _addresses.begin(); +} + +std::list >::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); + + 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) { 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) diff --git a/src/address.h b/src/address.h index 9b14fc5..90b1a03 100644 --- a/src/address.h +++ b/src/address.h @@ -70,11 +70,13 @@ public: operator std::string() const; - static std::list > addresses(); - static void add(const address& addr, const std::string& ifname); static void load(const std::string& path); + + static std::list >::iterator addresses_begin(); + + static std::list >::iterator addresses_end(); private: static int _ttl; diff --git a/src/proxy.cc b/src/proxy.cc index 5e32b2f..226b581 100644 --- a/src/proxy.cc +++ b/src/proxy.cc @@ -75,11 +75,34 @@ ptr 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 se; + if (receiver) { + for (std::list >::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 >::iterator it = _rules.begin(); it != _rules.end(); it++) { ptr ru = *it; @@ -116,14 +139,29 @@ ptr proxy::find_or_create_session(const address& saddr, const address& se->handle_advert(); return se; } else { - se->add_iface((*it)->ifa()); + + ptr 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 >::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 se = find_or_create_session(saddr, all_nodes, taddr, receiver); + ptr se = find_or_create_session(all_nodes, all_nodes, taddr, receiver); if (!se) return; se->handle_advert(receiver);