From a690d128e7f05d17fd33e3132b7a39d629a7377c Mon Sep 17 00:00:00 2001 From: John Sharratt Date: Mon, 3 Jul 2017 17:15:54 +0200 Subject: [PATCH] Added a global list of all the IP addresses that the interfaces of the local machine which will be used to cover some missing solicitation requests --- ndppd.conf-dist | 6 ++++ src/address.cc | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ src/address.h | 21 +++++++++++++ src/ndppd.cc | 8 +++++ src/route.cc | 6 ++-- src/route.h | 12 ++++---- src/rule.cc | 8 +++++ src/rule.h | 4 +++ 8 files changed, 134 insertions(+), 9 deletions(-) diff --git a/ndppd.conf-dist b/ndppd.conf-dist index d3986e2..3549b91 100644 --- a/ndppd.conf-dist +++ b/ndppd.conf-dist @@ -4,6 +4,12 @@ route-ttl 30000 +# address-ttl (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 # 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). diff --git a/src/address.cc b/src/address.cc index 0b1357e..49f082e 100644 --- a/src/address.cc +++ b/src/address.cc @@ -15,6 +15,8 @@ // along with this program. If not, see . #include #include +#include +#include #include #include @@ -27,9 +29,16 @@ #include "ndppd.h" #include "address.h" +#include "route.h" NDPPD_NS_BEGIN +std::list > address::_addresses; + +int address::_ttl; + +int address::_c_ttl; + address::address() { reset(); @@ -302,4 +311,73 @@ bool address::is_unicast() const return _addr.s6_addr[0] != 0xff; } +void address::add(const address& addr, const std::string& ifname) +{ + ptr rt(new route(addr, ifname)); + // logger::debug() << "address::create() addr=" << addr << ", ifname=" << ifname; + _addresses.push_back(rt); +} + +std::list > address::addresses() +{ + return _addresses; +} + +void address::load(const std::string& path) +{ + // Hack to make sure the addresses are not freed prematurely. + std::list > 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) { + continue; + } + + address addr; + + if (route::hexdec(buf, (unsigned char* )&addr.addr(), 32) != 32) { + // TODO: Warn here? + continue; + } + + addr.prefix(128); + + address::add(addr, route::token(buf + 45)); + } + } catch (std::ifstream::failure e) { + logger::warning() << "Failed to parse IPv6 address data from '" << path << "'"; + logger::error() << e.what(); + } +} + +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 diff --git a/src/address.h b/src/address.h index dc2ad18..9b14fc5 100644 --- a/src/address.h +++ b/src/address.h @@ -16,6 +16,7 @@ #pragma once #include +#include #include #include "ndppd.h" @@ -24,6 +25,8 @@ NDPPD_NS_BEGIN class iface; +class route; + class address { public: address(); @@ -33,6 +36,12 @@ public: address(const in6_addr& addr); address(const in6_addr& addr, const in6_addr& mask); 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(); @@ -60,8 +69,20 @@ public: bool is_multicast() const; 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); private: + static int _ttl; + + static int _c_ttl; + + static std::list > _addresses; + struct in6_addr _addr, _mask; }; diff --git a/src/ndppd.cc b/src/ndppd.cc index 51cb852..a4e44e4 100644 --- a/src/ndppd.cc +++ b/src/ndppd.cc @@ -141,6 +141,11 @@ static bool configure(ptr& cf) route::ttl(30000); else route::ttl(*x_cf); + + if (!(x_cf = cf->find("address-ttl"))) + address::ttl(30000); + else + address::ttl(*x_cf); std::vector >::const_iterator p_it; @@ -334,6 +339,9 @@ int main(int argc, char* argv[], char* env[]) if (rule::any_auto()) route::update(elapsed_time); + + if (rule::any_iface()) + address::update(elapsed_time); session::update_all(elapsed_time); } diff --git a/src/route.cc b/src/route.cc index 32e475f..6b7343d 100644 --- a/src/route.cc +++ b/src/route.cc @@ -105,19 +105,19 @@ void route::load(const std::string& path) 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? continue; } - if (hexdec(buf + 33,& pfx, 1) != 1) { + if (route::hexdec(buf + 33,& pfx, 1) != 1) { // TODO: Warn here? continue; } addr.prefix((int)pfx); - route::create(addr, token(buf + 141)); + route::create(addr, route::token(buf + 141)); } } catch (std::ifstream::failure e) { logger::warning() << "Failed to parse IPv6 routing data from '" << path << "'"; diff --git a/src/route.h b/src/route.h index e4fbb5b..ffe4d71 100644 --- a/src/route.h +++ b/src/route.h @@ -44,6 +44,12 @@ public: const address& addr() const; ptr 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: static int _ttl; @@ -56,14 +62,8 @@ private: ptr _ifa; - static size_t hexdec(const char* str, unsigned char* buf, size_t size); - - static std::string token(const char* str); - static std::list > _routes; - route(const address& addr, const std::string& ifname); - }; NDPPD_NS_END diff --git a/src/rule.cc b/src/rule.cc index 7475f0d..50ddbfe 100644 --- a/src/rule.cc +++ b/src/rule.cc @@ -29,6 +29,8 @@ std::vector interfaces; bool rule::_any_aut = false; +bool rule::_any_iface = false; + rule::rule() { } @@ -41,6 +43,7 @@ ptr rule::create(const ptr& pr, const address& addr, const ptr_ifa = ifa; ru->_addr = addr; ru->_aut = false; + _any_iface = true; unsigned int ifindex; ifindex = if_nametoindex(pr->ifa()->name().c_str()); @@ -93,6 +96,11 @@ bool rule::any_auto() return _any_aut; } +bool rule::any_iface() +{ + return _any_iface; +} + bool rule::check(const address& addr) const { return _addr == addr; diff --git a/src/rule.h b/src/rule.h index 384b05c..14912b4 100644 --- a/src/rule.h +++ b/src/rule.h @@ -44,6 +44,8 @@ public: bool check(const address& addr) const; static bool any_auto(); + + static bool any_iface(); private: weak_ptr _ptr; @@ -57,6 +59,8 @@ private: bool _aut; static bool _any_aut; + + static bool _any_iface; rule(); };