X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fnet.c;h=1b3d230eb4dff87b40d3e945016f9f783a3cfb71;hp=c4637dabf1633585e06fde49dcaaeb87a069391b;hb=fe84fafcb684391739a1b3366705c58683210392;hpb=714fb32d0377ed9f5643ed8f0bd914843d12266b diff --git a/src/net.c b/src/net.c index c4637dab..1b3d230e 100644 --- a/src/net.c +++ b/src/net.c @@ -1,7 +1,7 @@ /* net.c -- most of the network code - Copyright (C) 1998-2003 Ivo Timmermans , - 2000-2003 Guus Sliepen + Copyright (C) 1998-2004 Ivo Timmermans , + 2000-2004 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 @@ -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: net.c,v 1.35.4.194 2003/07/29 10:50:15 guus Exp $ + $Id$ */ #include "system.h" @@ -39,8 +39,10 @@ #include "protocol.h" #include "route.h" #include "subnet.h" +#include "xalloc.h" bool do_purge = false; +volatile bool running = false; time_t now = 0; @@ -57,9 +59,11 @@ static void purge(void) ifdebug(PROTOCOL) logger(LOG_DEBUG, _("Purging unreachable nodes")); + /* Remove all edges and subnets owned by unreachable nodes. */ + for(nnode = node_tree->head; nnode; nnode = nnext) { nnext = nnode->next; - n = (node_t *) nnode->data; + n = nnode->data; if(!n->status.reachable) { ifdebug(SCARY_THINGS) logger(LOG_DEBUG, _("Purging node %s (%s)"), n->name, @@ -67,19 +71,39 @@ static void purge(void) for(snode = n->subnet_tree->head; snode; snode = snext) { snext = snode->next; - s = (subnet_t *) snode->data; - send_del_subnet(broadcast, s); + s = snode->data; + if(!tunnelserver) + send_del_subnet(broadcast, s); subnet_del(n, s); } for(enode = n->edge_tree->head; enode; enode = enext) { enext = enode->next; - e = (edge_t *) enode->data; - send_del_edge(broadcast, e); + e = enode->data; + if(!tunnelserver) + send_del_edge(broadcast, e); edge_del(e); } + } + } + + /* Check if anyone else claims to have an edge to an unreachable node. If not, delete node. */ + + for(nnode = node_tree->head; nnode; nnode = nnext) { + nnext = nnode->next; + n = nnode->data; + + if(!n->status.reachable) { + for(enode = edge_weight_tree->head; enode; enode = enext) { + enext = enode->next; + e = enode->data; + + if(e->to == n) + break; + } - node_del(n); + if(!enode) + node_del(n); } } } @@ -100,7 +124,7 @@ static int build_fdset(fd_set * fs) for(node = connection_tree->head; node; node = next) { next = node->next; - c = (connection_t *) node->data; + c = node->data; if(c->status.remove) { connection_del(c); @@ -153,10 +177,10 @@ void terminate_connection(connection_t *c, bool report) c->node->connection = NULL; if(c->socket) - close(c->socket); + closesocket(c->socket); if(c->edge) { - if(report) + if(report && !tunnelserver) send_del_edge(broadcast, c->edge); edge_del(c->edge); @@ -164,6 +188,18 @@ void terminate_connection(connection_t *c, bool report) /* Run MST and SSSP algorithms */ graph(); + + /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */ + + if(report && !c->node->status.reachable) { + edge_t *e; + e = lookup_edge(c->node, myself); + if(e) { + if(!tunnelserver) + send_del_edge(broadcast, e); + edge_del(e); + } + } } /* Check if this was our outgoing connection */ @@ -191,7 +227,7 @@ static void check_dead_connections(void) for(node = connection_tree->head; node; node = next) { next = node->next; - c = (connection_t *) node->data; + c = node->data; if(c->last_ping_time + pingtimeout < now) { if(c->status.active) { @@ -212,7 +248,13 @@ static void check_dead_connections(void) } ifdebug(CONNECTIONS) logger(LOG_WARNING, _("Timeout from %s (%s) during authentication"), c->name, c->hostname); - terminate_connection(c, false); + if(c->status.connecting) { + c->status.connecting = false; + closesocket(c->socket); + do_outgoing_connection(c); + } else { + terminate_connection(c, false); + } } } } @@ -234,11 +276,11 @@ static void check_network_activity(fd_set * f) if(FD_ISSET(device_fd, f)) { if(read_packet(&packet)) - route_outgoing(&packet); + route(myself, &packet); } for(node = connection_tree->head; node; node = node->next) { - c = (connection_t *) node->data; + c = node->data; if(c->status.remove) continue; @@ -254,7 +296,7 @@ static void check_network_activity(fd_set * f) ifdebug(CONNECTIONS) logger(LOG_DEBUG, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(result)); - close(c->socket); + closesocket(c->socket); do_outgoing_connection(c); continue; } @@ -279,7 +321,7 @@ static void check_network_activity(fd_set * f) /* this is where it all happens... */ -void main_loop(void) +int main_loop(void) { fd_set fset; struct timeval tv; @@ -293,10 +335,13 @@ void main_loop(void) last_config_check = now; srand(now); - for(;;) { + running = true; + + while(running) { now = time(NULL); - tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */ + // tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */ + tv.tv_sec = 1; tv.tv_usec = 0; maxfd = build_fdset(&fset); @@ -309,7 +354,7 @@ void main_loop(void) strerror(errno)); cp_trace(); dump_connections(); - return; + return 1; } continue; @@ -329,7 +374,7 @@ void main_loop(void) last_ping_check = now; if(routing_mode == RMODE_SWITCH) - age_mac(); + age_subnets(); age_past_requests(); @@ -356,7 +401,7 @@ void main_loop(void) logger(LOG_INFO, _("Flushing event queue")); while(event_tree->head) { - event = (event_t *) event_tree->head->data; + event = event_tree->head->data; event->handler(event->data); event_del(event); } @@ -378,13 +423,13 @@ void main_loop(void) if(!read_server_config()) { logger(LOG_ERR, _("Unable to reread configuration file, exitting.")); - exit(1); + return 1; } /* Close connections to hosts that have a changed or deleted host config file */ for(node = connection_tree->head; node; node = node->next) { - c = (connection_t *) node->data; + c = node->data; if(c->outgoing) { free(c->outgoing->name); @@ -404,8 +449,8 @@ void main_loop(void) /* Try to make outgoing connections */ try_outgoing_connections(); - - continue; } } + + return 0; }