From 13b81fdd970f36eaed7c411b903d7e4cd949e427 Mon Sep 17 00:00:00 2001 From: Daniel Adolfsson Date: Tue, 7 Feb 2012 12:36:09 +0100 Subject: [PATCH] Last major commit for version 0.2.2 * Fix so that "route-ttl" in ndppd.conf works * Fix a typo in ndppd.conf.5 * Update "ndppd.conf" to reflect the big changes * Fix a bug with config loader * Fix so that "auto" will never forward a Neighbor Solicitation Message out through the "proxy" interface --- ChangeLog | 13 +++++++++++ ndppd.conf-dist | 52 ++++++++++++++++++++++++++------------------ ndppd.conf.5 | 2 +- src/conf.cc | 58 ++++++++++++++++++++----------------------------- src/ndppd.cc | 12 +++++++--- src/proxy.cc | 6 +++-- src/route.cc | 22 +++++++++++++++++++ src/route.h | 10 +++++++++ 8 files changed, 113 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index d6a30d3..05e4ee4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2012-02-06 Daniel Adolfsson + + * Version 0.2.2 + + * Removed "libconfuse" dependency. + + * New "auto" configuration to detect outgoing interface, for forwarding + Neighbor Solicitation Messages. + + * Improved logging. + + * Bug fixes related to memory management. + 2012-01-26 Daniel Adolfsson * Author changed e-mail address; updated copyright info. diff --git a/ndppd.conf-dist b/ndppd.conf-dist index 84c7c15..37656c7 100644 --- a/ndppd.conf-dist +++ b/ndppd.conf-dist @@ -1,29 +1,33 @@ +# route-ttl (NEW) +# This tells 'ndppd' how often to reload the route file /proc/net/ipv6_route. +# Default value is '30000' (30 seconds). + +route-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). -# is required. - -# You may have several 'proxy' sections. +# is required. You may have several 'proxy' sections. proxy eth0 { - # router = + # router # This option turns on or off the router flag for Neighbor Advertisement # messages. Default value is 'true'. - router = yes + router yes - # timeout = + # timeout # Controls how long to wait for a Neighbor Advertisment message before # invalidating the entry, in milliseconds. Default value is '500'. - timeout = 500 + timeout 500 - # ttl = + # ttl # Controls how long a valid or invalid entry remains in the cache, in # milliseconds. Default value is '30000' (30 seconds). - ttl = 30000 + ttl 30000 # rule [/] # This is a rule that the target address is to match against. If no netmask @@ -31,22 +35,28 @@ proxy eth0 { # addresses may or may not overlap. rule 1111:: { + # Only one of 'static', 'auto' and 'interface' may be specified. Please + # read 'ndppd.conf' manpage for details about the methods below. - # iface = - # By setting this option, ndppd will forward the Neighbor Solicitation - # message to this interface and wait for a response. Only if a client - # responds with a Neighbor Advertisement message will the proxy respond. + # 'auto' should work in most cases. - # Note that if you do not provide an interface, this rule will match - # and immediately send a response through the proxy. It's recommended - # that you use the "iface" option as much as possible. + # static (NEW) + # 'ndppd' will immediately answer any Neighbor Solicitation Messages + # (if they match the IP rule). - # Using a prefix <= /120 without an interface will trigger a notice. + # iface + # 'ndppd' will forward the Neighbor Solicitation Message through the + # specified interface - and only respond if a matching Neighbor + # Advertisement Message is received. + + # auto (NEW) + # Same as above, but instead of manually specifying the outgoing + # interface, 'ndppd' will check for a matching route in /proc/net/ipv6_route. - iface = eth1 - } + auto - rule 1111::1/96 { - iface = eth2 + # 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 + # to keep this behavior - for now (it may be removed in a future version). } } diff --git a/ndppd.conf.5 b/ndppd.conf.5 index 53817b3..785bce2 100644 --- a/ndppd.conf.5 +++ b/ndppd.conf.5 @@ -79,7 +79,7 @@ If this option is specified .B ndppd will attempt to detect which interface to use in order to forward Neighbor Solicitation Messages, by reading the routing table -.BR /proc/sys/ipv6_route . +.BR /proc/net/ipv6_route . .IP "static" .B (NEW) This option tells diff --git a/src/conf.cc b/src/conf.cc index 00cf3fa..a22b44e 100644 --- a/src/conf.cc +++ b/src/conf.cc @@ -103,29 +103,17 @@ bool conf::is_block() const return _is_block; } -const char* conf::skip(const char* str, bool all) +const char* conf::skip(const char* str, bool newlines) { - if (!all) { - while (*str && (*str != '\n') && isspace(*str)) - str++; - - return str; - } - while (*str) { - while (*str && isspace(*str)) + while (*str && isspace(*str) && ((*str != '\n') || newlines)) str++; - if (!*str) - break; - if ((*str == '#') || ((*str == '/') && (*(str + 1) == '/'))) { - while (*str && (*str != '\n')) + while (*str && (*str != '\n')) { str++; - continue; - } - - if ((*str == '/') && (*(str + 1) == '*')) { + } + } else if ((*str == '/') && (*(str + 1) == '*')) { while (*str) { if ((*str == '*') && (*(str + 1) == '/')) { str += 2; @@ -133,10 +121,9 @@ const char* conf::skip(const char* str, bool all) } str++; } - continue; + } else { + break; } - - break; } return str; @@ -158,20 +145,23 @@ bool conf::parse_block(const char** str) return true; } - while (*p && isalpha(*p)) { + while (isalnum(*p) || (*p == '_') || (*p == '-')) { ss << *p++; } - p = skip(p); + p = skip(p, false); if (*p == '=') { p++; + p = skip(p, false); } ptr cf(new conf); if (cf->parse(&p)) { _map.insert(std::pair >(ss.str(), cf)); + } else { + return false; } } @@ -186,18 +176,14 @@ bool conf::parse(const char** str) p = skip(p, false); - if (!*p) { - return false; - } else if ((*p == '\'') || (*p == '"')) { - for (char e = *p++; *p && (*p != e); p++) - ss <<* p; - } else if (isalnum(*p)) { - while (*p && (isalnum(*p) || strchr(":/.",* p))) - ss <<* p++; + if ((*p == '\'') || (*p == '"')) { + for (char e = *p++; *p && (*p != e) && (*p != '\n'); p++) + ss << *p; + p = skip(p, false); } else { - _value = ""; - *str = p; - return true; + while (*p && isgraph(*p) && (*p != '{') && (*p != '}')) { + ss << *p++; + } } _value = ss.str(); @@ -207,11 +193,13 @@ bool conf::parse(const char** str) if (*p == '{') { p++; - if (!parse_block(&p)) + if (!parse_block(&p)) { return false; + } - if (*p != '}') + if (*p != '}') { return false; + } p++; } diff --git a/src/ndppd.cc b/src/ndppd.cc index 628beea..6ac19e8 100644 --- a/src/ndppd.cc +++ b/src/ndppd.cc @@ -56,17 +56,22 @@ int daemonize() bool configure(const std::string& path) { - ptr cf; + ptr cf, x_cf; if (!(cf = conf::load(path))) return false; + if (!(x_cf = cf->find("route-ttl"))) + route::ttl(30000); + else + route::ttl(*x_cf); + std::vector >::const_iterator p_it; std::vector > proxies(cf->find_all("proxy")); for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) { - ptr pr_cf =* p_it, x_cf; + ptr pr_cf = *p_it; if (pr_cf->empty()) { logger::error() << "'proxy' section is missing interface name"; @@ -221,7 +226,7 @@ int main(int argc, char* argv[], char* env[]) if (!configure(config_path)) return -1; - route::load("/proc/net/ipv6_route"); + //route::load("/proc/net/ipv6_route"); // Time stuff. @@ -247,6 +252,7 @@ int main(int argc, char* argv[], char* env[]) t1.tv_sec = t2.tv_sec; t1.tv_usec = t2.tv_usec; + route::update(elapsed_time); session::update_all(elapsed_time); } diff --git a/src/proxy.cc b/src/proxy.cc index 246014c..062ae2b 100644 --- a/src/proxy.cc +++ b/src/proxy.cc @@ -105,8 +105,10 @@ void proxy::handle_solicit(const address& saddr, const address& daddr, if (ru->is_auto()) { ptr ifa = route::find_and_open(taddr); - // TODO: Check if it's a good interface. - if (ifa) { + + // If we could find a route matching our rule in /proc/net/ipv6_route, + // and it's not the same interface as the one pr (proxy) is using. + if (ifa && (ifa != ru->ifa())) { se->add_iface(ifa); continue; } diff --git a/src/route.cc b/src/route.cc index 87bb41e..f27f030 100644 --- a/src/route.cc +++ b/src/route.cc @@ -24,6 +24,10 @@ NDPPD_NS_BEGIN std::list > route::_routes; +int route::_ttl; + +int route::_c_ttl; + route::route(const address& addr, const std::string& ifname) : _addr(addr), _ifname(ifname) { @@ -112,6 +116,14 @@ void route::load(const std::string& path) } } +void route::update(int elapsed_time) +{ + if ((_c_ttl -= elapsed_time) <= 0) { + load("/proc/net/ipv6_route"); + _c_ttl = _ttl; + } +} + ptr route::create(const address& addr, const std::string& ifname) { ptr rt(new route(addr, ifname)); @@ -162,5 +174,15 @@ const address& route::addr() const return _addr; } +int route::ttl() +{ + return _ttl; +} + +void route::ttl(int ttl) +{ + _ttl = ttl; +} + NDPPD_NS_END diff --git a/src/route.h b/src/route.h index 555fb1b..e4fbb5b 100644 --- a/src/route.h +++ b/src/route.h @@ -33,6 +33,12 @@ public: static void load(const std::string& path); + static void update(int elapsed_time); + + static int ttl(); + + static void ttl(int ttl); + const std::string& ifname() const; const address& addr() const; @@ -40,6 +46,10 @@ public: ptr ifa(); private: + static int _ttl; + + static int _c_ttl; + address _addr; std::string _ifname;