Fix more memory leaks found by ASAN.
[tinc] / src / net_setup.c
index 1f0e74c..d4bc59e 100644 (file)
@@ -1,7 +1,7 @@
 /*
     net_setup.c -- Setup.
     Copyright (C) 1998-2005 Ivo Timmermans,
-                  2000-2017 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2021 Guus Sliepen <guus@tinc-vpn.org>
                   2006      Scott Lamb <slamb@slamb.org>
                   2010      Brandon Black <blblack@gmail.com>
 
@@ -52,10 +52,11 @@ static io_t device_io;
 devops_t devops;
 bool device_standby = false;
 
-char *proxyhost;
-char *proxyport;
-char *proxyuser;
-char *proxypass;
+char *proxyhost = NULL;
+char *proxyport = NULL;
+char *proxyuser = NULL;
+char *proxypass = NULL;
+
 proxytype_t proxytype;
 bool autoconnect;
 bool disablebuggypeers;
@@ -215,7 +216,7 @@ static bool read_ecdsa_private_key(void) {
                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 keypair with `tinc -n %s generate-ed25519-keys'.", netname ? netname : ".");
+                       logger(DEBUG_ALWAYS, LOG_INFO, "Create an Ed25519 key pair with `tinc -n %s generate-ed25519-keys'.", netname ? netname : ".");
                }
 
                free(fname);
@@ -231,7 +232,7 @@ static bool read_ecdsa_private_key(void) {
                return false;
        }
 
-       if(s.st_mode & ~0100700) {
+       if(s.st_mode & ~0100700u) {
                logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for Ed25519 private key file `%s'!", fname);
        }
 
@@ -307,7 +308,7 @@ static bool read_rsa_private_key(void) {
                       fname, strerror(errno));
 
                if(errno == ENOENT) {
-                       logger(DEBUG_ALWAYS, LOG_INFO, "Create an RSA keypair with `tinc -n %s generate-rsa-keys'.", netname ? netname : ".");
+                       logger(DEBUG_ALWAYS, LOG_INFO, "Create an RSA key pair with `tinc -n %s generate-rsa-keys'.", netname ? netname : ".");
                }
 
                free(fname);
@@ -323,7 +324,7 @@ static bool read_rsa_private_key(void) {
                return false;
        }
 
-       if(s.st_mode & ~0100700) {
+       if(s.st_mode & ~0100700u) {
                logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
        }
 
@@ -435,18 +436,10 @@ char *get_name(void) {
 }
 
 bool setup_myself_reloadable(void) {
-       char *proxy = NULL;
-       char *rmode = NULL;
-       char *fmode = NULL;
-       char *bmode = NULL;
-       char *afname = NULL;
-       char *space;
-       bool choice;
-
        free(scriptinterpreter);
        scriptinterpreter = NULL;
-       get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter);
 
+       get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter);
 
        free(scriptextension);
 
@@ -454,9 +447,13 @@ bool setup_myself_reloadable(void) {
                scriptextension = xstrdup("");
        }
 
+       char *proxy = NULL;
+
        get_config_string(lookup_config(config_tree, "Proxy"), &proxy);
 
        if(proxy) {
+               char *space;
+
                if((space = strchr(proxy, ' '))) {
                        *space++ = 0;
                }
@@ -475,9 +472,22 @@ bool setup_myself_reloadable(void) {
                        proxytype = PROXY_EXEC;
                } else {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Unknown proxy type %s!", proxy);
+                       free(proxy);
                        return false;
                }
 
+               free(proxyhost);
+               proxyhost = NULL;
+
+               free(proxyport);
+               proxyport = NULL;
+
+               free(proxyuser);
+               proxyuser = NULL;
+
+               free(proxypass);
+               proxypass = NULL;
+
                switch(proxytype) {
                case PROXY_NONE:
                default:
@@ -486,10 +496,11 @@ bool setup_myself_reloadable(void) {
                case PROXY_EXEC:
                        if(!space || !*space) {
                                logger(DEBUG_ALWAYS, LOG_ERR, "Argument expected for proxy type exec!");
+                               free(proxy);
                                return false;
                        }
 
-                       proxyhost =  xstrdup(space);
+                       proxyhost = xstrdup(space);
                        break;
 
                case PROXY_SOCKS4:
@@ -502,6 +513,14 @@ bool setup_myself_reloadable(void) {
                                *space++ = 0, proxyport = space;
                        }
 
+                       if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
+                               logger(DEBUG_ALWAYS, LOG_ERR, "Host and port argument expected for proxy!");
+                               proxyport = NULL;
+                               proxyhost = NULL;
+                               free(proxy);
+                               return false;
+                       }
+
                        if(space && (space = strchr(space, ' '))) {
                                *space++ = 0, proxyuser = space;
                        }
@@ -510,11 +529,6 @@ bool setup_myself_reloadable(void) {
                                *space++ = 0, proxypass = space;
                        }
 
-                       if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
-                               logger(DEBUG_ALWAYS, LOG_ERR, "Host and port argument expected for proxy!");
-                               return false;
-                       }
-
                        proxyhost = xstrdup(proxyhost);
                        proxyport = xstrdup(proxyport);
 
@@ -532,6 +546,8 @@ bool setup_myself_reloadable(void) {
                free(proxy);
        }
 
+       bool choice;
+
        if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) {
                myself->options |= OPTION_INDIRECT;
        }
@@ -555,6 +571,8 @@ bool setup_myself_reloadable(void) {
        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(!strcasecmp(rmode, "router")) {
                        routing_mode = RMODE_ROUTER;
@@ -564,12 +582,15 @@ bool setup_myself_reloadable(void) {
                        routing_mode = RMODE_HUB;
                } else {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Invalid routing mode!");
+                       free(rmode);
                        return false;
                }
 
                free(rmode);
        }
 
+       char *fmode = NULL;
+
        if(get_config_string(lookup_config(config_tree, "Forwarding"), &fmode)) {
                if(!strcasecmp(fmode, "off")) {
                        forwarding_mode = FMODE_OFF;
@@ -579,6 +600,7 @@ bool setup_myself_reloadable(void) {
                        forwarding_mode = FMODE_KERNEL;
                } else {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Invalid forwarding mode!");
+                       free(fmode);
                        return false;
                }
 
@@ -602,6 +624,8 @@ bool setup_myself_reloadable(void) {
        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(!strcasecmp(bmode, "no")) {
                        broadcast_mode = BMODE_NONE;
@@ -611,6 +635,7 @@ bool setup_myself_reloadable(void) {
                        broadcast_mode = BMODE_DIRECT;
                } else {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Invalid broadcast mode!");
+                       free(bmode);
                        return false;
                }
 
@@ -626,7 +651,11 @@ bool setup_myself_reloadable(void) {
                        abort();
                }
 
-               subnet_add(NULL, s);
+               if(splay_search(subnet_tree, s)) {
+                       free(s);
+               } else {
+                       subnet_add(NULL, s);
+               }
        }
 
        for(config_t *cfg = lookup_config(config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
@@ -636,7 +665,11 @@ bool setup_myself_reloadable(void) {
                        continue;
                }
 
-               subnet_add(NULL, s);
+               if(splay_search(subnet_tree, s)) {
+                       free(s);
+               } else {
+                       subnet_add(NULL, s);
+               }
        }
 
 #if !defined(IP_TOS)
@@ -668,6 +701,8 @@ bool setup_myself_reloadable(void) {
                maxtimeout = 900;
        }
 
+       char *afname = NULL;
+
        if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
                if(!strcasecmp(afname, "IPv4")) {
                        addressfamily = AF_INET;
@@ -677,6 +712,7 @@ bool setup_myself_reloadable(void) {
                        addressfamily = AF_UNSPEC;
                } else {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Invalid address family!");
+                       free(afname);
                        return false;
                }
 
@@ -762,6 +798,7 @@ static bool add_listen_address(char *address, bool bindto) {
 
                if(listen_sockets >= MAXSOCKETS) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets");
+                       freeaddrinfo(ai);
                        return false;
                }
 
@@ -935,6 +972,8 @@ static bool setup_myself(void) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "UDPRcvBuf cannot be negative!");
                        return false;
                }
+
+               udp_rcvbuf_warnings = true;
        }
 
        if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
@@ -942,6 +981,8 @@ static bool setup_myself(void) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "UDPSndBuf cannot be negative!");
                        return false;
                }
+
+               udp_sndbuf_warnings = true;
        }
 
        get_config_int(lookup_config(config_tree, "FWMark"), &fwmark);
@@ -1019,8 +1060,49 @@ static bool setup_myself(void) {
        /* Compression */
 
        if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
-               if(myself->incompression < 0 || myself->incompression > 11) {
+               switch(myself->incompression) {
+               case 12:
+#ifdef HAVE_LZ4
+                       break;
+#else
+                       logger(DEBUG_ALWAYS, LOG_ERR, "Bogus compression level!");
+                       logger(DEBUG_ALWAYS, LOG_ERR, "LZ4 compression is unavailable on this node.");
+                       return false;
+#endif
+
+               case 11:
+               case 10:
+#ifdef HAVE_LZO
+                       break;
+#else
+                       logger(DEBUG_ALWAYS, LOG_ERR, "Bogus compression level!");
+                       logger(DEBUG_ALWAYS, LOG_ERR, "LZO compression is unavailable on this node.");
+                       return false;
+#endif
+
+               case 9:
+               case 8:
+               case 7:
+               case 6:
+               case 5:
+               case 4:
+               case 3:
+               case 2:
+               case 1:
+#ifdef HAVE_ZLIB
+                       break;
+#else
+                       logger(DEBUG_ALWAYS, LOG_ERR, "Bogus compression level!");
+                       logger(DEBUG_ALWAYS, LOG_ERR, "ZLIB compression is unavailable on this node.");
+                       return false;
+#endif
+
+               case 0:
+                       break;
+
+               default:
                        logger(DEBUG_ALWAYS, LOG_ERR, "Bogus compression level!");
+                       logger(DEBUG_ALWAYS, LOG_ERR, "Compression level %i is unrecognized by this node.", myself->incompression);
                        return false;
                }
        } else {
@@ -1285,7 +1367,7 @@ void close_network_connections(void) {
 
        if(myself && myself->connection) {
                subnet_update(myself, NULL, false);
-               connection_del(myself->connection);
+               free_connection(myself->connection);
        }
 
        for(int i = 0; i < listen_sockets; i++) {