From: Guus Sliepen Date: Mon, 2 Sep 2002 22:40:42 +0000 (+0000) Subject: Replacement for the current routing algorithm. X-Git-Tag: release-1.0pre8~41 X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=commitdiff_plain;h=2cb21f8810a6e0241a80623e991c8308b603ae95;hp=f2c2443bbcfd5e09518bd87f3fd8d4a727d73ae2 Replacement for the current routing algorithm. --- diff --git a/src/protocol_node.c b/src/protocol_node.c new file mode 100644 index 00000000..3d0355fd --- /dev/null +++ b/src/protocol_node.c @@ -0,0 +1,195 @@ +/* + protocol_node.c -- handle the meta-protocol, nodes + Copyright (C) 1999-2002 Ivo Timmermans , + 2000-2002 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + 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 $ +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "conf.h" +#include "net.h" +#include "netutl.h" +#include "protocol.h" +#include "meta.h" +#include "connection.h" +#include "node.h" + +#include "system.h" + +int send_add_node(connection_t *c, node_t *n) +{ + int x; + char *address, *port; +cp + sockaddr2str(&n->address, &address, &port); + x = send_request(c, "%d %s %s %s %lx %d", ADD_NODE, + n->name, address, port, + n->options, n->distance + 1); + free(address); + free(port); +cp + return x; +} + +int add_node_h(connection_t *c) +{ + connection_t *other; + node_t *n; + char name[MAX_STRING_SIZE]; + char address[MAX_STRING_SIZE]; + char port[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) + { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_NODE", c->name, c->hostname); + return -1; + } + + /* Check if names are valid */ + + if(check_id(name)) + { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_NODE", c->name, c->hostname, _("invalid name")); + return -1; + } + + /* Lookup nodes */ + + n = lookup_node(name); + + if(!n) + { + // It's a new node. Add it and tell the others. + n = new_node(); + n->name = xstrdup(name); + n->address = str2sockaddr(address, port); + n->hostname = sockaddr2hostname(&n->address); + n->options = options; + n->distance = distance; + n->nexthop = c->node; + node_add(n); + } + 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) + { + free(n->hostname); + n->address = str2sockaddr(address, port); + n->hostname = sockaddr2hostname(&n->address); + n->options = options; + n->distance = distance; + n->nexthop = c->node; + } + else + // Otherwise, just ignore it. + return 0; + } + + /* Tell the rest about the new node */ + + for(node = connection_tree->head; node; node = node->next) + { + other = (connection_t *)node->data; + if(other->status.active && other != c) + send_add_node(other, n); + } + +cp + return 0; +} + +int send_del_node(connection_t *c, node_t *n) +{ +cp + return send_request(c, "%d %s", DEL_NODE, n->name); +} + +int del_node_h(connection_t *c) +{ + char name[MAX_STRING_SIZE]; + node_t *n; + connection_t *other; + avl_node_t *node; +cp + if(sscanf(c->buffer, "%*d "MAX_STRING, name) != 1) + { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_NODE", + c->name, c->hostname); + return -1; + } + + /* Check if names are valid */ + + if(check_id(name)) + { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_NODE", c->name, c->hostname, _("invalid name")); + return -1; + } + + /* Lookup nodes */ + + n = lookup_node(name); + + if(!n) + { + 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); + return 0; + } + + /* If we got a DEL_NODE but we know of a different route to it, tell the one who send the DEL_NODE */ + + if(n->nexthop != c->node) + { + return send_add_node(c, n); + } + + /* Otherwise, tell the rest about the deleted node */ + + for(node = connection_tree->head; node; node = node->next) + { + other = (connection_t *)node->data; + if(other->status.active && other != c) + send_del_node(other, n); + } + + /* Delete the node */ + + node_del(n); + + exit: +cp + return 0; +}