Merge branch 'master' into 1.1
[tinc] / src / net.c
index 10a2d20..1a45041 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -1,7 +1,7 @@
 /*
     net.c -- most of the network code
     Copyright (C) 1998-2005 Ivo Timmermans,
-                  2000-2011 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2012 Guus Sliepen <guus@tinc-vpn.org>
                   2006      Scott Lamb <slamb@slamb.org>
                  2011      Loïc Grenié <loic.grenie@gmail.com>
 
@@ -113,7 +113,7 @@ void terminate_connection(connection_t *c, bool report) {
 
        c->status.active = false;
 
-       if(c->node)
+       if(c->node && c->node->connection == c)
                c->node->connection = NULL;
 
        if(c->edge) {
@@ -121,6 +121,7 @@ void terminate_connection(connection_t *c, bool report) {
                        send_del_edge(everyone, c->edge);
 
                edge_del(c->edge);
+               c->edge = NULL;
 
                /* Run MST and SSSP algorithms */
 
@@ -139,12 +140,15 @@ void terminate_connection(connection_t *c, bool report) {
                }
        }
 
-       /* Check if this was our outgoing connection */
+       free_connection_partially(c);
 
-       if(c->outgoing)
-               retry_outgoing(c->outgoing);
+       /* Check if this was our outgoing connection */
 
-       connection_del(c);
+       if(c->outgoing) {
+               do_outgoing_connection(c);
+       } else {
+               connection_del(c);
+        }
 }
 
 /*
@@ -171,7 +175,7 @@ static void timeout_handler(int fd, short events, void *event) {
                        if(c->status.active) {
                                if(c->status.pinged) {
                                        logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds",
-                                                          c->name, c->hostname, now - c->last_ping_time);
+                                                          c->name, c->hostname, (long)now - c->last_ping_time);
                                        terminate_connection(c, true);
                                        continue;
                                } else if(c->last_ping_time + pinginterval <= now) {
@@ -272,6 +276,16 @@ int reload_configuration(void) {
                return EINVAL;
        }
 
+       read_config_options(config_tree, NULL);
+
+        xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
+        read_config_file(config_tree, fname);
+       free(fname);    
+
+       /* Parse some options that are allowed to be changed while tinc is running */
+
+       setup_myself_reloadable();
+
        /* Close connections to hosts that have a changed or deleted host config file */
        
        for(node = connection_tree->head; node; node = next) {
@@ -289,7 +303,7 @@ int reload_configuration(void) {
                        c->outgoing = NULL;
                }
                
-               xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
+               xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
                if(stat(fname, &s) || s.st_mtime > last_config_check)
                        terminate_connection(c, c->status.active);
                free(fname);
@@ -302,7 +316,6 @@ int reload_configuration(void) {
        if(strictsubnets) {
                subnet_t *subnet;
 
-
                for(node = subnet_tree->head; node; node = node->next) {
                        subnet = node->data;
                        subnet->expires = 1;
@@ -326,6 +339,48 @@ int reload_configuration(void) {
                                        subnet_update(subnet->owner, subnet, true);
                        }
                }
+       } else { /* Only read our own subnets back in */
+               subnet_t *subnet, *s2;
+
+               for(node = myself->subnet_tree->head; node; node = node->next) {
+                       subnet_t *subnet = node->data;
+                       logger(DEBUG_ALWAYS, LOG_DEBUG, "subnet %p expires %d\n", subnet, (int)subnet->expires);
+                       if(!subnet->expires)
+                               subnet->expires = 1;
+               }
+
+               config_t *cfg = lookup_config(config_tree, "Subnet");
+
+               while(cfg) {
+                       if(!get_config_subnet(cfg, &subnet))
+                               continue;
+
+                       if((s2 = lookup_subnet(myself, subnet))) {
+                               logger(DEBUG_ALWAYS, LOG_DEBUG, "read subnet that already exists: %p expires %d\n", s2, (int)s2->expires);
+                               if(s2->expires == 1)
+                                       s2->expires = 0;
+
+                               free_subnet(subnet);
+                       } else {
+                               logger(DEBUG_ALWAYS, LOG_DEBUG, "read new subnet %p", subnet);
+                               subnet_add(myself, subnet);
+                               send_add_subnet(everyone, subnet);
+                               subnet_update(myself, subnet, true);
+                       }
+
+                       cfg = lookup_config_next(config_tree, cfg);
+               }
+
+               for(node = myself->subnet_tree->head; node; node = next) {
+                       next = node->next;
+                       subnet_t *subnet = node->data;
+                       if(subnet->expires == 1) {
+                               logger(DEBUG_ALWAYS, LOG_DEBUG, "removed subnet %p", subnet);
+                               send_del_subnet(everyone, subnet);
+                               subnet_update(myself, subnet, false);
+                               subnet_del(myself, subnet);
+                       }
+               }
        }
 
        /* Try to make outgoing connections */
@@ -337,9 +392,10 @@ int reload_configuration(void) {
 
 void retry(void) {
        connection_t *c;
-       splay_node_t *node;
+       splay_node_t *node, *next;
 
-       for(node = connection_tree->head; node; node = node->next) {
+       for(node = connection_tree->head; node; node = next) {
+               next = node->next;
                c = node->data;
                
                if(c->outgoing && !c->node) {