]> git.meshlink.io Git - meshlink/blobdiff - src/meshlink.c
Check the return value of node_write_config() while handling invitations.
[meshlink] / src / meshlink.c
index bb77ccf85da0ad8687d8520b76278738df1ddf12..7a01bd0ffae8f921f7e3b28457e26f6198b7b6b2 100644 (file)
@@ -333,7 +333,7 @@ void remove_duplicate_hostnames(char *host[], char *port[], int n) {
                        break;
                }
 
-               if(found) {
+               if(found || !is_valid_hostname(host[i])) {
                        free(host[i]);
                        free(port[i]);
                        host[i] = NULL;
@@ -417,7 +417,7 @@ static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) {
                        char resolved_port[NI_MAXSERV];
                        err = getnameinfo(ai_in->ai_addr, ai_in->ai_addrlen, resolved_host, sizeof resolved_host, resolved_port, sizeof resolved_port, NI_NUMERICSERV);
 
-                       if(err) {
+                       if(err || !is_valid_hostname(resolved_host)) {
                                freeaddrinfo(ai_in);
                                continue;
                        }
@@ -514,9 +514,9 @@ static bool try_bind(int port) {
        return true;
 }
 
-int check_port(meshlink_handle_t *mesh) {
+static int check_port(meshlink_handle_t *mesh) {
        for(int i = 0; i < 1000; i++) {
-               int port = 0x1000 + (rand() & 0x7fff);
+               int port = 0x1000 + prng(mesh, 0x8000);
 
                if(try_bind(port)) {
                        free(mesh->myport);
@@ -846,6 +846,7 @@ static struct timeval idle(event_loop_t *loop, void *data) {
 // Get our local address(es) by simulating connecting to an Internet host.
 static void add_local_addresses(meshlink_handle_t *mesh) {
        struct sockaddr_storage sn;
+       sn.ss_family = AF_UNKNOWN;
        socklen_t sl = sizeof(sn);
 
        // IPv4 example.org
@@ -1013,13 +1014,14 @@ meshlink_open_params_t *meshlink_open_params_init(const char *confbase, const ch
 
        if(!name || !*name) {
                logger(NULL, MESHLINK_ERROR, "No name given!\n");
-               //return NULL;
-       } else { //check name only if there is a name != NULL
-               if(!check_id(name)) {
-                       logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
-                       meshlink_errno = MESHLINK_EINVAL;
-                       return NULL;
-               }
+               meshlink_errno = MESHLINK_EINVAL;
+               return NULL;
+       };
+
+       if(!check_id(name)) {
+               logger(NULL, MESHLINK_ERROR, "Invalid name given!\n");
+               meshlink_errno = MESHLINK_EINVAL;
+               return NULL;
        }
 
        if(devclass < 0 || devclass >= DEV_CLASS_COUNT) {
@@ -1284,6 +1286,8 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) {
        mesh->log_cb = global_log_cb;
        mesh->log_level = global_log_level;
 
+       randomize(&mesh->prng_state, sizeof(mesh->prng_state));
+
        memcpy(mesh->dev_class_traits, default_class_traits, sizeof(default_class_traits));
 
        if(usingname) {
@@ -1602,15 +1606,23 @@ void meshlink_close(meshlink_handle_t *mesh) {
                close(mesh->netns);
        }
 
+       for(vpn_packet_t *packet; (packet = meshlink_queue_pop(&mesh->outpacketqueue));) {
+               free(packet);
+       }
+
+       meshlink_queue_exit(&mesh->outpacketqueue);
+
        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);
 
+       pthread_mutex_unlock(&mesh->mesh_mutex);
+       pthread_mutex_destroy(&mesh->mesh_mutex);
+
        memset(mesh, 0, sizeof(*mesh));
 
        free(mesh);
@@ -1706,6 +1718,17 @@ void meshlink_set_log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, me
        }
 }
 
+void meshlink_set_error_cb(struct meshlink_handle *mesh, meshlink_error_cb_t cb) {
+       if(!mesh) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return;
+       }
+
+       pthread_mutex_lock(&(mesh->mesh_mutex));
+       mesh->error_cb = cb;
+       pthread_mutex_unlock(&(mesh->mesh_mutex));
+}
+
 bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const void *data, size_t len) {
        meshlink_packethdr_t *hdr;
 
@@ -1765,8 +1788,9 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const
        return true;
 }
 
-void meshlink_send_from_queue(event_loop_t *loop, meshlink_handle_t *mesh) {
+void meshlink_send_from_queue(event_loop_t *loop, void *data) {
        (void)loop;
+       meshlink_handle_t *mesh = data;
        vpn_packet_t *packet = meshlink_queue_pop(&mesh->outpacketqueue);
 
        if(!packet) {
@@ -1776,6 +1800,8 @@ void meshlink_send_from_queue(event_loop_t *loop, meshlink_handle_t *mesh) {
        mesh->self->in_packets++;
        mesh->self->in_bytes += packet->len;
        route(mesh, mesh->self, packet);
+
+       free(packet);
 }
 
 ssize_t meshlink_get_pmtu(meshlink_handle_t *mesh, meshlink_node_t *destination) {
@@ -1847,6 +1873,11 @@ meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) {
        pthread_mutex_lock(&(mesh->mesh_mutex));
        node = (meshlink_node_t *)lookup_node(mesh, (char *)name); // TODO: make lookup_node() use const
        pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+       if(!node) {
+               meshlink_errno = MESHLINK_ENOENT;
+       }
+
        return node;
 }
 
@@ -1861,6 +1892,11 @@ meshlink_submesh_t *meshlink_get_submesh(meshlink_handle_t *mesh, const char *na
        pthread_mutex_lock(&(mesh->mesh_mutex));
        submesh = (meshlink_submesh_t *)lookup_submesh(mesh, name);
        pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+       if(!submesh) {
+               meshlink_errno = MESHLINK_ENOENT;
+       }
+
        return submesh;
 }
 
@@ -2140,7 +2176,13 @@ int meshlink_get_port(meshlink_handle_t *mesh) {
                return -1;
        }
 
-       return atoi(mesh->myport);
+       int port;
+
+       pthread_mutex_lock(&(mesh->mesh_mutex));
+       port = atoi(mesh->myport);
+       pthread_mutex_unlock(&(mesh->mesh_mutex));
+
+       return port;
 }
 
 bool meshlink_set_port(meshlink_handle_t *mesh, int port) {
@@ -2186,10 +2228,10 @@ bool meshlink_set_port(meshlink_handle_t *mesh, int port) {
                meshlink_errno = MESHLINK_ESTORAGE;
                free_node(mesh->self);
                mesh->self = NULL;
+               goto done;
        } else if(!setup_network(mesh)) {
                meshlink_errno = MESHLINK_ENETWORK;
-       } else {
-               rval = true;
+               goto done;
        }
 
        /* Rebuild our own list of recent addresses */
@@ -2199,9 +2241,7 @@ bool meshlink_set_port(meshlink_handle_t *mesh, int port) {
        /* Write meshlink.conf with the updated port number */
        write_main_config_files(mesh);
 
-       if(!config_sync(mesh, "current")) {
-               return false;
-       }
+       rval = config_sync(mesh, "current");
 
 done:
        pthread_mutex_unlock(&(mesh->mesh_mutex));
@@ -2737,6 +2777,8 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
 
        pthread_mutex_unlock(&(mesh->mesh_mutex));
 
+       free(buf);
+
        if(!packmsg_done(&in)) {
                logger(mesh, MESHLINK_ERROR, "Invalid data\n");
                meshlink_errno = MESHLINK_EPEER;
@@ -3051,9 +3093,15 @@ static void channel_poll(struct utcp_connection *connection, size_t len) {
 }
 
 void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_poll_cb_t cb) {
-       (void)mesh;
+       if(!mesh || !channel) {
+               meshlink_errno = MESHLINK_EINVAL;
+               return;
+       }
+
+       pthread_mutex_lock(&mesh->mesh_mutex);
        channel->poll_cb = cb;
        utcp_set_poll_cb(channel->c, (cb || channel->aio_send) ? channel_poll : NULL);
+       pthread_mutex_unlock(&mesh->mesh_mutex);
 }
 
 void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_accept_cb_t cb) {
@@ -3111,6 +3159,8 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n
                return NULL;
        }
 
+       pthread_mutex_lock(&mesh->mesh_mutex);
+
        node_t *n = (node_t *)node;
 
        if(!n->utcp) {
@@ -3119,12 +3169,14 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n
 
                if(!n->utcp) {
                        meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL;
+                       pthread_mutex_unlock(&mesh->mesh_mutex);
                        return NULL;
                }
        }
 
        if(n->status.blacklisted) {
                logger(mesh, MESHLINK_ERROR, "Cannot open a channel with blacklisted node\n");
+               pthread_mutex_unlock(&mesh->mesh_mutex);
                return NULL;
        }
 
@@ -3133,6 +3185,8 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n
        channel->receive_cb = cb;
        channel->c = utcp_connect_ex(n->utcp, port, channel_recv, channel, flags);
 
+       pthread_mutex_unlock(&mesh->mesh_mutex);
+
        if(!channel->c) {
                meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL;
                free(channel);
@@ -3152,7 +3206,9 @@ void meshlink_channel_shutdown(meshlink_handle_t *mesh, meshlink_channel_t *chan
                return;
        }
 
+       pthread_mutex_lock(&mesh->mesh_mutex);
        utcp_shutdown(channel->c, direction);
+       pthread_mutex_unlock(&mesh->mesh_mutex);
 }
 
 void meshlink_channel_close(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
@@ -3161,6 +3217,8 @@ void meshlink_channel_close(meshlink_handle_t *mesh, meshlink_channel_t *channel
                return;
        }
 
+       pthread_mutex_lock(&mesh->mesh_mutex);
+
        utcp_close(channel->c);
 
        /* Clean up any outstanding AIO buffers. */
@@ -3176,6 +3234,8 @@ void meshlink_channel_close(meshlink_handle_t *mesh, meshlink_channel_t *channel
                free(aio);
        }
 
+       pthread_mutex_unlock(&mesh->mesh_mutex);
+
        free(channel);
 }
 
@@ -3468,18 +3528,31 @@ void meshlink_set_dev_class_timeouts(meshlink_handle_t *mesh, dev_class_t devcla
 void handle_network_change(meshlink_handle_t *mesh, bool online) {
        (void)online;
 
-       if(!mesh->connections) {
+       if(!mesh->connections || !mesh->loop.running) {
                return;
        }
 
        retry(mesh);
 }
 
+void call_error_cb(meshlink_handle_t *mesh, meshlink_errno_t meshlink_errno) {
+       // We should only call the callback function if we are in the background thread.
+       if(!mesh->error_cb) {
+               return;
+       }
+
+       if(!mesh->threadstarted) {
+               return;
+       }
+
+       if(mesh->thread == pthread_self()) {
+               mesh->error_cb(mesh, meshlink_errno);
+       }
+}
+
+
 static void __attribute__((constructor)) meshlink_init(void) {
        crypto_init();
-       unsigned int seed;
-       randomize(&seed, sizeof(seed));
-       srand(seed);
 }
 
 static void __attribute__((destructor)) meshlink_exit(void) {