Use xoshiro256** to generate pseudo-random numbers.
[tinc] / src / net_setup.c
index f1a70f3..43895dd 100644 (file)
 #include "system.h"
 
 #include "cipher.h"
+#include "conf_net.h"
 #include "conf.h"
 #include "connection.h"
+#include "compression.h"
 #include "control.h"
+#include "crypto.h"
 #include "device.h"
 #include "digest.h"
 #include "ecdsa.h"
 #include "process.h"
 #include "protocol.h"
 #include "route.h"
-#include "rsa.h"
 #include "script.h"
 #include "subnet.h"
 #include "utils.h"
 #include "xalloc.h"
+#include "keys.h"
 
 #ifdef HAVE_MINIUPNPC
 #include "upnp.h"
@@ -69,20 +72,20 @@ bool node_read_ecdsa_public_key(node_t *n) {
                return true;
        }
 
-       splay_tree_t *config_tree;
        FILE *fp;
        char *pubname = NULL;
        char *p;
 
-       init_configuration(&config_tree);
+       splay_tree_t config;
+       init_configuration(&config);
 
-       if(!read_host_config(config_tree, n->name, true)) {
+       if(!read_host_config(&config, n->name, true)) {
                goto exit;
        }
 
        /* First, check for simple Ed25519PublicKey statement */
 
-       if(get_config_string(lookup_config(config_tree, "Ed25519PublicKey"), &p)) {
+       if(get_config_string(lookup_config(&config, "Ed25519PublicKey"), &p)) {
                n->ecdsa = ecdsa_set_base64_public_key(p);
                free(p);
                goto exit;
@@ -90,7 +93,7 @@ bool node_read_ecdsa_public_key(node_t *n) {
 
        /* Else, check for Ed25519PublicKeyFile statement and read it */
 
-       if(!get_config_string(lookup_config(config_tree, "Ed25519PublicKeyFile"), &pubname)) {
+       if(!get_config_string(lookup_config(&config, "Ed25519PublicKeyFile"), &pubname)) {
                xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, n->name);
        }
 
@@ -104,151 +107,11 @@ bool node_read_ecdsa_public_key(node_t *n) {
        fclose(fp);
 
 exit:
-       exit_configuration(&config_tree);
+       splay_empty_tree(&config);
        free(pubname);
        return n->ecdsa;
 }
 
-bool read_ecdsa_public_key(connection_t *c) {
-       if(ecdsa_active(c->ecdsa)) {
-               return true;
-       }
-
-       FILE *fp;
-       char *fname;
-       char *p;
-
-       if(!c->config_tree) {
-               init_configuration(&c->config_tree);
-
-               if(!read_host_config(c->config_tree, c->name, true)) {
-                       return false;
-               }
-       }
-
-       /* First, check for simple Ed25519PublicKey statement */
-
-       if(get_config_string(lookup_config(c->config_tree, "Ed25519PublicKey"), &p)) {
-               c->ecdsa = ecdsa_set_base64_public_key(p);
-               free(p);
-               return c->ecdsa;
-       }
-
-       /* Else, check for Ed25519PublicKeyFile statement and read it */
-
-       if(!get_config_string(lookup_config(c->config_tree, "Ed25519PublicKeyFile"), &fname)) {
-               xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
-       }
-
-       fp = fopen(fname, "r");
-
-       if(!fp) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 public key file `%s': %s",
-                      fname, strerror(errno));
-               free(fname);
-               return false;
-       }
-
-       c->ecdsa = ecdsa_read_pem_public_key(fp);
-
-       if(!c->ecdsa && errno != ENOENT) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Parsing Ed25519 public key file `%s' failed.", fname);
-       }
-
-       fclose(fp);
-       free(fname);
-       return c->ecdsa;
-}
-
-#ifndef DISABLE_LEGACY
-bool read_rsa_public_key(connection_t *c) {
-       FILE *fp;
-       char *fname;
-       char *n;
-
-       /* First, check for simple PublicKey statement */
-
-       if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &n)) {
-               c->rsa = rsa_set_hex_public_key(n, "FFFF");
-               free(n);
-               return c->rsa;
-       }
-
-       /* Else, check for PublicKeyFile statement and read it */
-
-       if(!get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) {
-               xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
-       }
-
-       fp = fopen(fname, "r");
-
-       if(!fp) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno));
-               free(fname);
-               return false;
-       }
-
-       c->rsa = rsa_read_pem_public_key(fp);
-       fclose(fp);
-
-       if(!c->rsa) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA public key file `%s' failed: %s", fname, strerror(errno));
-       }
-
-       free(fname);
-       return c->rsa;
-}
-#endif
-
-static bool read_ecdsa_private_key(void) {
-       FILE *fp;
-       char *fname;
-
-       /* Check for PrivateKeyFile statement and read it */
-
-       if(!get_config_string(lookup_config(config_tree, "Ed25519PrivateKeyFile"), &fname)) {
-               xasprintf(&fname, "%s" SLASH "ed25519_key.priv", confbase);
-       }
-
-       fp = fopen(fname, "r");
-
-       if(!fp) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Error reading Ed25519 private key file `%s': %s", fname, strerror(errno));
-
-               if(errno == ENOENT) {
-                       logger(DEBUG_ALWAYS, LOG_INFO, "Create an Ed25519 key pair with `tinc -n %s generate-ed25519-keys'.", netname ? netname : ".");
-               }
-
-               free(fname);
-               return false;
-       }
-
-#ifndef HAVE_MINGW
-       struct stat s;
-
-       if(fstat(fileno(fp), &s)) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat Ed25519 private key file `%s': %s'", fname, strerror(errno));
-               free(fname);
-               return false;
-       }
-
-       if(s.st_mode & ~0100700u) {
-               logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for Ed25519 private key file `%s'!", fname);
-       }
-
-#endif
-
-       myself->connection->ecdsa = ecdsa_read_pem_private_key(fp);
-       fclose(fp);
-
-       if(!myself->connection->ecdsa) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
-       }
-
-       free(fname);
-       return myself->connection->ecdsa;
-}
-
 static bool read_invitation_key(void) {
        FILE *fp;
        char fname[PATH_MAX];
@@ -274,81 +137,13 @@ static bool read_invitation_key(void) {
        return invitation_key;
 }
 
-#ifndef DISABLE_LEGACY
-static bool read_rsa_private_key(void) {
-       FILE *fp;
-       char *fname;
-       char *n, *d;
-
-       /* First, check for simple PrivateKey statement */
-
-       if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) {
-               if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) {
-                       logger(DEBUG_ALWAYS, LOG_ERR, "PrivateKey used but no PublicKey found!");
-                       free(d);
-                       return false;
-               }
-
-               myself->connection->rsa = rsa_set_hex_private_key(n, "FFFF", d);
-               free(n);
-               free(d);
-               return myself->connection->rsa;
-       }
-
-       /* Else, check for PrivateKeyFile statement and read it */
-
-       if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) {
-               xasprintf(&fname, "%s" SLASH "rsa_key.priv", confbase);
-       }
-
-       fp = fopen(fname, "r");
-
-       if(!fp) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s",
-                      fname, strerror(errno));
-
-               if(errno == ENOENT) {
-                       logger(DEBUG_ALWAYS, LOG_INFO, "Create an RSA key pair with `tinc -n %s generate-rsa-keys'.", netname ? netname : ".");
-               }
-
-               free(fname);
-               return false;
-       }
-
-#ifndef HAVE_MINGW
-       struct stat s;
-
-       if(fstat(fileno(fp), &s)) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno));
-               free(fname);
-               return false;
-       }
-
-       if(s.st_mode & ~0100700u) {
-               logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
-       }
-
-#endif
-
-       myself->connection->rsa = rsa_read_pem_private_key(fp);
-       fclose(fp);
-
-       if(!myself->connection->rsa) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA private key file `%s' failed: %s", fname, strerror(errno));
-       }
-
-       free(fname);
-       return myself->connection->rsa;
-}
-#endif
-
 #ifndef DISABLE_LEGACY
 static timeout_t keyexpire_timeout;
 
 static void keyexpire_handler(void *data) {
        regenerate_key();
        timeout_set(data, &(struct timeval) {
-               keylifetime, rand() % 100000
+               keylifetime, jitter()
        });
 }
 #endif
@@ -357,7 +152,7 @@ void regenerate_key(void) {
        logger(DEBUG_STATUS, LOG_INFO, "Expiring symmetric keys");
        send_key_changed();
 
-       for splay_each(node_t, n, node_tree) {
+       for splay_each(node_t, n, &node_tree) {
                n->status.validkey_in = false;
        }
 }
@@ -382,10 +177,10 @@ void load_all_nodes(void) {
 
                node_t *n = lookup_node(ent->d_name);
 
-               splay_tree_t *config_tree;
-               init_configuration(&config_tree);
-               read_config_options(config_tree, ent->d_name);
-               read_host_config(config_tree, ent->d_name, true);
+               splay_tree_t config;
+               init_configuration(&config);
+               read_config_options(&config, ent->d_name);
+               read_host_config(&config, ent->d_name, true);
 
                if(!n) {
                        n = new_node();
@@ -394,7 +189,7 @@ void load_all_nodes(void) {
                }
 
                if(strictsubnets) {
-                       for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+                       for(config_t *cfg = lookup_config(&config, "Subnet"); cfg; cfg = lookup_config_next(&config, cfg)) {
                                subnet_t *s, *s2;
 
                                if(!get_config_subnet(cfg, &s)) {
@@ -410,11 +205,11 @@ void load_all_nodes(void) {
                        }
                }
 
-               if(lookup_config(config_tree, "Address")) {
+               if(lookup_config(&config, "Address")) {
                        n->status.has_address = true;
                }
 
-               exit_configuration(&config_tree);
+               splay_empty_tree(&config);
        }
 
        closedir(dir);
@@ -424,7 +219,7 @@ char *get_name(void) {
        char *name = NULL;
        char *returned_name;
 
-       get_config_string(lookup_config(config_tree, "Name"), &name);
+       get_config_string(lookup_config(&config_tree, "Name"), &name);
 
        if(!name) {
                return NULL;
@@ -439,17 +234,17 @@ bool setup_myself_reloadable(void) {
        free(scriptinterpreter);
        scriptinterpreter = NULL;
 
-       get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter);
+       get_config_string(lookup_config(&config_tree, "ScriptsInterpreter"), &scriptinterpreter);
 
        free(scriptextension);
 
-       if(!get_config_string(lookup_config(config_tree, "ScriptsExtension"), &scriptextension)) {
+       if(!get_config_string(lookup_config(&config_tree, "ScriptsExtension"), &scriptextension)) {
                scriptextension = xstrdup("");
        }
 
        char *proxy = NULL;
 
-       get_config_string(lookup_config(config_tree, "Proxy"), &proxy);
+       get_config_string(lookup_config(&config_tree, "Proxy"), &proxy);
 
        if(proxy) {
                char *space;
@@ -548,11 +343,11 @@ bool setup_myself_reloadable(void) {
 
        bool choice;
 
-       if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) {
+       if(get_config_bool(lookup_config(&config_tree, "IndirectData"), &choice) && choice) {
                myself->options |= OPTION_INDIRECT;
        }
 
-       if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) {
+       if(get_config_bool(lookup_config(&config_tree, "TCPOnly"), &choice) && choice) {
                myself->options |= OPTION_TCPONLY;
        }
 
@@ -560,20 +355,20 @@ bool setup_myself_reloadable(void) {
                myself->options |= OPTION_INDIRECT;
        }
 
-       get_config_bool(lookup_config(config_tree, "UDPDiscovery"), &udp_discovery);
-       get_config_int(lookup_config(config_tree, "UDPDiscoveryKeepaliveInterval"), &udp_discovery_keepalive_interval);
-       get_config_int(lookup_config(config_tree, "UDPDiscoveryInterval"), &udp_discovery_interval);
-       get_config_int(lookup_config(config_tree, "UDPDiscoveryTimeout"), &udp_discovery_timeout);
+       get_config_bool(lookup_config(&config_tree, "UDPDiscovery"), &udp_discovery);
+       get_config_int(lookup_config(&config_tree, "UDPDiscoveryKeepaliveInterval"), &udp_discovery_keepalive_interval);
+       get_config_int(lookup_config(&config_tree, "UDPDiscoveryInterval"), &udp_discovery_interval);
+       get_config_int(lookup_config(&config_tree, "UDPDiscoveryTimeout"), &udp_discovery_timeout);
 
-       get_config_int(lookup_config(config_tree, "MTUInfoInterval"), &mtu_info_interval);
-       get_config_int(lookup_config(config_tree, "UDPInfoInterval"), &udp_info_interval);
+       get_config_int(lookup_config(&config_tree, "MTUInfoInterval"), &mtu_info_interval);
+       get_config_int(lookup_config(&config_tree, "UDPInfoInterval"), &udp_info_interval);
 
-       get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
-       get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery);
+       get_config_bool(lookup_config(&config_tree, "DirectOnly"), &directonly);
+       get_config_bool(lookup_config(&config_tree, "LocalDiscovery"), &localdiscovery);
 
        char *rmode = NULL;
 
-       if(get_config_string(lookup_config(config_tree, "Mode"), &rmode)) {
+       if(get_config_string(lookup_config(&config_tree, "Mode"), &rmode)) {
                if(!strcasecmp(rmode, "router")) {
                        routing_mode = RMODE_ROUTER;
                } else if(!strcasecmp(rmode, "switch")) {
@@ -591,7 +386,7 @@ bool setup_myself_reloadable(void) {
 
        char *fmode = NULL;
 
-       if(get_config_string(lookup_config(config_tree, "Forwarding"), &fmode)) {
+       if(get_config_string(lookup_config(&config_tree, "Forwarding"), &fmode)) {
                if(!strcasecmp(fmode, "off")) {
                        forwarding_mode = FMODE_OFF;
                } else if(!strcasecmp(fmode, "internal")) {
@@ -608,25 +403,25 @@ bool setup_myself_reloadable(void) {
        }
 
        choice = !(myself->options & OPTION_TCPONLY);
-       get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
+       get_config_bool(lookup_config(&config_tree, "PMTUDiscovery"), &choice);
 
        if(choice) {
                myself->options |= OPTION_PMTU_DISCOVERY;
        }
 
        choice = true;
-       get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
+       get_config_bool(lookup_config(&config_tree, "ClampMSS"), &choice);
 
        if(choice) {
                myself->options |= OPTION_CLAMP_MSS;
        }
 
-       get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
-       get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
+       get_config_bool(lookup_config(&config_tree, "PriorityInheritance"), &priorityinheritance);
+       get_config_bool(lookup_config(&config_tree, "DecrementTTL"), &decrement_ttl);
 
        char *bmode = NULL;
 
-       if(get_config_string(lookup_config(config_tree, "Broadcast"), &bmode)) {
+       if(get_config_string(lookup_config(&config_tree, "Broadcast"), &bmode)) {
                if(!strcasecmp(bmode, "no")) {
                        broadcast_mode = BMODE_NONE;
                } else if(!strcasecmp(bmode, "yes") || !strcasecmp(bmode, "mst")) {
@@ -644,9 +439,9 @@ bool setup_myself_reloadable(void) {
 
        /* Delete all broadcast subnets before re-adding them */
 
-       for splay_each(subnet_t, s, subnet_tree) {
+       for splay_each(subnet_t, s, &subnet_tree) {
                if(!s->owner) {
-                       splay_delete_node(subnet_tree, node);
+                       splay_delete_node(&subnet_tree, node);
                }
        }
 
@@ -662,7 +457,7 @@ bool setup_myself_reloadable(void) {
                subnet_add(NULL, s);
        }
 
-       for(config_t *cfg = lookup_config(config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+       for(config_t *cfg = lookup_config(&config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
                subnet_t *s;
 
                if(!get_config_subnet(cfg, &s)) {
@@ -688,11 +483,11 @@ bool setup_myself_reloadable(void) {
 
 #endif
 
-       if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) {
+       if(!get_config_int(lookup_config(&config_tree, "MACExpire"), &macexpire)) {
                macexpire = 600;
        }
 
-       if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
+       if(get_config_int(lookup_config(&config_tree, "MaxTimeout"), &maxtimeout)) {
                if(maxtimeout <= 0) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Bogus maximum timeout!");
                        return false;
@@ -703,7 +498,7 @@ bool setup_myself_reloadable(void) {
 
        char *afname = NULL;
 
-       if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
+       if(get_config_string(lookup_config(&config_tree, "AddressFamily"), &afname)) {
                if(!strcasecmp(afname, "IPv4")) {
                        addressfamily = AF_INET;
                } else if(!strcasecmp(afname, "IPv6")) {
@@ -719,19 +514,19 @@ bool setup_myself_reloadable(void) {
                free(afname);
        }
 
-       get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);
+       get_config_bool(lookup_config(&config_tree, "Hostnames"), &hostnames);
 
-       if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) {
+       if(!get_config_int(lookup_config(&config_tree, "KeyExpire"), &keylifetime)) {
                keylifetime = 3600;
        }
 
-       if(!get_config_bool(lookup_config(config_tree, "AutoConnect"), &autoconnect)) {
+       if(!get_config_bool(lookup_config(&config_tree, "AutoConnect"), &autoconnect)) {
                autoconnect = true;
        }
 
-       get_config_bool(lookup_config(config_tree, "DisableBuggyPeers"), &disablebuggypeers);
+       get_config_bool(lookup_config(&config_tree, "DisableBuggyPeers"), &disablebuggypeers);
 
-       if(!get_config_int(lookup_config(config_tree, "InvitationExpire"), &invitation_lifetime)) {
+       if(!get_config_int(lookup_config(&config_tree, "InvitationExpire"), &invitation_lifetime)) {
                invitation_lifetime = 604800;        // 1 week
        }
 
@@ -875,9 +670,9 @@ static bool setup_myself(void) {
        myself->connection = new_connection();
        myself->name = name;
        myself->connection->name = xstrdup(name);
-       read_host_config(config_tree, name, true);
+       read_host_config(&config_tree, name, true);
 
-       if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) {
+       if(!get_config_string(lookup_config(&config_tree, "Port"), &myport)) {
                myport = xstrdup("655");
        } else {
                port_specified = true;
@@ -890,7 +685,8 @@ static bool setup_myself(void) {
        myself->options |= PROT_MINOR << 24;
 
 #ifdef DISABLE_LEGACY
-       experimental = read_ecdsa_private_key();
+       myself->connection->ecdsa = read_ecdsa_private_key(&config_tree, NULL);
+       experimental = myself->connection->ecdsa != NULL;
 
        if(!experimental) {
                logger(DEBUG_ALWAYS, LOG_ERR, "No private key available, cannot start tinc!");
@@ -899,19 +695,26 @@ static bool setup_myself(void) {
 
 #else
 
-       if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) {
-               experimental = read_ecdsa_private_key();
+       if(!get_config_bool(lookup_config(&config_tree, "ExperimentalProtocol"), &experimental)) {
+               myself->connection->ecdsa = read_ecdsa_private_key(&config_tree, NULL);
+               experimental = myself->connection->ecdsa != NULL;
 
                if(!experimental) {
                        logger(DEBUG_ALWAYS, LOG_WARNING, "Support for SPTPS disabled.");
                }
        } else {
-               if(experimental && !read_ecdsa_private_key()) {
-                       return false;
+               if(experimental) {
+                       myself->connection->ecdsa = read_ecdsa_private_key(&config_tree, NULL);
+
+                       if(!myself->connection->ecdsa) {
+                               return false;
+                       }
                }
        }
 
-       if(!read_rsa_private_key()) {
+       myself->connection->rsa = read_rsa_private_key(&config_tree, NULL);
+
+       if(!myself->connection->rsa) {
                if(experimental) {
                        logger(DEBUG_ALWAYS, LOG_WARNING, "Support for legacy protocol disabled.");
                } else {
@@ -940,7 +743,7 @@ static bool setup_myself(void) {
 
        /* Read in all the subnets specified in the host configuration file */
 
-       for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+       for(config_t *cfg = lookup_config(&config_tree, "Subnet"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
                subnet_t *subnet;
 
                if(!get_config_subnet(cfg, &subnet)) {
@@ -956,18 +759,18 @@ static bool setup_myself(void) {
                return false;
        }
 
-       get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
-       get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
+       get_config_bool(lookup_config(&config_tree, "StrictSubnets"), &strictsubnets);
+       get_config_bool(lookup_config(&config_tree, "TunnelServer"), &tunnelserver);
        strictsubnets |= tunnelserver;
 
-       if(get_config_int(lookup_config(config_tree, "MaxConnectionBurst"), &max_connection_burst)) {
+       if(get_config_int(lookup_config(&config_tree, "MaxConnectionBurst"), &max_connection_burst)) {
                if(max_connection_burst <= 0) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "MaxConnectionBurst cannot be negative!");
                        return false;
                }
        }
 
-       if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
+       if(get_config_int(lookup_config(&config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
                if(udp_rcvbuf < 0) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "UDPRcvBuf cannot be negative!");
                        return false;
@@ -976,7 +779,7 @@ static bool setup_myself(void) {
                udp_rcvbuf_warnings = true;
        }
 
-       if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
+       if(get_config_int(lookup_config(&config_tree, "UDPSndBuf"), &udp_sndbuf)) {
                if(udp_sndbuf < 0) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "UDPSndBuf cannot be negative!");
                        return false;
@@ -985,7 +788,7 @@ static bool setup_myself(void) {
                udp_sndbuf_warnings = true;
        }
 
-       get_config_int(lookup_config(config_tree, "FWMark"), &fwmark);
+       get_config_int(lookup_config(&config_tree, "FWMark"), &fwmark);
 #ifndef SO_MARK
 
        if(fwmark) {
@@ -997,7 +800,7 @@ static bool setup_myself(void) {
 
        int replaywin_int;
 
-       if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) {
+       if(get_config_int(lookup_config(&config_tree, "ReplayWindow"), &replaywin_int)) {
                if(replaywin_int < 0) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "ReplayWindow cannot be negative!");
                        return false;
@@ -1012,28 +815,33 @@ static bool setup_myself(void) {
 
        char *cipher;
 
-       if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) {
+       if(!get_config_string(lookup_config(&config_tree, "Cipher"), &cipher)) {
                cipher = xstrdup("aes-256-cbc");
        }
 
        if(!strcasecmp(cipher, "none")) {
                myself->incipher = NULL;
-       } else if(!(myself->incipher = cipher_open_by_name(cipher))) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized cipher type!");
-               free(cipher);
-               return false;
+       } else {
+               myself->incipher = cipher_alloc();
+
+               if(!cipher_open_by_name(myself->incipher, cipher)) {
+                       logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized cipher type!");
+                       cipher_free(&myself->incipher);
+                       free(cipher);
+                       return false;
+               }
        }
 
        free(cipher);
 
        timeout_add(&keyexpire_timeout, keyexpire_handler, &keyexpire_timeout, &(struct timeval) {
-               keylifetime, rand() % 100000
+               keylifetime, jitter()
        });
 
        /* Check if we want to use message authentication codes... */
 
        int maclength = 4;
-       get_config_int(lookup_config(config_tree, "MACLength"), &maclength);
+       get_config_int(lookup_config(&config_tree, "MACLength"), &maclength);
 
        if(maclength < 0) {
                logger(DEBUG_ALWAYS, LOG_ERR, "Bogus MAC length!");
@@ -1042,26 +850,30 @@ static bool setup_myself(void) {
 
        char *digest;
 
-       if(!get_config_string(lookup_config(config_tree, "Digest"), &digest)) {
+       if(!get_config_string(lookup_config(&config_tree, "Digest"), &digest)) {
                digest = xstrdup("sha256");
        }
 
        if(!strcasecmp(digest, "none")) {
                myself->indigest = NULL;
-       } else if(!(myself->indigest = digest_open_by_name(digest, maclength))) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized digest type!");
-               free(digest);
-               return false;
+       } else {
+               myself->indigest = digest_alloc();
+
+               if(!digest_open_by_name(myself->indigest, digest, maclength)) {
+                       logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized digest type!");
+                       digest_free(&myself->indigest);
+                       free(digest);
+                       return false;
+               }
        }
 
        free(digest);
 #endif
 
        /* Compression */
-
-       if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
+       if(get_config_int(lookup_config(&config_tree, "Compression"), &myself->incompression)) {
                switch(myself->incompression) {
-               case 12:
+               case COMPRESS_LZ4:
 #ifdef HAVE_LZ4
                        break;
 #else
@@ -1070,8 +882,8 @@ static bool setup_myself(void) {
                        return false;
 #endif
 
-               case 11:
-               case 10:
+               case COMPRESS_LZO_HI:
+               case COMPRESS_LZO_LO:
 #ifdef HAVE_LZO
                        break;
 #else
@@ -1080,15 +892,15 @@ static bool setup_myself(void) {
                        return false;
 #endif
 
-               case 9:
-               case 8:
-               case 7:
-               case 6:
-               case 5:
-               case 4:
-               case 3:
-               case 2:
-               case 1:
+               case COMPRESS_ZLIB_9:
+               case COMPRESS_ZLIB_8:
+               case COMPRESS_ZLIB_7:
+               case COMPRESS_ZLIB_6:
+               case COMPRESS_ZLIB_5:
+               case COMPRESS_ZLIB_4:
+               case COMPRESS_ZLIB_3:
+               case COMPRESS_ZLIB_2:
+               case COMPRESS_ZLIB_1:
 #ifdef HAVE_ZLIB
                        break;
 #else
@@ -1097,7 +909,7 @@ static bool setup_myself(void) {
                        return false;
 #endif
 
-               case 0:
+               case COMPRESS_NONE:
                        break;
 
                default:
@@ -1106,10 +918,10 @@ static bool setup_myself(void) {
                        return false;
                }
        } else {
-               myself->incompression = 0;
+               myself->incompression = COMPRESS_NONE;
        }
 
-       myself->connection->outcompression = 0;
+       myself->connection->outcompression = COMPRESS_NONE;
 
        /* Done */
 
@@ -1128,7 +940,7 @@ static bool setup_myself(void) {
 
        devops = os_devops;
 
-       if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
+       if(get_config_string(lookup_config(&config_tree, "DeviceType"), &type)) {
                if(!strcasecmp(type, "dummy")) {
                        devops = dummy_devops;
                } else if(!strcasecmp(type, "raw_socket")) {
@@ -1158,7 +970,7 @@ static bool setup_myself(void) {
                free(type);
        }
 
-       get_config_bool(lookup_config(config_tree, "DeviceStandby"), &device_standby);
+       get_config_bool(lookup_config(&config_tree, "DeviceStandby"), &device_standby);
 
        if(!devops.setup()) {
                return false;
@@ -1217,7 +1029,7 @@ static bool setup_myself(void) {
                listen_sockets = 0;
                int cfgs = 0;
 
-               for(config_t *cfg = lookup_config(config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+               for(config_t *cfg = lookup_config(&config_tree, "BindToAddress"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
                        cfgs++;
                        get_config_string(cfg, &address);
 
@@ -1226,7 +1038,7 @@ static bool setup_myself(void) {
                        }
                }
 
-               for(config_t *cfg = lookup_config(config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
+               for(config_t *cfg = lookup_config(&config_tree, "ListenAddress"); cfg; cfg = lookup_config_next(&config_tree, cfg)) {
                        cfgs++;
                        get_config_string(cfg, &address);
 
@@ -1266,7 +1078,7 @@ static bool setup_myself(void) {
        myself->connection->hostname = xstrdup(myself->hostname);
 
        char *upnp = NULL;
-       get_config_string(lookup_config(config_tree, "UPnP"), &upnp);
+       get_config_string(lookup_config(&config_tree, "UPnP"), &upnp);
        bool upnp_tcp = false;
        bool upnp_udp = false;
 
@@ -1301,11 +1113,8 @@ static bool setup_myself(void) {
 bool setup_network(void) {
        init_connections();
        init_subnets();
-       init_nodes();
-       init_edges();
-       init_requests();
 
-       if(get_config_int(lookup_config(config_tree, "PingInterval"), &pinginterval)) {
+       if(get_config_int(lookup_config(&config_tree, "PingInterval"), &pinginterval)) {
                if(pinginterval < 1) {
                        pinginterval = 86400;
                }
@@ -1313,7 +1122,7 @@ bool setup_network(void) {
                pinginterval = 60;
        }
 
-       if(!get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) {
+       if(!get_config_int(lookup_config(&config_tree, "PingTimeout"), &pingtimeout)) {
                pingtimeout = 5;
        }
 
@@ -1321,7 +1130,7 @@ bool setup_network(void) {
                pingtimeout = pinginterval;
        }
 
-       if(!get_config_int(lookup_config(config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) {
+       if(!get_config_int(lookup_config(&config_tree, "MaxOutputBufferSize"), &maxoutbufsize)) {
                maxoutbufsize = 10 * MTU;
        }
 
@@ -1348,7 +1157,7 @@ bool setup_network(void) {
   close all open network connections
 */
 void close_network_connections(void) {
-       for(list_node_t *node = connection_list->head, *next; node; node = next) {
+       for(list_node_t *node = connection_list.head, *next; node; node = next) {
                next = node->next;
                connection_t *c = node->data;
 
@@ -1361,9 +1170,7 @@ void close_network_connections(void) {
                terminate_connection(c, false);
        }
 
-       if(outgoing_list) {
-               list_delete_list(outgoing_list);
-       }
+       list_empty_list(&outgoing_list);
 
        if(myself && myself->connection) {
                subnet_update(myself, NULL, false);