]> 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 0826487674f2467d24c8d201968e8e815b1a702b..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;
                        }
@@ -516,7 +516,7 @@ static bool try_bind(int port) {
 
 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;
 }
 
@@ -2192,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 */
@@ -2205,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));
@@ -2743,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;
@@ -3492,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) {