Fix edge updates containing local address changes.

This commit fixes a logic bug in the edge update code where local
address changes are not taken into account if they are bundled in with
other changes. This bug breaks local discovery in some scenarios.

The regression was introduced by commit
e4670fc4a0576eb76f1807ce29fa9455dd247632.
This commit is contained in:
Etienne Dechamps 2016-12-18 14:25:20 +00:00
parent 0792a10a5a
commit 3bf3d7d3e7

View file

@ -132,7 +132,13 @@ bool add_edge_h(connection_t *c, const char *request) {
e = lookup_edge(from, to); e = lookup_edge(from, to);
if(e) { if(e) {
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { // local_address.sa.sa_family will be 0 if we got it from older tinc versions
// local_address.sa.sa_family will be 255 (AF_UNKNOWN) if we got it from newer versions
// but for edge which does not have local_address
bool new_local_address = local_address.sa.sa_family && local_address.sa.sa_family != AF_UNKNOWN &&
sockaddrcmp(&e->local_address, &local_address);
if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address) || new_local_address) {
if(from == myself) { if(from == myself) {
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
"ADD_EDGE", c->name, c->hostname); "ADD_EDGE", c->name, c->hostname);
@ -147,6 +153,10 @@ bool add_edge_h(connection_t *c, const char *request) {
sockaddrfree(&e->address); sockaddrfree(&e->address);
e->address = address; e->address = address;
} }
if(new_local_address) {
sockaddrfree(&e->local_address);
e->local_address = local_address;
}
if(e->weight != weight) { if(e->weight != weight) {
splay_node_t *node = splay_unlink(edge_weight_tree, e); splay_node_t *node = splay_unlink(edge_weight_tree, e);
e->weight = weight; e->weight = weight;
@ -155,36 +165,6 @@ bool add_edge_h(connection_t *c, const char *request) {
goto done; goto done;
} }
} else if(sockaddrcmp(&e->local_address, &local_address)) {
if(from == myself) {
if(e->local_address.sa.sa_family && local_address.sa.sa_family) {
// Someone has the wrong local address for ourself. Correct then.
logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry",
"ADD_EDGE", c->name, c->hostname);
send_add_edge(c, e);
sockaddrfree(&local_address);
return true;
}
// Otherwise, just ignore it.
sockaddrfree(&local_address);
return true;
} else if(local_address.sa.sa_family && local_address.sa.sa_family != AF_UNKNOWN) {
// We learned a new local address for this edge.
// local_address.sa.sa_family will be 0 if we got it from older tinc versions
// local_address.sa.sa_family will be 255 (AF_UNKNOWN) if we got it from newer versions
// but for edge which does not have local_address
sockaddrfree(&e->local_address);
e->local_address = local_address;
// Tell others about it.
if(!tunnelserver)
forward_request(c, request);
return true;
} else {
sockaddrfree(&local_address);
return true;
}
} else { } else {
sockaddrfree(&local_address); sockaddrfree(&local_address);
return true; return true;