Allocate temporary filenames on the stack.
authorGuus Sliepen <guus@tinc-vpn.org>
Tue, 19 May 2015 22:55:00 +0000 (00:55 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Tue, 19 May 2015 22:58:00 +0000 (00:58 +0200)
This gets rid of xasprintf() in a number of places, and removes the need
to free() the temporary strings. A few potential memory leaks have been
fixed.

src/conf.c
src/invitation.c
src/net.c
src/net_setup.c
src/script.c
src/tincctl.c

index e0d8e922fb9248eee0a11cafe0e0f4b412a9a0d8..2b323597024111792fd855e89c3ac289a9711a2f 100644 (file)
@@ -4,7 +4,7 @@
                   1998-2005 Ivo Timmermans
                   2000      Cris van Pelt
                   2010-2011 Julien Muchembled <jm@jmuchemb.eu>
-                  2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2015 Guus Sliepen <guus@tinc-vpn.org>
                   2013      Florent Clairambault <florent@clairambault.fr>
 
     This program is free software; you can redistribute it and/or modify
@@ -368,19 +368,19 @@ void read_config_options(splay_tree_t *config_tree, const char *prefix) {
 }
 
 bool read_server_config(void) {
-       char *fname;
+       char fname[PATH_MAX];
        bool x;
 
        read_config_options(config_tree, NULL);
 
-       xasprintf(&fname, "%s" SLASH "tinc.conf", confbase);
+       snprintf(fname, sizeof fname, "%s" SLASH "tinc.conf", confbase);
        errno = 0;
        x = read_config_file(config_tree, fname);
 
        // We will try to read the conf files in the "conf.d" dir
        if (x) {
-               char * dname;
-               xasprintf(&dname, "%s" SLASH "conf.d", confbase);
+               char dname[PATH_MAX];
+               snprintf(dname, sizeof dname, "%s" SLASH "conf.d", confbase);
                DIR *dir = opendir (dname);
                // If we can find this dir
                if (dir) { 
@@ -390,51 +390,44 @@ bool read_server_config(void) {
                                size_t l = strlen(ep->d_name);
                                // And we try to read the ones that end with ".conf"
                                if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
-                                       free(fname);
-                                       xasprintf(&fname, "%s" SLASH "%s", dname, ep->d_name);
+                                       snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ep->d_name);
                                        x = read_config_file(config_tree, fname);
                                }
                        }
                        closedir (dir);
                }
-               free(dname);
        }
 
        if(!x && errno)
                logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
 
-       free(fname);
-
        return x;
 }
 
 bool read_host_config(splay_tree_t *config_tree, const char *name) {
-       char *fname;
+       char fname[PATH_MAX];
        bool x;
 
        read_config_options(config_tree, name);
 
-       xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+       snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
        x = read_config_file(config_tree, fname);
-       free(fname);
 
        return x;
 }
 
 bool append_config_file(const char *name, const char *key, const char *value) {
-       char *fname;
-       xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+       char fname[PATH_MAX];
+       snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
 
        FILE *fp = fopen(fname, "a");
 
        if(!fp) {
                logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
-       } else {
-               fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
-               fclose(fp);
+               return false;
        }
 
-       free(fname);
-
-       return fp != NULL;
+       fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
+       fclose(fp);
+       return true;
 }
index 1a2f93f5696678a44559b4d7917daf5c98b644bb..cc6cbd4d36ec706f65c4d9abe78848fd95bfd3be 100644 (file)
@@ -1,6 +1,6 @@
 /*
     invitation.c -- Create and accept invitations
-    Copyright (C) 2013-2014 Guus Sliepen <guus@tinc-vpn.org>
+    Copyright (C) 2013-2015 Guus Sliepen <guus@tinc-vpn.org>
 
     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
@@ -84,11 +84,11 @@ char *get_my_hostname() {
        char *port = NULL;
        char *hostport = NULL;
        char *name = get_my_name(false);
-       char *filename = NULL;
+       char filename[PATH_MAX];
 
        // Use first Address statement in own host config file
        if(check_id(name)) {
-               xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+               snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
                scan_for_hostname(filename, &hostname, &port);
                scan_for_hostname(tinc_conf, &hostname, &port);
        }
@@ -207,7 +207,6 @@ done:
 
        free(hostname);
        free(port);
-       free(filename);
        return hostport;
 }
 
@@ -243,14 +242,12 @@ int cmd_invite(int argc, char *argv[]) {
                return 1;
 
        // Ensure no host configuration file with that name exists
-       char *filename = NULL;
-       xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
+       char filename[PATH_MAX];
+       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
        if(!access(filename, F_OK)) {
-               free(filename);
                fprintf(stderr, "A host config file for %s already exists!\n", argv[1]);
                return 1;
        }
-       free(filename);
 
        // If a daemon is running, ensure no other nodes know about this name
        bool found = false;
@@ -272,10 +269,9 @@ int cmd_invite(int argc, char *argv[]) {
                }
        }
 
-       xasprintf(&filename, "%s" SLASH "invitations", confbase);
+       snprintf(filename, sizeof filename, "%s" SLASH "invitations", confbase);
        if(mkdir(filename, 0700) && errno != EEXIST) {
                fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
-               free(filename);
                return 1;
        }
 
@@ -283,7 +279,6 @@ int cmd_invite(int argc, char *argv[]) {
        DIR *dir = opendir(filename);
        if(!dir) {
                fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno));
-               free(filename);
                return 1;
        }
 
@@ -295,9 +290,9 @@ int cmd_invite(int argc, char *argv[]) {
        while((ent = readdir(dir))) {
                if(strlen(ent->d_name) != 24)
                        continue;
-               char *invname;
+               char invname[PATH_MAX];
                struct stat st;
-               xasprintf(&invname, "%s" SLASH "%s", filename, ent->d_name);
+               snprintf(invname, sizeof invname, "%s" SLASH "%s", filename, ent->d_name);
                if(!stat(invname, &st)) {
                        if(deadline < st.st_mtime)
                                count++;
@@ -307,21 +302,17 @@ int cmd_invite(int argc, char *argv[]) {
                        fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno));
                        errno = 0;
                }
-               free(invname);
        }
 
+       closedir(dir);
+
        if(errno) {
                fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno));
-               closedir(dir);
-               free(filename);
                return 1;
        }
                
-       closedir(dir);
-       free(filename);
-
        ecdsa_t *key;
-       xasprintf(&filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
+       snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
 
        // Remove the key if there are no outstanding invitations.
        if(!count)
@@ -332,19 +323,15 @@ int cmd_invite(int argc, char *argv[]) {
        if(!f) {
                if(errno != ENOENT) {
                        fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno));
-                       free(filename);
                        return 1;
                }
 
                key = ecdsa_generate();
-               if(!key) {
-                       free(filename);
+               if(!key)
                        return 1;
-               }
                f = fopen(filename, "w");
                if(!f) {
                        fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
-                       free(filename);
                        return 1;
                }
                chmod(filename, 0600);
@@ -360,7 +347,6 @@ int cmd_invite(int argc, char *argv[]) {
                        fprintf(stderr, "Could not read private key from %s\n", filename);
        }
 
-       free(filename);
        if(!key)
                return 1;
 
@@ -385,11 +371,10 @@ int cmd_invite(int argc, char *argv[]) {
        b64encode_urlsafe(cookie, cookie, 18);
 
        // Create a file containing the details of the invitation.
-       xasprintf(&filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
+       snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
        int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
        if(!ifd) {
                fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno));
-               free(filename);
                return 1;
        }
        f = fdopen(ifd, "w");
@@ -424,11 +409,10 @@ int cmd_invite(int argc, char *argv[]) {
        fprintf(f, "#---------------------------------------------------------------#\n");
        fprintf(f, "Name = %s\n", myname);
 
-       char *filename2;
-       xasprintf(&filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
+       char filename2[PATH_MAX];
+       snprintf(filename2, sizeof filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
        fcopy(f, filename2);
        fclose(f);
-       free(filename2);
 
        // Create an URL from the local address, key hash and cookie
        char *url;
@@ -447,7 +431,6 @@ int cmd_invite(int argc, char *argv[]) {
 
        puts(url);
        free(url);
-       free(filename);
        free(address);
 
        return 0;
@@ -606,8 +589,8 @@ make_names:
 
        fprintf(f, "Name = %s\n", name);
 
-       char *filename;
-       xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
+       char filename[PATH_MAX];
+       snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
        FILE *fh = fopen(filename, "w");
        if(!fh) {
                fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
@@ -668,7 +651,6 @@ make_names:
        }
 
        fclose(f);
-       free(filename);
 
        while(l && !strcasecmp(l, "Name")) {
                if(!check_id(value)) {
@@ -681,7 +663,7 @@ make_names:
                        return false;
                }
 
-               xasprintf(&filename, "%s" SLASH "%s", hosts_dir, value);
+               snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, value);
                f = fopen(filename, "w");
 
                if(!f) {
@@ -709,7 +691,6 @@ make_names:
                }
 
                fclose(f);
-               free(filename);
        }
 
        // Generate our key and send a copy to the server
@@ -721,7 +702,7 @@ make_names:
        if(!b64key)
                return false;
 
-       xasprintf(&filename, "%s" SLASH "ed25519_key.priv", confbase);
+       snprintf(filename, sizeof filename, "%s" SLASH "ed25519_key.priv", confbase);
        f = fopenmask(filename, "w", 0600);
 
        if(!ecdsa_write_pem_private_key(key, f)) {
@@ -741,7 +722,7 @@ make_names:
 
 #ifndef DISABLE_LEGACY
        rsa_t *rsa = rsa_generate(2048, 0x1001);
-       xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase);
+       snprintf(filename, sizeof filename, "%s" SLASH "rsa_key.priv", confbase);
        f = fopenmask(filename, "w", 0600);
 
        rsa_write_pem_private_key(rsa, f);
@@ -767,15 +748,13 @@ ask_netname:
 
                line[strlen(line) - 1] = 0;
 
-               char *newbase;
-               xasprintf(&newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
+               char newbase[PATH_MAX];
+               snprintf(newbase, sizeof newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
                if(rename(confbase, newbase)) {
                        fprintf(stderr, "Error trying to rename %s to %s: %s\n", confbase, newbase, strerror(errno));
-                       free(newbase);
                        goto ask_netname;
                }
 
-               free(newbase);
                netname = line;
                make_names();
        }
index 1ce8071d9d0216fb0cadc68586fe0d3560ca5508..a539425668b865b61bba91c2112d2530945b1dc2 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-2013 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2015 Guus Sliepen <guus@tinc-vpn.org>
                   2006      Scott Lamb <slamb@slamb.org>
                   2011      Loïc Grenié <loic.grenie@gmail.com>
 
@@ -314,7 +314,7 @@ static void sigalrm_handler(void *data) {
 #endif
 
 int reload_configuration(void) {
-       char *fname = NULL;
+       char fname[PATH_MAX];
 
        /* Reread our own configuration file */
 
@@ -328,9 +328,8 @@ int reload_configuration(void) {
 
        read_config_options(config_tree, NULL);
 
-       xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
+       snprintf(fname, sizeof 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 */
 
@@ -407,13 +406,12 @@ int reload_configuration(void) {
                if(c->status.control)
                        continue;
 
-               xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
+               snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
                struct stat s;
                if(stat(fname, &s) || s.st_mtime > last_config_check) {
                        logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
                        terminate_connection(c, c->edge);
                }
-               free(fname);
        }
 
        last_config_check = now.tv_sec;
index 3c66c136c3d2e580fd44555ac0464201e5ccb08d..bf5ba04c1e7e1005b22f48ffd164b32584a34510 100644 (file)
@@ -1,7 +1,7 @@
 /*
     net_setup.c -- Setup.
     Copyright (C) 1998-2005 Ivo Timmermans,
-                  2000-2014 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2015 Guus Sliepen <guus@tinc-vpn.org>
                   2006      Scott Lamb <slamb@slamb.org>
                   2010      Brandon Black <blblack@gmail.com>
 
@@ -226,14 +226,14 @@ static bool read_ecdsa_private_key(void) {
 
 static bool read_invitation_key(void) {
        FILE *fp;
-       char *fname;
+       char fname[PATH_MAX];
 
        if(invitation_key) {
                ecdsa_free(invitation_key);
                invitation_key = NULL;
        }
 
-       xasprintf(&fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
+       snprintf(fname, sizeof fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
 
        fp = fopen(fname, "r");
 
@@ -244,7 +244,6 @@ static bool read_invitation_key(void) {
                        logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
        }
 
-       free(fname);
        return invitation_key;
 }
 
@@ -327,13 +326,12 @@ void regenerate_key(void) {
 void load_all_subnets(void) {
        DIR *dir;
        struct dirent *ent;
-       char *dname;
+       char dname[PATH_MAX];
 
-       xasprintf(&dname, "%s" SLASH "hosts", confbase);
+       snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
        dir = opendir(dname);
        if(!dir) {
                logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
-               free(dname);
                return;
        }
 
@@ -380,13 +378,12 @@ void load_all_subnets(void) {
 void load_all_nodes(void) {
        DIR *dir;
        struct dirent *ent;
-       char *dname;
+       char dname[PATH_MAX];
 
-       xasprintf(&dname, "%s" SLASH "hosts", confbase);
+       snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
        dir = opendir(dname);
        if(!dir) {
                logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
-               free(dname);
                return;
        }
 
index 6389cb4b19ca0559a9c74373e0c83f7d30b598e8..55473b1f95e6ea595fe1664740aceefee8684e6e 100644 (file)
@@ -1,7 +1,7 @@
 /*
     script.c -- call an external script
     Copyright (C) 1999-2005 Ivo Timmermans,
-                  2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2015 Guus Sliepen <guus@tinc-vpn.org>
 
     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
 
 bool execute_script(const char *name, char **envp) {
 #ifdef HAVE_SYSTEM
-       char *scriptname;
+       char scriptname[PATH_MAX];
        char *command;
 
-       xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
+       snprintf(scriptname, sizeof scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
 
        /* First check if there is a script */
 
@@ -57,17 +57,13 @@ bool execute_script(const char *name, char **envp) {
                                break;
                        p = q;
                }
-               if(!found) {
-                       free(scriptname);
+               if(!found)
                        return true;
-               }
        } else
 #endif
 
-       if(access(scriptname, F_OK)) {
-               free(scriptname);
+       if(access(scriptname, F_OK))
                return true;
-       }
 
        logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
 
@@ -86,7 +82,6 @@ bool execute_script(const char *name, char **envp) {
        int status = system(command);
 
        free(command);
-       free(scriptname);
 
        /* Unset environment */
 
index e0a6086e8f89b9b44f3ce9d328656c16206efb8c..fc59c580c36fffefa842f56465b2417b0b08ca77 100644 (file)
@@ -376,7 +376,7 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo
 static bool ed25519_keygen(bool ask) {
        ecdsa_t *key;
        FILE *f;
-       char *pubname, *privname;
+       char fname[PATH_MAX];
 
        fprintf(stderr, "Generating Ed25519 keypair:\n");
 
@@ -386,41 +386,42 @@ static bool ed25519_keygen(bool ask) {
        } else
                fprintf(stderr, "Done.\n");
 
-       xasprintf(&privname, "%s" SLASH "ed25519_key.priv", confbase);
-       f = ask_and_open(privname, "private Ed25519 key", "a", ask, 0600);
-       free(privname);
+       snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.priv", confbase);
+       f = ask_and_open(fname, "private Ed25519 key", "a", ask, 0600);
 
        if(!f)
-               return false;
+               goto error;
 
        if(!ecdsa_write_pem_private_key(key, f)) {
                fprintf(stderr, "Error writing private key!\n");
-               ecdsa_free(key);
-               fclose(f);
-               return false;
+               goto error;
        }
 
        fclose(f);
 
        if(name)
-               xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+               snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
        else
-               xasprintf(&pubname, "%s" SLASH "ed25519_key.pub", confbase);
+               snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.pub", confbase);
 
-       f = ask_and_open(pubname, "public Ed25519 key", "a", ask, 0666);
-       free(pubname);
+       f = ask_and_open(fname, "public Ed25519 key", "a", ask, 0666);
 
        if(!f)
                return false;
 
        char *pubkey = ecdsa_get_base64_public_key(key);
        fprintf(f, "Ed25519PublicKey = %s\n", pubkey);
-       free(pubkey);
 
        fclose(f);
        ecdsa_free(key);
 
        return true;
+
+error:
+       if(f)
+               fclose(f);
+       ecdsa_free(key);
+       return false;
 }
 
 #ifndef DISABLE_LEGACY
@@ -431,7 +432,7 @@ static bool ed25519_keygen(bool ask) {
 static bool rsa_keygen(int bits, bool ask) {
        rsa_t *key;
        FILE *f;
-       char *pubname, *privname;
+       char fname[PATH_MAX];
 
        // Make sure the key size is a multiple of 8 bits.
        bits &= ~0x7;
@@ -450,44 +451,44 @@ static bool rsa_keygen(int bits, bool ask) {
        } else
                fprintf(stderr, "Done.\n");
 
-       xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase);
-       f = ask_and_open(privname, "private RSA key", "a", ask, 0600);
-       free(privname);
+       snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.priv", confbase);
+       f = ask_and_open(fname, "private RSA key", "a", ask, 0600);
 
        if(!f)
-               return false;
+               goto error;
 
        if(!rsa_write_pem_private_key(key, f)) {
                fprintf(stderr, "Error writing private key!\n");
-               fclose(f);
-               rsa_free(key);
-               return false;
+               goto error;
        }
 
        fclose(f);
 
        if(name)
-               xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+               snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
        else
-               xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase);
+               snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.pub", confbase);
 
-       f = ask_and_open(pubname, "public RSA key", "a", ask, 0666);
-       free(pubname);
+       f = ask_and_open(fname, "public RSA key", "a", ask, 0666);
 
        if(!f)
-               return false;
+               goto error;
 
        if(!rsa_write_pem_public_key(key, f)) {
                fprintf(stderr, "Error writing public key!\n");
-               fclose(f);
-               rsa_free(key);
-               return false;
+               goto error;
        }
 
        fclose(f);
        rsa_free(key);
 
        return true;
+
+error:
+       if(f)
+               fclose(f);
+       rsa_free(key);
+       return false;
 }
 #endif
 
@@ -1597,11 +1598,11 @@ static int cmd_config(int argc, char *argv[]) {
        }
 
        // Open the right configuration file.
-       char *filename;
+       char filename[PATH_MAX];
        if(node)
-               xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node);
+               snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, node);
        else
-               filename = tinc_conf;
+               snprintf(filename, sizeof filename, "%s", tinc_conf);
 
        FILE *f = fopen(filename, "r");
        if(!f) {
@@ -1609,11 +1610,11 @@ static int cmd_config(int argc, char *argv[]) {
                return 1;
        }
 
-       char *tmpfile = NULL;
+       char tmpfile[PATH_MAX];
        FILE *tf = NULL;
 
        if(action >= -1) {
-               xasprintf(&tmpfile, "%s.config.tmp", filename);
+               snprintf(tmpfile, sizeof tmpfile, "%s.config.tmp", filename);
                tf = fopen(tmpfile, "w");
                if(!tf) {
                        fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
@@ -1799,11 +1800,11 @@ int check_port(char *name) {
        for(int i = 0; i < 100; i++) {
                int port = 0x1000 + (rand() & 0x7fff);
                if(try_bind(port)) {
-                       char *filename;
-                       xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+                       char filename[PATH_MAX];
+                       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
                        FILE *f = fopen(filename, "a");
-                       free(filename);
                        if(!f) {
+                               fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
                                fprintf(stderr, "Please change tinc's Port manually.\n");
                                return 0;
                        }
@@ -1894,8 +1895,8 @@ static int cmd_init(int argc, char *argv[]) {
        check_port(name);
 
 #ifndef HAVE_MINGW
-       char *filename;
-       xasprintf(&filename, "%s" SLASH "tinc-up", confbase);
+       char filename[PATH_MAX];
+       snprintf(filename, sizeof filename, "%s" SLASH "tinc-up", confbase);
        if(access(filename, F_OK)) {
                FILE *f = fopenmask(filename, "w", 0777);
                if(!f) {
@@ -2005,12 +2006,12 @@ static int cmd_edit(int argc, char *argv[]) {
                return 1;
        }
 
-       char *filename = NULL;
+       char filename[PATH_MAX] = "";
 
        if(strncmp(argv[1], "hosts" SLASH, 6)) {
                for(int i = 0; conffiles[i]; i++) {
                        if(!strcmp(argv[1], conffiles[i])) {
-                               xasprintf(&filename, "%s" SLASH "%s", confbase, argv[1]);
+                               snprintf(filename, sizeof filename, "%s" SLASH "%s", confbase, argv[1]);
                                break;
                        }
                }
@@ -2018,8 +2019,8 @@ static int cmd_edit(int argc, char *argv[]) {
                argv[1] += 6;
        }
 
-       if(!filename) {
-               xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]);
+       if(!*filename) {
+               snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, argv[1]);
                char *dash = strchr(argv[1], '-');
                if(dash) {
                        *dash++ = 0;
@@ -2037,6 +2038,7 @@ static int cmd_edit(int argc, char *argv[]) {
        xasprintf(&command, "edit \"%s\"", filename);
 #endif
        int result = system(command);
+       free(command);
        if(result)
                return result;
 
@@ -2048,8 +2050,8 @@ static int cmd_edit(int argc, char *argv[]) {
 }
 
 static int export(const char *name, FILE *out) {
-       char *filename;
-       xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
+       char filename[PATH_MAX];
+       snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
        FILE *in = fopen(filename, "r");
        if(!in) {
                fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
@@ -2136,7 +2138,7 @@ static int cmd_import(int argc, char *argv[]) {
 
        char buf[4096];
        char name[4096];
-       char *filename = NULL;
+       char filename[PATH_MAX] = "";
        int count = 0;
        bool firstline = true;
 
@@ -2152,8 +2154,7 @@ static int cmd_import(int argc, char *argv[]) {
                        if(out)
                                fclose(out);
 
-                       free(filename);
-                       xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
+                       snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
 
                        if(!force && !access(filename, F_OK)) {
                                fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
@@ -2259,11 +2260,10 @@ static int cmd_network(int argc, char *argv[]) {
                        continue;
                }
 
-               char *fname;
-               xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
+               char fname[PATH_MAX];
+               snprintf(fname, sizeof fname, "%s/%s/tinc.conf", confdir, ent->d_name);
                if(!access(fname, R_OK))
                        printf("%s\n", ent->d_name);
-               free(fname);
        }
 
        closedir(dir);