X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fprotocol_edge.c;h=be48e0d4bb470aefbcb9589784b443b634cc1c7a;hp=9d439225678b12d1afdfcd66774c8ef2d346be73;hb=3fae14fae5a347823679ef694ab630b4991a201d;hpb=2762509be179dcb21d855f3d6f90d3ee686e3910 diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 9d439225..be48e0d4 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -1,7 +1,7 @@ /* protocol_edge.c -- handle the meta-protocol, edges Copyright (C) 1999-2005 Ivo Timmermans, - 2000-2009 Guus Sliepen + 2000-2016 Guus Sliepen 2009 Michael Tokarev This program is free software; you can redistribute it and/or modify @@ -41,9 +41,9 @@ bool send_add_edge(connection_t *c, const edge_t *e) { sockaddr2str(&e->address, &address, &port); - x = send_request(c, "%d %x %s %s %s %s %lx %d", ADD_EDGE, rand(), - e->from->name, e->to->name, address, port, - e->options, e->weight); + x = send_request(c, "%d %x %s %s %s %s %x %d", ADD_EDGE, rand(), + e->from->name, e->to->name, address, port, + e->options, e->weight); free(address); free(port); @@ -58,13 +58,13 @@ bool add_edge_h(connection_t *c) { char to_address[MAX_STRING_SIZE]; char to_port[MAX_STRING_SIZE]; sockaddr_t address; - long int options; + uint32_t options; int weight; - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d", - from_name, to_name, to_address, to_port, &options, &weight) != 6) { + if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d", + from_name, to_name, to_address, to_port, &options, &weight) != 6) { logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, - c->hostname); + c->hostname); return false; } @@ -72,12 +72,13 @@ bool add_edge_h(connection_t *c) { if(!check_id(from_name) || !check_id(to_name)) { logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, - c->hostname, "invalid name"); + c->hostname, "invalid name"); return false; } - if(seen_request(c->buffer)) + if(seen_request(c->buffer)) { return true; + } /* Lookup nodes */ @@ -85,12 +86,12 @@ bool add_edge_h(connection_t *c) { to = lookup_node(to_name); if(tunnelserver && - from != myself && from != c->node && - to != myself && to != c->node) { + from != myself && from != c->node && + to != myself && to != c->node) { /* ignore indirect edge registrations for tunnelserver */ ifdebug(PROTOCOL) logger(LOG_WARNING, - "Ignoring indirect %s from %s (%s)", - "ADD_EDGE", c->name, c->hostname); + "Ignoring indirect %s from %s (%s)", + "ADD_EDGE", c->name, c->hostname); return true; } @@ -119,20 +120,34 @@ bool add_edge_h(connection_t *c) { if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { if(from == myself) { ifdebug(PROTOCOL) logger(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); send_add_edge(c, e); return true; } else { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry", - "ADD_EDGE", c->name, c->hostname); - edge_del(e); - graph(); + "ADD_EDGE", c->name, c->hostname); + e->options = options; + + if(sockaddrcmp(&e->address, &address)) { + sockaddrfree(&e->address); + e->address = address; + } + + if(e->weight != weight) { + avl_node_t *node = avl_unlink(edge_weight_tree, e); + e->weight = weight; + avl_insert_node(edge_weight_tree, node); + } + + goto done; } - } else + } else { return true; + } } else if(from == myself) { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist", - "ADD_EDGE", c->name, c->hostname); + "ADD_EDGE", c->name, c->hostname); + contradicting_add_edge++; e = new_edge(); e->from = from; e->to = to; @@ -149,10 +164,12 @@ bool add_edge_h(connection_t *c) { e->weight = weight; edge_add(e); +done: /* Tell the rest about the new edge */ - if(!tunnelserver) + if(!tunnelserver) { forward_request(c); + } /* Run MST before or after we tell the rest? */ @@ -163,7 +180,7 @@ bool add_edge_h(connection_t *c) { bool send_del_edge(connection_t *c, const edge_t *e) { return send_request(c, "%d %x %s %s", DEL_EDGE, rand(), - e->from->name, e->to->name); + e->from->name, e->to->name); } bool del_edge_h(connection_t *c) { @@ -174,7 +191,7 @@ bool del_edge_h(connection_t *c) { if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) { logger(LOG_ERR, "Got bad %s from %s (%s)", "DEL_EDGE", c->name, - c->hostname); + c->hostname); return false; } @@ -182,12 +199,13 @@ bool del_edge_h(connection_t *c) { if(!check_id(from_name) || !check_id(to_name)) { logger(LOG_ERR, "Got bad %s from %s (%s): %s", "DEL_EDGE", c->name, - c->hostname, "invalid name"); + c->hostname, "invalid name"); return false; } - if(seen_request(c->buffer)) + if(seen_request(c->buffer)) { return true; + } /* Lookup nodes */ @@ -195,24 +213,24 @@ bool del_edge_h(connection_t *c) { to = lookup_node(to_name); if(tunnelserver && - from != myself && from != c->node && - to != myself && to != c->node) { + from != myself && from != c->node && + to != myself && to != c->node) { /* ignore indirect edge registrations for tunnelserver */ ifdebug(PROTOCOL) logger(LOG_WARNING, - "Ignoring indirect %s from %s (%s)", - "DEL_EDGE", c->name, c->hostname); + "Ignoring indirect %s from %s (%s)", + "DEL_EDGE", c->name, c->hostname); return true; } if(!from) { ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + "DEL_EDGE", c->name, c->hostname); return true; } if(!to) { ifdebug(PROTOCOL) logger(LOG_ERR, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + "DEL_EDGE", c->name, c->hostname); return true; } @@ -222,21 +240,23 @@ bool del_edge_h(connection_t *c) { if(!e) { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not appear in the edge tree", - "DEL_EDGE", c->name, c->hostname); + "DEL_EDGE", c->name, c->hostname); return true; } if(e->from == myself) { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself", - "DEL_EDGE", c->name, c->hostname); - send_add_edge(c, e); /* Send back a correction */ + "DEL_EDGE", c->name, c->hostname); + contradicting_del_edge++; + send_add_edge(c, e); /* Send back a correction */ return true; } /* Tell the rest about the deleted edge */ - if(!tunnelserver) + if(!tunnelserver) { forward_request(c); + } /* Delete the edge */ @@ -250,9 +270,12 @@ bool del_edge_h(connection_t *c) { if(!to->status.reachable) { e = lookup_edge(to, myself); + if(e) { - if(!tunnelserver) - send_del_edge(broadcast, e); + if(!tunnelserver) { + send_del_edge(everyone, e); + } + edge_del(e); } }