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
This commit is contained in:
Daniel Adolfsson 2012-02-07 12:36:09 +01:00
parent d51acba693
commit 13b81fdd97
8 changed files with 113 additions and 62 deletions

View File

@ -1,3 +1,16 @@
2012-02-06 Daniel Adolfsson <daniel@priv.nu>
* 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 <daniel@priv.nu> 2012-01-26 Daniel Adolfsson <daniel@priv.nu>
* Author changed e-mail address; updated copyright info. * Author changed e-mail address; updated copyright info.

View File

@ -1,29 +1,33 @@
# route-ttl <integer> (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 <interface> # proxy <interface>
# This sets up a listener, that will listen for any Neighbor Solicitation # 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). # messages, and respond to them according to a set of rules (see below).
# <interface> is required. # <interface> is required. You may have several 'proxy' sections.
# You may have several 'proxy' sections.
proxy eth0 { proxy eth0 {
# router = <yes|no|true|false> # router <yes|no|true|false>
# This option turns on or off the router flag for Neighbor Advertisement # This option turns on or off the router flag for Neighbor Advertisement
# messages. Default value is 'true'. # messages. Default value is 'true'.
router = yes router yes
# timeout = <integer> # timeout <integer>
# Controls how long to wait for a Neighbor Advertisment message before # Controls how long to wait for a Neighbor Advertisment message before
# invalidating the entry, in milliseconds. Default value is '500'. # invalidating the entry, in milliseconds. Default value is '500'.
timeout = 500 timeout 500
# ttl = <integer> # ttl <integer>
# Controls how long a valid or invalid entry remains in the cache, in # Controls how long a valid or invalid entry remains in the cache, in
# milliseconds. Default value is '30000' (30 seconds). # milliseconds. Default value is '30000' (30 seconds).
ttl = 30000 ttl 30000
# rule <ip>[/<mask>] # rule <ip>[/<mask>]
# This is a rule that the target address is to match against. If no netmask # 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. # addresses may or may not overlap.
rule 1111:: { rule 1111:: {
# Only one of 'static', 'auto' and 'interface' may be specified. Please
# read 'ndppd.conf' manpage for details about the methods below.
# iface = <interface> # 'auto' should work in most cases.
# 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.
# Note that if you do not provide an interface, this rule will match # static (NEW)
# and immediately send a response through the proxy. It's recommended # 'ndppd' will immediately answer any Neighbor Solicitation Messages
# that you use the "iface" option as much as possible. # (if they match the IP rule).
# Using a prefix <= /120 without an interface will trigger a notice. # iface <interface>
# '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 { # Note that before version 0.2.2 of 'ndppd', if you didn't choose a
iface = eth2 # method, it defaulted to 'static'. For compatibility reasons we choose
# to keep this behavior - for now (it may be removed in a future version).
} }
} }

View File

@ -79,7 +79,7 @@ If this option is specified
.B ndppd .B ndppd
will attempt to detect which interface to use in order to forward will attempt to detect which interface to use in order to forward
Neighbor Solicitation Messages, by reading the routing table Neighbor Solicitation Messages, by reading the routing table
.BR /proc/sys/ipv6_route . .BR /proc/net/ipv6_route .
.IP "static" .IP "static"
.B (NEW) .B (NEW)
This option tells This option tells

View File

@ -103,29 +103,17 @@ bool conf::is_block() const
return _is_block; 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) {
while (*str && isspace(*str)) while (*str && isspace(*str) && ((*str != '\n') || newlines))
str++; str++;
if (!*str)
break;
if ((*str == '#') || ((*str == '/') && (*(str + 1) == '/'))) { if ((*str == '#') || ((*str == '/') && (*(str + 1) == '/'))) {
while (*str && (*str != '\n')) while (*str && (*str != '\n')) {
str++; str++;
continue; }
} } else if ((*str == '/') && (*(str + 1) == '*')) {
if ((*str == '/') && (*(str + 1) == '*')) {
while (*str) { while (*str) {
if ((*str == '*') && (*(str + 1) == '/')) { if ((*str == '*') && (*(str + 1) == '/')) {
str += 2; str += 2;
@ -133,10 +121,9 @@ const char* conf::skip(const char* str, bool all)
} }
str++; str++;
} }
continue; } else {
break;
} }
break;
} }
return str; return str;
@ -158,20 +145,23 @@ bool conf::parse_block(const char** str)
return true; return true;
} }
while (*p && isalpha(*p)) { while (isalnum(*p) || (*p == '_') || (*p == '-')) {
ss << *p++; ss << *p++;
} }
p = skip(p); p = skip(p, false);
if (*p == '=') { if (*p == '=') {
p++; p++;
p = skip(p, false);
} }
ptr<conf> cf(new conf); ptr<conf> cf(new conf);
if (cf->parse(&p)) { if (cf->parse(&p)) {
_map.insert(std::pair<std::string, ptr<conf> >(ss.str(), cf)); _map.insert(std::pair<std::string, ptr<conf> >(ss.str(), cf));
} else {
return false;
} }
} }
@ -186,18 +176,14 @@ bool conf::parse(const char** str)
p = skip(p, false); p = skip(p, false);
if (!*p) { if ((*p == '\'') || (*p == '"')) {
return false; for (char e = *p++; *p && (*p != e) && (*p != '\n'); p++)
} else if ((*p == '\'') || (*p == '"')) { ss << *p;
for (char e = *p++; *p && (*p != e); p++) p = skip(p, false);
ss <<* p;
} else if (isalnum(*p)) {
while (*p && (isalnum(*p) || strchr(":/.",* p)))
ss <<* p++;
} else { } else {
_value = ""; while (*p && isgraph(*p) && (*p != '{') && (*p != '}')) {
*str = p; ss << *p++;
return true; }
} }
_value = ss.str(); _value = ss.str();
@ -207,11 +193,13 @@ bool conf::parse(const char** str)
if (*p == '{') { if (*p == '{') {
p++; p++;
if (!parse_block(&p)) if (!parse_block(&p)) {
return false; return false;
}
if (*p != '}') if (*p != '}') {
return false; return false;
}
p++; p++;
} }

View File

@ -56,17 +56,22 @@ int daemonize()
bool configure(const std::string& path) bool configure(const std::string& path)
{ {
ptr<conf> cf; ptr<conf> cf, x_cf;
if (!(cf = conf::load(path))) if (!(cf = conf::load(path)))
return false; return false;
if (!(x_cf = cf->find("route-ttl")))
route::ttl(30000);
else
route::ttl(*x_cf);
std::vector<ptr<conf> >::const_iterator p_it; std::vector<ptr<conf> >::const_iterator p_it;
std::vector<ptr<conf> > proxies(cf->find_all("proxy")); std::vector<ptr<conf> > proxies(cf->find_all("proxy"));
for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) { for (p_it = proxies.begin(); p_it != proxies.end(); p_it++) {
ptr<conf> pr_cf =* p_it, x_cf; ptr<conf> pr_cf = *p_it;
if (pr_cf->empty()) { if (pr_cf->empty()) {
logger::error() << "'proxy' section is missing interface name"; logger::error() << "'proxy' section is missing interface name";
@ -221,7 +226,7 @@ int main(int argc, char* argv[], char* env[])
if (!configure(config_path)) if (!configure(config_path))
return -1; return -1;
route::load("/proc/net/ipv6_route"); //route::load("/proc/net/ipv6_route");
// Time stuff. // Time stuff.
@ -247,6 +252,7 @@ int main(int argc, char* argv[], char* env[])
t1.tv_sec = t2.tv_sec; t1.tv_sec = t2.tv_sec;
t1.tv_usec = t2.tv_usec; t1.tv_usec = t2.tv_usec;
route::update(elapsed_time);
session::update_all(elapsed_time); session::update_all(elapsed_time);
} }

View File

@ -105,8 +105,10 @@ void proxy::handle_solicit(const address& saddr, const address& daddr,
if (ru->is_auto()) { if (ru->is_auto()) {
ptr<iface> ifa = route::find_and_open(taddr); ptr<iface> 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); se->add_iface(ifa);
continue; continue;
} }

View File

@ -24,6 +24,10 @@ NDPPD_NS_BEGIN
std::list<ptr<route> > route::_routes; std::list<ptr<route> > route::_routes;
int route::_ttl;
int route::_c_ttl;
route::route(const address& addr, const std::string& ifname) : route::route(const address& addr, const std::string& ifname) :
_addr(addr), _ifname(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> route::create(const address& addr, const std::string& ifname) ptr<route> route::create(const address& addr, const std::string& ifname)
{ {
ptr<route> rt(new route(addr, ifname)); ptr<route> rt(new route(addr, ifname));
@ -162,5 +174,15 @@ const address& route::addr() const
return _addr; return _addr;
} }
int route::ttl()
{
return _ttl;
}
void route::ttl(int ttl)
{
_ttl = ttl;
}
NDPPD_NS_END NDPPD_NS_END

View File

@ -33,6 +33,12 @@ public:
static void load(const std::string& path); 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 std::string& ifname() const;
const address& addr() const; const address& addr() const;
@ -40,6 +46,10 @@ public:
ptr<iface> ifa(); ptr<iface> ifa();
private: private:
static int _ttl;
static int _c_ttl;
address _addr; address _addr;
std::string _ifname; std::string _ifname;