From 3bf3d7d3e7d51034bda873861c52578f3abe6b5d Mon Sep 17 00:00:00 2001 From: Etienne Dechamps Date: Sun, 18 Dec 2016 14:25:20 +0000 Subject: [PATCH] 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. --- src/protocol_edge.c | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/src/protocol_edge.c b/src/protocol_edge.c index dc0cf051..1d721227 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -132,7 +132,13 @@ bool add_edge_h(connection_t *c, const char *request) { e = lookup_edge(from, to); 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) { logger(DEBUG_PROTOCOL, LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", "ADD_EDGE", c->name, c->hostname); @@ -147,6 +153,10 @@ bool add_edge_h(connection_t *c, const char *request) { sockaddrfree(&e->address); e->address = address; } + if(new_local_address) { + sockaddrfree(&e->local_address); + e->local_address = local_address; + } if(e->weight != weight) { splay_node_t *node = splay_unlink(edge_weight_tree, e); e->weight = weight; @@ -155,36 +165,6 @@ bool add_edge_h(connection_t *c, const char *request) { 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 { sockaddrfree(&local_address); return true; -- 2.20.1