]> git.meshlink.io Git - meshlink/commitdiff
Various fixes: feature/encrypted-storage
authorGuus Sliepen <guus@meshlink.io>
Wed, 13 Mar 2019 22:13:06 +0000 (23:13 +0100)
committerGuus Sliepen <guus@meshlink.io>
Mon, 8 Apr 2019 19:51:37 +0000 (21:51 +0200)
- create_initial_config_files() and node_write_config() are now the only
  functions that generate the content of new config files from scratch.
- All public API functions that change config files now immediately
  write them out.
- Config files of nodes that join using an invitation file are immediately
  written out.
- Ensure nodes marked dirty have their config files written out in
  periodic_handler(), and on meshlink_stop().
- Fix some memory leaks.
- Write out updated config files, and recreate mesh->self in meshlink_set_port().

doc/Configuration.md
src/conf.c
src/meshlink.c
src/net.c
src/net_setup.c
src/netutl.c
src/node.c
src/protocol_auth.c
src/submesh.c

index 1520ee570b6c322f60698444468bce0b3405f786..6b76457bacbce7a1f06f0e25db943bbb599537e6 100644 (file)
@@ -43,9 +43,10 @@ The contents of a host configuration are:
 
 - uint32: configuration format version
 - str: name of the node
+- str: name of the submesh this node is part of, or "." if it's in the core mesh
 - int32: device class
 - bool: blacklisted
-- bin: public Ed25519 key
+- bin: public Ed25519 key, or zero-length if no key is known
 - str: canonical address (may be zero length if unset)
 - arr[ext]: recent addresses
 
@@ -56,6 +57,7 @@ The contents of an invitation file are:
 
 - uint32: invitation format version
 - str: name of the invitee
+- str: name of the submesh this node will be part of, or "." if it's in the core mesh
 - int32: device class of the invitee (may be unused)
 - arr[bin]: one or more host config files
 
index 9664e2b776a923a9d33d69451d5867c52986b5b4..1a3c82ae2e8c45e5cf07cceaf2945bcc9eaac6bf 100644 (file)
@@ -223,6 +223,7 @@ bool config_read_file(meshlink_handle_t *mesh, FILE *f, config_t *config) {
                chacha_poly1305_set_key(ctx, mesh->config_key);
 
                if(len > 12 && chacha_poly1305_decrypt_iv96(ctx, buf, buf + 12, len - 12, decrypted, &decrypted_len)) {
+                       chacha_poly1305_exit(ctx);
                        free(buf);
                        config->buf = decrypted;
                        config->len = decrypted_len;
@@ -230,6 +231,7 @@ bool config_read_file(meshlink_handle_t *mesh, FILE *f, config_t *config) {
                } else {
                        logger(mesh, MESHLINK_ERROR, "Cannot decrypt config file\n");
                        meshlink_errno = MESHLINK_ESTORAGE;
+                       chacha_poly1305_exit(ctx);
                        free(decrypted);
                        free(buf);
                        return false;
@@ -330,7 +332,7 @@ void config_scan_all(meshlink_handle_t *mesh, config_scan_action_t action) {
        DIR *dir;
        struct dirent *ent;
        char dname[PATH_MAX];
-       make_host_path(mesh, NULL, dname, sizeof(dname));
+       make_host_path(mesh, "", dname, sizeof(dname));
 
        dir = opendir(dname);
 
index 0697c0253eaf2f4d9362fafb54369ed6139b5dbe..5152fb06858a19c67d5cb4600f9483c5d1298e7d 100644 (file)
@@ -522,6 +522,36 @@ int check_port(meshlink_handle_t *mesh) {
        return 0;
 }
 
+static bool write_main_config_files(meshlink_handle_t *mesh) {
+       uint8_t buf[4096];
+
+       /* Write the main config file */
+       packmsg_output_t out = {buf, sizeof buf};
+
+       packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
+       packmsg_add_str(&out, mesh->name);
+       packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96);
+       packmsg_add_bin(&out, ecdsa_get_private_key(mesh->invitation_key), 96);
+       packmsg_add_uint16(&out, atoi(mesh->myport));
+
+       if(!packmsg_output_ok(&out)) {
+               return false;
+       }
+
+       config_t config = {buf, packmsg_output_size(&out, buf)};
+
+       if(!main_config_write(mesh, &config)) {
+               return false;
+       }
+
+       /* Write our own host config file */
+       if(!node_write_config(mesh, mesh->self)) {
+               return false;
+       }
+
+       return true;
+}
+
 static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len) {
        packmsg_input_t in = {buf, len};
        uint32_t version = packmsg_get_uint32(&in);
@@ -543,48 +573,28 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len
 
        if(!check_id(name)) {
                logger(mesh, MESHLINK_DEBUG, "Invalid Name found in invitation: %s!\n", name);
+               free(name);
                return false;
        }
 
        if(!count) {
                logger(mesh, MESHLINK_ERROR, "Incomplete invitation file!\n");
+               free(name);
                return false;
        }
 
+       free(mesh->name);
+       free(mesh->self->name);
+       mesh->name = name;
+       mesh->self->name = xstrdup(name);
+       mesh->self->devclass = devclass;
+
        // Initialize configuration directory
        if(!config_init(mesh)) {
                return false;
        }
 
-       // Write main config file
-       uint8_t outbuf[4096];
-       packmsg_output_t out = {outbuf, sizeof(outbuf)};
-       packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
-       packmsg_add_str(&out, name);
-       packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96);
-       packmsg_add_uint16(&out, atoi(mesh->myport));
-
-       config_t config = {outbuf, packmsg_output_size(&out, outbuf)};
-
-       if(!main_config_write(mesh, &config)) {
-               return false;
-       }
-
-       // Write our own host config file
-       out.ptr = outbuf;
-       out.len = sizeof(outbuf);
-       packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
-       packmsg_add_str(&out, name);
-       packmsg_add_str(&out, CORE_MESH);
-       packmsg_add_int32(&out, devclass);
-       packmsg_add_bool(&out, false);
-       packmsg_add_bin(&out, ecdsa_get_public_key(mesh->private_key), 32);
-       packmsg_add_str(&out, ""); // TODO: copy existing canonical address, in case it was added before meshlink_join().
-       packmsg_add_array(&out, 0);
-
-       config.len = packmsg_output_size(&out, outbuf);
-
-       if(!config_write(mesh, name, &config)) {
+       if(!write_main_config_files(mesh)) {
                return false;
        }
 
@@ -598,19 +608,36 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len
                        return false;
                }
 
-               config_t config = {data, len};
-               node_t *n = new_node();
+               packmsg_input_t in2 = {data, len};
+               uint32_t version = packmsg_get_uint32(&in2);
+               char *name = packmsg_get_str_dup(&in2);
 
-               if(!node_read_from_config(mesh, n, &config)) {
-                       free_node(n);
-                       logger(mesh, MESHLINK_ERROR, "Invalid host config file in invitation file!\n");
+               if(!packmsg_input_ok(&in2) || version != MESHLINK_CONFIG_VERSION || !check_id(name)) {
+                       free(name);
+                       packmsg_input_invalidate(&in);
+                       break;
+               }
+
+               if(!check_id(name)) {
+                       free(name);
+                       break;
+               }
+
+               if(!strcmp(name, mesh->name)) {
+                       logger(mesh, MESHLINK_DEBUG, "Secondary chunk would overwrite our own host config file.\n");
+                       free(name);
                        meshlink_errno = MESHLINK_EPEER;
                        return false;
                }
 
-               if(!strcmp(n->name, name)) {
-                       logger(mesh, MESHLINK_DEBUG, "Secondary chunk would overwrite our own host config file.\n");
+               node_t *n = new_node();
+               n->name = name;
+
+               config_t config = {data, len};
+
+               if(!node_read_from_config(mesh, n, &config)) {
                        free_node(n);
+                       logger(mesh, MESHLINK_ERROR, "Invalid host config file in invitation file!\n");
                        meshlink_errno = MESHLINK_EPEER;
                        return false;
                }
@@ -624,11 +651,6 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len
 
        sptps_send_record(&(mesh->sptps), 1, ecdsa_get_public_key(mesh->private_key), 32);
 
-       free(mesh->name);
-       free(mesh->self->name);
-       mesh->name = xstrdup(name);
-       mesh->self->name = xstrdup(name);
-
        logger(mesh, MESHLINK_DEBUG, "Configuration stored in: %s\n", mesh->confbase);
 
        return true;
@@ -825,24 +847,6 @@ static void add_local_addresses(meshlink_handle_t *mesh) {
        }
 }
 
-#if 0
-static bool meshlink_write_config(meshlink_handle_t *mesh) {
-       uint8_t buf[1024];
-       packmsg_output_t out = {buf, sizeof buf};
-       packmsg_add_str(&out, mesh->name);
-       packmsg_add_uint32(&out, mesh->devclass);
-       packmsg_add_uint16(&out, mesh->port);
-       packmsg_add_bin(&out, ecdsa, sizeof(ecdsa));
-       uint32_t len = packmsg_output_size(&out, buf);
-
-       if(!len) {
-               logger(mesh, MESHLINK_DEBUG, "Could not create configuration data\n",);
-               meshlink_errno = MESHLINK_EINTERNAL;
-               return false;
-       }
-}
-#endif
-
 static bool meshlink_setup(meshlink_handle_t *mesh) {
        if(!config_init(mesh)) {
                logger(mesh, MESHLINK_ERROR, "Could not set up configuration in %s: %s\n", mesh->confbase, strerror(errno));
@@ -867,36 +871,13 @@ static bool meshlink_setup(meshlink_handle_t *mesh) {
        mesh->self->devclass = mesh->devclass;
        mesh->self->ecdsa = ecdsa_set_public_key(ecdsa_get_public_key(mesh->private_key));
 
-       // Write the main config file
-       uint8_t buf[4096];
-       packmsg_output_t out = {buf, sizeof(buf)};
-
-       packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
-       packmsg_add_str(&out, mesh->name);
-       packmsg_add_bin(&out, ecdsa_get_private_key(mesh->private_key), 96);
-       packmsg_add_bin(&out, ecdsa_get_private_key(mesh->invitation_key), 96);
-       packmsg_add_uint16(&out, atoi(mesh->myport));
-
-       config_t config = {buf, packmsg_output_size(&out, buf)};
-
-       if(!main_config_write(mesh, &config)) {
+       if(!write_main_config_files(mesh)) {
                return false;
        }
 
-       // Write our own host config file
-       out.ptr = buf;
-       out.len = sizeof(buf);
-       packmsg_add_uint32(&out, MESHLINK_CONFIG_VERSION);
-       packmsg_add_str(&out, mesh->name);
-       packmsg_add_int32(&out, mesh->devclass);
-       packmsg_add_bool(&out, false);
-       packmsg_add_bin(&out, ecdsa_get_public_key(mesh->private_key), 32);
-       packmsg_add_str(&out, ""); // TODO: copy existing canonical address, in case it was added before meshlink_join().
-       packmsg_add_array(&out, 0);
-
-       config.len = packmsg_output_size(&out, buf);
-
-       if(!config_write(mesh, mesh->name, &config)) {
+       if(!main_config_lock(mesh)) {
+               logger(NULL, MESHLINK_ERROR, "Cannot lock main config file\n");
+               meshlink_errno = MESHLINK_ESTORAGE;
                return false;
        }
 
@@ -963,6 +944,7 @@ static bool meshlink_read_config(meshlink_handle_t *mesh) {
 
        if(!node_read_public_key(mesh, mesh->self)) {
                logger(NULL, MESHLINK_ERROR, "Could not read our host configuration file!");
+               meshlink_errno = MESHLINK_ESTORAGE;
                free_node(mesh->self);
                mesh->self = NULL;
                return false;
@@ -1193,6 +1175,7 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
 
                if(!prf(params->key, params->keylen, "MeshLink configuration key", 26, mesh->config_key, CHACHA_POLY1305_KEYLEN)) {
                        logger(NULL, MESHLINK_ERROR, "Error creating configuration key!\n");
+                       meshlink_close(mesh);
                        meshlink_errno = MESHLINK_EINTERNAL;
                        return NULL;
                }
@@ -1434,6 +1417,16 @@ void meshlink_stop(meshlink_handle_t *mesh) {
 
        exit_outgoings(mesh);
 
+       // Write out any changed node config files
+       if(mesh->nodes) {
+               for splay_each(node_t, n, mesh->nodes) {
+                       if(n->status.dirty) {
+                               node_write_config(mesh, n);
+                               n->status.dirty = false;
+                       }
+               }
+       }
+
        pthread_mutex_unlock(&(mesh->mesh_mutex));
 }
 
@@ -1474,6 +1467,8 @@ void meshlink_close(meshlink_handle_t *mesh) {
        free(mesh->name);
        free(mesh->appname);
        free(mesh->confbase);
+       free(mesh->config_key);
+       ecdsa_free(mesh->private_key);
        pthread_mutex_destroy(&(mesh->mesh_mutex));
 
        main_config_unlock(mesh);
@@ -1917,7 +1912,7 @@ bool meshlink_set_canonical_address(meshlink_handle_t *mesh, meshlink_node_t *no
        node_t *n = (node_t *)node;
        free(n->canonical_address);
        n->canonical_address = canonical_address;
-       n->status.dirty = true;
+       node_write_config(mesh, n);
 
        pthread_mutex_unlock(&(mesh->mesh_mutex));
 
@@ -1984,11 +1979,26 @@ bool meshlink_set_port(meshlink_handle_t *mesh, int port) {
                goto done;
        }
 
+       free(mesh->myport);
+       xasprintf(&mesh->myport, "%d", port);
+
+       /* Write meshlink.conf with the updated port number */
+       write_main_config_files(mesh);
+
+       /* Close down the network. This also deletes mesh->self. */
        close_network_connections(mesh);
 
-       // TODO: write meshlink.conf again
+       /* Recreate mesh->self. */
+       mesh->self = new_node();
+       mesh->self->name = xstrdup(mesh->name);
+       mesh->self->devclass = mesh->devclass;
 
-       if(!setup_network(mesh)) {
+       if(!node_read_public_key(mesh, mesh->self)) {
+               logger(NULL, MESHLINK_ERROR, "Could not read our host configuration file!");
+               meshlink_errno = MESHLINK_ESTORAGE;
+               free_node(mesh->self);
+               mesh->self = NULL;
+       } else if(!setup_network(mesh)) {
                meshlink_errno = MESHLINK_ENETWORK;
        } else {
                rval = true;
@@ -2098,7 +2108,10 @@ char *meshlink_invite_ex(meshlink_handle_t *mesh, meshlink_submesh_t *submesh, c
        packmsg_add_str(&inv, s ? s->name : CORE_MESH);
        packmsg_add_int32(&inv, DEV_CLASS_UNKNOWN); /* TODO: allow this to be set by inviter? */
 
-       /* TODO: Add several host config files to bootstrap connections */
+       /* TODO: Add several host config files to bootstrap connections.
+        * Note: make sure we only add config files of nodes that are in the core mesh or the same submesh,
+        * and are not blacklisted.
+        */
        config_t configs[5] = {NULL};
        int count = 0;
 
@@ -2270,7 +2283,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
 
        mesh->blen = 0;
 
-       if(!sendline(mesh->sock, "0 ?%s %d.%d %s", b64key, PROT_MAJOR, 1, mesh->appname)) {
+       if(!sendline(mesh->sock, "0 ?%s %d.%d %s", b64key, PROT_MAJOR, PROT_MINOR, mesh->appname)) {
                logger(mesh, MESHLINK_DEBUG, "Error sending request to %s port %s: %s\n", address, port, strerror(errno));
                closesocket(mesh->sock);
                meshlink_errno = MESHLINK_ENETWORK;
@@ -2482,7 +2495,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
 
                if(!packmsg_input_ok(&in2) || version != MESHLINK_CONFIG_VERSION || !check_id(name)) {
                        free(name);
-                       packmsg_input_invalidate(&in2);
+                       packmsg_input_invalidate(&in);
                        break;
                }
 
@@ -2494,58 +2507,24 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
                node_t *n = lookup_node(mesh, name);
 
                if(n) {
-                       free(name);
                        logger(mesh, MESHLINK_DEBUG, "Node %s already exists, not importing\n", name);
+                       free(name);
                        continue;
                }
 
                n = new_node();
                n->name = name;
-               char *submesh_name = packmsg_get_str_dup(&in2);
-
-               if(submesh_name) {
-                       if(!strcmp(submesh_name, CORE_MESH)) {
-                               n->submesh = NULL;
-                       } else {
-                               n->submesh = lookup_or_create_submesh(mesh, submesh_name);
 
-                               if(!n->submesh) {
-                                       packmsg_input_invalidate(&in2);
-                               }
-                       }
-
-                       free(submesh_name);
-               }
-
-               n->devclass = packmsg_get_int32(&in2);
-               n->status.blacklisted = packmsg_get_bool(&in2);
-               const void *key;
-               uint32_t keylen = packmsg_get_bin_raw(&in2, &key);
-
-               if(keylen == 32) {
-                       n->ecdsa = ecdsa_set_public_key(key);
-               }
-
-               n->canonical_address = packmsg_get_str_dup(&in2);
-               uint32_t count = packmsg_get_array(&in2);
-
-               if(count > 5) {
-                       count = 5;
-               }
-
-               for(uint32_t i = 0; i < count; i++) {
-                       n->recent[i] = packmsg_get_sockaddr(&in2);
-               }
+               config_t config = {data, len};
 
-               if(!packmsg_done(&in2) || keylen != 32) {
-                       packmsg_input_invalidate(&in);
+               if(!node_read_from_config(mesh, n, &config)) {
                        free_node(n);
+                       packmsg_input_invalidate(&in);
                        break;
-               } else {
-                       config_t config = {data, len};
-                       config_write(mesh, n->name, &config);
-                       node_add(mesh, n);
                }
+
+               config_write(mesh, n->name, &config);
+               node_add(mesh, n);
        }
 
        pthread_mutex_unlock(&(mesh->mesh_mutex));
@@ -2584,7 +2563,7 @@ void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
        }
 
        n->status.blacklisted = true;
-       n->status.dirty = true;
+       node_write_config(mesh, n);
        logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n", node->name);
 
        //Immediately terminate any connections we have with the blacklisted node
@@ -2627,7 +2606,7 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) {
        }
 
        n->status.blacklisted = false;
-       n->status.dirty = true;
+       node_write_config(mesh, n);
 
        pthread_mutex_unlock(&(mesh->mesh_mutex));
        return;
@@ -2651,7 +2630,7 @@ void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const
        node_t *n = (node_t *)node;
        memmove(n->recent + 1, n->recent, 4 * sizeof(*n->recent));
        memcpy(n->recent, addr, SALEN(*addr));
-       n->status.dirty = true;
+       node_write_config(mesh, n);
 
        pthread_mutex_unlock(&(mesh->mesh_mutex));
        // @TODO do we want to fire off a connection attempt right away?
index 660adf4ac1e47afcc85be08bf424c63ab94bbb4e..aaf7517683f7f95dc0ff9414a1e26e4ceb40f8da 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -491,23 +491,27 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                        connect_to->last_connect_try = time(NULL);
 
                        /* check if there is already a connection attempt to this node */
-                       bool found = false;
+                       bool skip = false;
 
                        for list_each(outgoing_t, outgoing, mesh->outgoings) {
                                if(outgoing->node == connect_to) {
-                                       found = true;
+                                       logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since it is an outgoing connection already");
+                                       skip = true;
                                        break;
                                }
                        }
 
-                       if(!found) {
+                       if(!node_read_public_key(mesh, connect_to)) {
+                               logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since we don't know this node's public key");
+                               skip = true;
+                       }
+
+                       if(!skip) {
                                logger(mesh, MESHLINK_DEBUG, "Autoconnecting to %s", connect_to->name);
                                outgoing_t *outgoing = xzalloc(sizeof(outgoing_t));
                                outgoing->node = connect_to;
                                list_insert_tail(mesh->outgoings, outgoing);
                                setup_outgoing_connection(mesh, outgoing);
-                       } else {
-                               logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since it is an outgoing connection already");
                        }
                }
 
@@ -588,6 +592,13 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                logger(mesh, MESHLINK_DEBUG, "--- autoconnect end ---");
        }
 
+       for splay_each(node_t, n, mesh->nodes) {
+               if(n->status.dirty) {
+                       node_write_config(mesh, n);
+                       n->status.dirty = false;
+               }
+       }
+
        timeout_set(&mesh->loop, data, &(struct timeval) {
                timeout, rand() % 100000
        });
index 4f2022b7e02de08868d336c7a6a6d3f7d3fbd5dc..64088b3af1877f1fbf88d4d6826fb805c265cd90 100644 (file)
@@ -124,6 +124,34 @@ bool node_read_public_key(meshlink_handle_t *mesh, node_t *n) {
        }
 
        n->ecdsa = ecdsa_set_public_key(key);
+
+       // While we are at it, read known address information
+       if(!n->canonical_address) {
+               n->canonical_address = packmsg_get_str_dup(&in);
+       } else {
+               packmsg_skip_element(&in);
+       }
+
+       // Append any known addresses in the config file to the list we currently have
+       uint32_t known_count = 0;
+
+       for(uint32_t i = 0; i < 5; i++) {
+               if(n->recent[i].sa.sa_family) {
+                       known_count++;
+               }
+       }
+
+       uint32_t count = packmsg_get_array(&in);
+
+       if(count > 5 - known_count) {
+               count = 5 - known_count;
+       }
+
+       for(uint32_t i = 0; i < count; i++) {
+               n->recent[i + known_count] = packmsg_get_sockaddr(&in);
+       }
+
+
        config_free(&config);
        return true;
 }
@@ -207,7 +235,6 @@ bool node_write_config(meshlink_handle_t *mesh, node_t *n) {
        packmsg_add_str(&out, n->name);
        packmsg_add_str(&out, n->submesh ? n->submesh->name : CORE_MESH);
        packmsg_add_int32(&out, n->devclass);
-       assert(n->devclass != 3);
        packmsg_add_bool(&out, n->status.blacklisted);
 
        if(ecdsa_active(n->ecdsa)) {
@@ -456,11 +483,13 @@ void close_network_connections(meshlink_handle_t *mesh) {
        exit_requests(mesh);
        exit_edges(mesh);
        exit_nodes(mesh);
+       exit_submeshes(mesh);
        exit_connections(mesh);
 
-       if(mesh->myport) {
-               free(mesh->myport);
-       }
+       free(mesh->myport);
+       mesh->myport = NULL;
+
+       mesh->self = NULL;
 
        return;
 }
index 895d9aa8116e82aea5fde1c9d3e73652a1cd72ec..4e5c76a2e8809e550b9e04f4b0192b6da049cee3 100644 (file)
@@ -232,11 +232,11 @@ void sockaddrcpy_setport(sockaddr_t *a, const sockaddr_t *b, uint16_t port) {
 
        switch(b->sa.sa_family) {
        case AF_INET:
-               a->in.sin_port = port;
+               a->in.sin_port = htons(port);
                break;
 
        case AF_INET6:
-               a->in6.sin6_port = port;
+               a->in6.sin6_port = htons(port);
                break;
 
        default:
index 4f4f599932caa1d6985afdc689b1a9d43b670310..45784668c524211641b7cc22cfa39a33b58215fe 100644 (file)
@@ -81,6 +81,7 @@ void free_node(node_t *n) {
        }
 
        free(n->name);
+       free(n->canonical_address);
 
        free(n);
 }
index 9fec1ffad737451a94d17f7b5d5132196a0ff7bc..d26b0f651f3dde6c374a7dcd49784d998bb6efde 100644 (file)
@@ -164,9 +164,8 @@ static bool finalize_invitation(meshlink_handle_t *mesh, connection_t *c, const
        n->devclass = DEV_CLASS_UNKNOWN;
        n->ecdsa = ecdsa_set_public_key(data);
        n->submesh = c->submesh;
-       n->status.dirty = true;
        node_add(mesh, n);
-       // TODO: immediately write the config file?
+       node_write_config(mesh, n);
 
        logger(mesh, MESHLINK_INFO, "Key successfully received from %s", c->name);
 
index 7d4a326ed733cd9bf551e4f3bf0ea041c34e8934..a3bccc144e0d863abeae8857ac6753e60575f64e 100644 (file)
@@ -35,7 +35,10 @@ void init_submeshes(meshlink_handle_t *mesh) {
 }
 
 void exit_submeshes(meshlink_handle_t *mesh) {
-       list_delete_list(mesh->submeshes);
+       if(mesh->submeshes) {
+               list_delete_list(mesh->submeshes);
+       }
+
        mesh->submeshes = NULL;
 }
 
@@ -155,4 +158,4 @@ bool submesh_allows_node(const submesh_t *submesh, const node_t *node) {
        } else {
                return false;
        }
-}
\ No newline at end of file
+}