X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fprotocol_node.c;h=758b1eaafc2a2e0b950f1b3379d754a15144413f;hp=3d0355fda4e3f28fa3ad767662b35aeceb2f50d5;hb=66741978e16cc407e5c760621c34d1aabb753cd2;hpb=2cb21f8810a6e0241a80623e991c8308b603ae95 diff --git a/src/protocol_node.c b/src/protocol_node.c index 3d0355fd..758b1eaa 100644 --- a/src/protocol_node.c +++ b/src/protocol_node.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol_node.c,v 1.1.4.1 2002/09/02 22:40:42 guus Exp $ + $Id: protocol_node.c,v 1.1.4.6 2002/09/04 08:48:03 guus Exp $ */ #include "config.h" @@ -48,10 +48,14 @@ int send_add_node(connection_t *c, node_t *n) int x; char *address, *port; cp + if(!n->status.reachable) + return 0; + sockaddr2str(&n->address, &address, &port); - x = send_request(c, "%d %s %s %s %lx %d", ADD_NODE, + x = send_request(c, "%d %s %s %s %lx %d %s %s", ADD_NODE, n->name, address, port, - n->options, n->distance + 1); + n->options, n->distance + 1, // Alternatively, use n->distance + c->estimated_weight + n->prevhop->name, n->via->name); free(address); free(port); cp @@ -61,16 +65,18 @@ cp int add_node_h(connection_t *c) { connection_t *other; - node_t *n; + node_t *n, *prevhop, *via; char name[MAX_STRING_SIZE]; char address[MAX_STRING_SIZE]; char port[MAX_STRING_SIZE]; + char prevhopname[MAX_STRING_SIZE]; + char vianame[MAX_STRING_SIZE]; long int options; int distance; avl_node_t *node; cp - if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d", - name, address, port, &options, &distance) != 5) + if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d "MAX_STRING" "MAX_STRING, + name, address, port, &options, &distance, prevhopname, vianame) != 7) { syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_NODE", c->name, c->hostname); return -1; @@ -84,8 +90,31 @@ cp return -1; } + /* This node is indirect if it's nexthop is as well */ + + if(c->node->options & OPTION_INDIRECT) + options |= OPTION_INDIRECT; + /* Lookup nodes */ + prevhop = lookup_node(prevhopname); + + if(!prevhop) + { + prevhop = new_node(); + prevhop->name = xstrdup(prevhopname); + node_add(prevhop); + } + + via = lookup_node(vianame); + + if(!via) + { + via = new_node(); + via->name = xstrdup(vianame); + node_add(via); + } + n = lookup_node(name); if(!n) @@ -98,19 +127,40 @@ cp n->options = options; n->distance = distance; n->nexthop = c->node; + n->prevhop = prevhop; + n->via = via; node_add(n); + if(prevhop == myself) + { + syslog(LOG_WARNING, _("Got ADD_NODE %s prevhop %s via %s from %s, sending back a DEL_NODE!"), name, prevhopname, vianame, c->name); + // send_del_node(c, n); + return 0; + } + n->status.reachable = 1; } else { // If this ADD_NODE is closer or more direct, use it instead of the old one. - if((n->options & OPTION_INDIRECT) && !(options & OPTION_INDIRECT) || n->distance > distance) + if(!n->status.reachable || ((n->options & OPTION_INDIRECT) && !(options & OPTION_INDIRECT)) || n->distance > distance) { - free(n->hostname); + if(prevhop == myself) + { + syslog(LOG_WARNING, _("Got ADD_NODE %s prevhop %s via %s from %s!"), name, prevhopname, vianame, c->name); + // send_del_node(c, n); + return 0; + } + node = avl_unlink(node_udp_tree, n); n->address = str2sockaddr(address, port); + avl_insert_node(node_udp_tree, node); + if(n->hostname) + free(n->hostname); n->hostname = sockaddr2hostname(&n->address); n->options = options; n->distance = distance; - n->nexthop = c->node; + n->via = n->nexthop = c->node; + n->status.reachable = 1; + n->status.validkey = 0; + n->status.waitingforkey = 0; } else // Otherwise, just ignore it. @@ -133,17 +183,18 @@ cp int send_del_node(connection_t *c, node_t *n) { cp - return send_request(c, "%d %s", DEL_NODE, n->name); + return send_request(c, "%d %s %s", DEL_NODE, n->name, n->prevhop->name); } int del_node_h(connection_t *c) { char name[MAX_STRING_SIZE]; - node_t *n; + char prevhopname[MAX_STRING_SIZE]; + node_t *n, *prevhop; connection_t *other; avl_node_t *node; cp - if(sscanf(c->buffer, "%*d "MAX_STRING, name) != 1) + if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, prevhopname) != 2) { syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_NODE", c->name, c->hostname); @@ -161,8 +212,9 @@ cp /* Lookup nodes */ n = lookup_node(name); - - if(!n) + prevhop = lookup_node(prevhopname); + + if(!n || !prevhop) { if(debug_lvl >= DEBUG_PROTOCOL) syslog(LOG_WARNING, _("Got %s from %s (%s) which does not appear in the node tree"), "DEL_NODE", c->name, c->hostname); @@ -185,11 +237,10 @@ cp send_del_node(other, n); } - /* Delete the node */ + /* "Delete" the node */ - node_del(n); - - exit: + n->status.reachable = 0; + n->status.validkey = 0; cp return 0; }