]> git.meshlink.io Git - meshlink/blobdiff - src/meshlink.c
Move meshlink_get_all_edges_state() to devtools_get_all_edges().
[meshlink] / src / meshlink.c
index 6a2c99da68d8c416f79704a3dd8b615ba8906921..e70ac5f624589023139dc54fda2ba797dd391940 100644 (file)
@@ -126,7 +126,7 @@ static bool fcopy(FILE *out, const char *filename) {
 
        char buf[1024];
        size_t len;
-       while((len = fread(buf, 1, sizeof buf, in)))
+       while((len = fread(buf, 1, sizeof(buf), in)))
                fwrite(buf, len, 1, out);
        fclose(in);
        return true;
@@ -148,7 +148,7 @@ static void scan_for_hostname(const char *filename, char **hostname, char **port
        if(!f)
                return;
 
-       while(fgets(line, sizeof line, f)) {
+       while(fgets(line, sizeof(line), f)) {
                if(!rstrip(line))
                        continue;
                char *p = line, *q;
@@ -199,8 +199,8 @@ static void set_timeout(int sock, int timeout) {
        tv.tv_sec = timeout / 1000;
        tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;
 #endif
-       setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
-       setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv);
+       setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+       setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
 }
 
 char *meshlink_get_external_address(meshlink_handle_t *mesh) {
@@ -222,8 +222,8 @@ char *meshlink_get_external_address(meshlink_handle_t *mesh) {
                        }
                }
                if(s >= 0) {
-                       send(s, request, sizeof request - 1, 0);
-                       int len = recv(s, line, sizeof line - 1, MSG_WAITALL);
+                       send(s, request, sizeof(request) - 1, 0);
+                       int len = recv(s, line, sizeof(line) - 1, MSG_WAITALL);
                        if(len > 0) {
                                line[len] = 0;
                                if(line[len - 1] == '\n')
@@ -255,7 +255,7 @@ char *meshlink_get_external_address(meshlink_handle_t *mesh) {
        return hostname;
 }
 
-static char *get_my_hostname(meshlink_handle_tmesh) {
+static char *get_my_hostname(meshlink_handle_t *mesh) {
        char *hostname = NULL;
        char *port = NULL;
        char *hostport = NULL;
@@ -264,7 +264,7 @@ static char *get_my_hostname(meshlink_handle_t* mesh) {
        FILE *f;
 
        // Use first Address statement in own host config file
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
        scan_for_hostname(filename, &hostname, &port);
 
        if(hostname)
@@ -303,7 +303,7 @@ static char *get_line(const char **data) {
        if(!data || !*data)
                return NULL;
 
-       if(!**data) {
+       if(! **data) {
                *data = NULL;
                return NULL;
        }
@@ -311,7 +311,7 @@ static char *get_line(const char **data) {
        static char line[1024];
        const char *end = strchr(*data, '\n');
        size_t len = end ? end - *data : strlen(*data);
-       if(len >= sizeof line) {
+       if(len >= sizeof(line)) {
                logger(NULL, MESHLINK_ERROR, "Maximum line length exceeded!\n");
                return NULL;
        }
@@ -354,7 +354,7 @@ static bool try_bind(int port) {
        };
 
        char portstr[16];
-       snprintf(portstr, sizeof portstr, "%d", port);
+       snprintf(portstr, sizeof(portstr), "%d", port);
 
        if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai)
                return false;
@@ -383,7 +383,7 @@ static int check_port(meshlink_handle_t *mesh) {
                int port = 0x1000 + (rand() & 0x7fff);
                if(try_bind(port)) {
                        char filename[PATH_MAX];
-                       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->name);
+                       snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->name);
                        FILE *f = fopen(filename, "a");
                        if(!f) {
                                logger(mesh, MESHLINK_DEBUG, "Please change MeshLink's Port manually.\n");
@@ -413,7 +413,7 @@ static bool finalize_join(meshlink_handle_t *mesh) {
        }
 
        char filename[PATH_MAX];
-       snprintf(filename, sizeof filename, "%s" SLASH "meshlink.conf", mesh->confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase);
 
        FILE *f = fopen(filename, "w");
        if(!f) {
@@ -423,7 +423,7 @@ static bool finalize_join(meshlink_handle_t *mesh) {
 
        fprintf(f, "Name = %s\n", name);
 
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
        FILE *fh = fopen(filename, "w");
        if(!fh) {
                logger(mesh, MESHLINK_DEBUG, "Could not create file %s: %s\n", filename, strerror(errno));
@@ -496,7 +496,7 @@ static bool finalize_join(meshlink_handle_t *mesh) {
                        return false;
                }
 
-               snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, value);
+               snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, value);
                f = fopen(filename, "w");
 
                if(!f) {
@@ -553,7 +553,7 @@ static bool finalize_join(meshlink_handle_t *mesh) {
 }
 
 static bool invitation_send(void *handle, uint8_t type, const void *data, size_t len) {
-       meshlink_handle_tmesh = handle;
+       meshlink_handle_t *mesh = handle;
        while(len) {
                int result = send(mesh->sock, data, len, 0);
                if(result == -1 && errno == EINTR)
@@ -567,10 +567,10 @@ static bool invitation_send(void *handle, uint8_t type, const void *data, size_t
 }
 
 static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint16_t len) {
-       meshlink_handle_tmesh = handle;
+       meshlink_handle_t *mesh = handle;
        switch(type) {
        case SPTPS_HANDSHAKE:
-               return sptps_send_record(&(mesh->sptps), 0, mesh->cookie, sizeof mesh->cookie);
+               return sptps_send_record(&(mesh->sptps), 0, mesh->cookie, sizeof(mesh)->cookie);
 
        case 0:
                mesh->data = xrealloc(mesh->data, mesh->thedatalen + len + 1);
@@ -596,14 +596,14 @@ static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint
        return true;
 }
 
-static bool recvline(meshlink_handle_tmesh, size_t len) {
+static bool recvline(meshlink_handle_t *mesh, size_t len) {
        char *newline = NULL;
 
        if(!mesh->sock)
                abort();
 
        while(!(newline = memchr(mesh->buffer, '\n', mesh->blen))) {
-               int result = recv(mesh->sock, mesh->buffer + mesh->blen, sizeof mesh->buffer - mesh->blen, 0);
+               int result = recv(mesh->sock, mesh->buffer + mesh->blen, sizeof(mesh)->buffer - mesh->blen, 0);
                if(result == -1 && errno == EINTR)
                        continue;
                else if(result <= 0)
@@ -630,10 +630,10 @@ static bool sendline(int fd, char *format, ...) {
        va_list ap;
 
        va_start(ap, format);
-       blen = vsnprintf(buffer, sizeof buffer, format, ap);
+       blen = vsnprintf(buffer, sizeof(buffer), format, ap);
        va_end(ap);
 
-       if(blen < 1 || blen >= sizeof buffer)
+       if(blen < 1 || blen >= sizeof(buffer))
                return false;
 
        buffer[blen] = '\n';
@@ -666,7 +666,7 @@ static const char *errstr[] = {
 };
 
 const char *meshlink_strerror(meshlink_errno_t err) {
-       if(err < 0 || err >= sizeof errstr / sizeof *errstr)
+       if(err < 0 || err >= sizeof(errstr) / sizeof(*errstr))
                return "Invalid error code";
        return errstr[err];
 }
@@ -685,7 +685,7 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) {
        } else
                logger(mesh, MESHLINK_DEBUG, "Done.\n");
 
-       snprintf(privname, sizeof privname, "%s" SLASH "ecdsa_key.priv", mesh->confbase);
+       snprintf(privname, sizeof(privname), "%s" SLASH "ecdsa_key.priv", mesh->confbase);
        f = fopen(privname, "wb");
 
        if(!f) {
@@ -707,7 +707,7 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) {
 
        fclose(f);
 
-       snprintf(pubname, sizeof pubname, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->name);
+       snprintf(pubname, sizeof(pubname), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->name);
        f = fopen(pubname, "a");
 
        if(!f) {
@@ -766,7 +766,7 @@ static bool getlocaladdrname(char *destaddr, char *host, socklen_t hostlen) {
        freeaddrinfo(rai);
 
        struct sockaddr_storage sn;
-       socklen_t sl = sizeof sn;
+       socklen_t sl = sizeof(sn);
 
        if(getsockname(sock, (struct sockaddr *)&sn, &sl))
                return false;
@@ -784,15 +784,15 @@ static void add_local_addresses(meshlink_handle_t *mesh) {
 
        // IPv4 example.org
 
-       if(getlocaladdrname("93.184.216.34", host, sizeof host)) {
-               snprintf(entry, sizeof entry, "%s %s", host, mesh->myport);
+       if(getlocaladdrname("93.184.216.34", host, sizeof(host))) {
+               snprintf(entry, sizeof(entry), "%s %s", host, mesh->myport);
                append_config_file(mesh, mesh->name, "Address", entry);
        }
 
        // IPv6 example.org
 
-       if(getlocaladdrname("2606:2800:220:1:248:1893:25c8:1946", host, sizeof host)) {
-               snprintf(entry, sizeof entry, "%s %s", host, mesh->myport);
+       if(getlocaladdrname("2606:2800:220:1:248:1893:25c8:1946", host, sizeof(host))) {
+               snprintf(entry, sizeof(entry), "%s %s", host, mesh->myport);
                append_config_file(mesh, mesh->name, "Address", entry);
        }
 }
@@ -805,7 +805,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) {
        }
 
        char filename[PATH_MAX];
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts", mesh->confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "hosts", mesh->confbase);
 
        if(mkdir(filename, 0777) && errno != EEXIST) {
                logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
@@ -813,7 +813,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) {
                return false;
        }
 
-       snprintf(filename, sizeof filename, "%s" SLASH "meshlink.conf", mesh->confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase);
 
        if(!access(filename, F_OK)) {
                logger(mesh, MESHLINK_DEBUG, "Configuration file %s already exists!\n", filename);
@@ -841,7 +841,7 @@ static bool meshlink_setup(meshlink_handle_t *mesh) {
        return true;
 }
 
-meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const charappname, dev_class_t devclass) {
+meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const char *appname, dev_class_t devclass) {
        // Validate arguments provided by the application
        bool usingname = false;
 
@@ -897,7 +897,7 @@ meshlink_handle_t *meshlink_open(const char *confbase, const char *name, const c
        // Check whether meshlink.conf already exists
 
        char filename[PATH_MAX];
-       snprintf(filename, sizeof filename, "%s" SLASH "meshlink.conf", confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", confbase);
 
        if(access(filename, R_OK)) {
                if(errno == ENOENT) {
@@ -1001,13 +1001,13 @@ bool meshlink_start(meshlink_handle_t *mesh) {
 
        if(pthread_create(&mesh->thread, NULL, meshlink_main_loop, mesh) != 0) {
                logger(mesh, MESHLINK_DEBUG, "Could not start thread: %s\n", strerror(errno));
-               memset(&mesh->thread, 0, sizeof mesh->thread);
+               memset(&mesh->thread, 0, sizeof(mesh)->thread);
                meshlink_errno = MESHLINK_EINTERNAL;
                pthread_mutex_unlock(&(mesh->mesh_mutex));
                return false;
        }
 
-       mesh->threadstarted=true;
+       mesh->threadstarted = true;
 
        if(mesh->discovery)
                discovery_start(mesh);
@@ -1044,6 +1044,20 @@ void meshlink_stop(meshlink_handle_t *mesh) {
 
        mesh->threadstarted = false;
 
+       // Close all metaconnections
+       if(mesh->connections) {
+               for(list_node_t *node = mesh->connections->head, *next; node; node = next) {
+                       next = node->next;
+                       connection_t *c = node->data;
+                       c->outgoing = NULL;
+                       terminate_connection(mesh, c, false);
+               }
+       }
+
+       if(mesh->outgoings)
+               list_delete_list(mesh->outgoings);
+       mesh->outgoings = NULL;
+
        pthread_mutex_unlock(&(mesh->mesh_mutex));
 }
 
@@ -1080,7 +1094,7 @@ void meshlink_close(meshlink_handle_t *mesh) {
        free(mesh->confbase);
        pthread_mutex_destroy(&(mesh->mesh_mutex));
 
-       memset(mesh, 0, sizeof *mesh);
+       memset(mesh, 0, sizeof(*mesh));
 
        free(mesh);
 }
@@ -1093,7 +1107,7 @@ static void deltree(const char *dirname) {
                        if(ent->d_name[0] == '.')
                                continue;
                        char filename[PATH_MAX];
-                       snprintf(filename, sizeof filename, "%s" SLASH "%s", dirname, ent->d_name);
+                       snprintf(filename, sizeof(filename), "%s" SLASH "%s", dirname, ent->d_name);
                        if(unlink(filename))
                                deltree(filename);
                }
@@ -1110,7 +1124,7 @@ bool meshlink_destroy(const char *confbase) {
        }
 
        char filename[PATH_MAX];
-       snprintf(filename, sizeof filename, "%s" SLASH "meshlink.conf", confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", confbase);
 
        if(unlink(filename)) {
                if(errno == ENOENT) {
@@ -1166,7 +1180,7 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const
        meshlink_packethdr_t *hdr;
 
        // Validate arguments
-       if(!mesh || !destination || len >= MAXSIZE - sizeof *hdr) {
+       if(!mesh || !destination || len >= MAXSIZE - sizeof(*hdr)) {
                meshlink_errno = MESHLINK_EINVAL;
                return false;
        }
@@ -1180,7 +1194,7 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const
        }
 
        // Prepare the packet
-       vpn_packet_t *packet = malloc(sizeof *packet);
+       vpn_packet_t *packet = malloc(sizeof(*packet));
        if(!packet) {
                meshlink_errno = MESHLINK_ENOMEM;
                return false;
@@ -1188,16 +1202,16 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const
 
        packet->probe = false;
        packet->tcp = false;
-       packet->len = len + sizeof *hdr;
+       packet->len = len + sizeof(*hdr);
 
        hdr = (meshlink_packethdr_t *)packet->data;
-       memset(hdr, 0, sizeof *hdr);
+       memset(hdr, 0, sizeof(*hdr));
        // leave the last byte as 0 to make sure strings are always
        // null-terminated if they are longer than the buffer
-       strncpy(hdr->destination, destination->name, (sizeof hdr->destination) - 1);
-       strncpy(hdr->source, mesh->self->name, (sizeof hdr->source) -1);
+       strncpy((char *)hdr->destination, destination->name, (sizeof(hdr)->destination) - 1);
+       strncpy((char *)hdr->source, mesh->self->name, (sizeof(hdr)->source) - 1);
 
-       memcpy(packet->data + sizeof *hdr, data, len);
+       memcpy(packet->data + sizeof(*hdr), data, len);
 
        // Queue it
        if(!meshlink_queue_push(&mesh->outpacketqueue, packet)) {
@@ -1207,7 +1221,7 @@ bool meshlink_send(meshlink_handle_t *mesh, meshlink_node_t *destination, const
        }
 
        // Notify event loop
-       signal_trigger(&(mesh->loop),&(mesh->datafromapp));
+       signal_trigger(&(mesh->loop), &(mesh->datafromapp));
 
        return true;
 }
@@ -1302,7 +1316,7 @@ meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_
        pthread_mutex_lock(&(mesh->mesh_mutex));
 
        *nmemb = mesh->nodes->count;
-       result = realloc(nodes, *nmemb * sizeof *nodes);
+       result = realloc(nodes, *nmemb * sizeof(*nodes));
 
        if(result) {
                meshlink_node_t **p = result;
@@ -1374,7 +1388,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) {
 
        pthread_mutex_lock(&(mesh->mesh_mutex));
 
-       snprintf(filename, sizeof filename, "%s" SLASH "invitations", mesh->confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "invitations", mesh->confbase);
        if(mkdir(filename, 0700) && errno != EEXIST) {
                logger(mesh, MESHLINK_DEBUG, "Could not create directory %s: %s\n", filename, strerror(errno));
                meshlink_errno = MESHLINK_ESTORAGE;
@@ -1401,7 +1415,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) {
                        continue;
                char invname[PATH_MAX];
                struct stat st;
-               snprintf(invname, sizeof invname, "%s" SLASH "%s", filename, ent->d_name);
+               snprintf(invname, sizeof(invname), "%s" SLASH "%s", filename, ent->d_name);
                if(!stat(invname, &st)) {
                        if(mesh->invitation_key && deadline < st.st_mtime)
                                count++;
@@ -1423,7 +1437,7 @@ static bool refresh_invitation_key(meshlink_handle_t *mesh) {
 
        closedir(dir);
 
-       snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "ecdsa_key.priv", mesh->confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "invitations" SLASH "ecdsa_key.priv", mesh->confbase);
 
        // Remove the key if there are no outstanding invitations.
        if(!count) {
@@ -1560,8 +1574,8 @@ bool meshlink_set_port(meshlink_handle_t *mesh, int port) {
        exit_configuration(&mesh->config);
 
        char portstr[10];
-       snprintf(portstr, sizeof portstr, "%d", port);
-       portstr[sizeof portstr - 1] = 0;
+       snprintf(portstr, sizeof(portstr), "%d", port);
+       portstr[sizeof(portstr) - 1] = 0;
 
        modify_config_file(mesh, mesh->name, "Port", portstr, true);
 
@@ -1598,7 +1612,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
 
        // Ensure no host configuration file with that name exists
        char filename[PATH_MAX];
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
        if(!access(filename, F_OK)) {
                logger(mesh, MESHLINK_DEBUG, "A host config file for %s already exists!\n", name);
                meshlink_errno = MESHLINK_EEXIST;
@@ -1644,8 +1658,8 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
        char buf[18 + strlen(fingerprint)];
        char cookiehash[64];
        memcpy(buf, cookie, 18);
-       memcpy(buf + 18, fingerprint, sizeof buf - 18);
-       sha512(buf, sizeof buf, cookiehash);
+       memcpy(buf + 18, fingerprint, sizeof(buf) - 18);
+       sha512(buf, sizeof(buf), cookiehash);
        b64encode_urlsafe(cookiehash, cookiehash, 18);
 
        b64encode_urlsafe(cookie, cookie, 18);
@@ -1653,7 +1667,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
        free(fingerprint);
 
        // Create a file containing the details of the invitation.
-       snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "%s", mesh->confbase, cookiehash);
+       snprintf(filename, sizeof(filename), "%s" SLASH "invitations" SLASH "%s", mesh->confbase, cookiehash);
        int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
        if(!ifd) {
                logger(mesh, MESHLINK_DEBUG, "Could not create invitation file %s: %s\n", filename, strerror(errno));
@@ -1672,11 +1686,11 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
        fprintf(f, "ConnectTo = %s\n", mesh->self->name);
 
        // Copy Broadcast and Mode
-       snprintf(filename, sizeof filename, "%s" SLASH "meshlink.conf", mesh->confbase);
+       snprintf(filename, sizeof(filename), "%s" SLASH "meshlink.conf", mesh->confbase);
        FILE *tc = fopen(filename,  "r");
        if(tc) {
                char buf[1024];
-               while(fgets(buf, sizeof buf, tc)) {
+               while(fgets(buf, sizeof(buf), tc)) {
                        if((!strncasecmp(buf, "Mode", 4) && strchr(" \t=", buf[4]))
                                        || (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) {
                                fputs(buf, f);
@@ -1696,7 +1710,7 @@ char *meshlink_invite(meshlink_handle_t *mesh, const char *name) {
        fprintf(f, "#---------------------------------------------------------------#\n");
        fprintf(f, "Name = %s\n", mesh->self->name);
 
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
+       snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
        fcopy(f, filename);
        fclose(f);
 
@@ -1817,7 +1831,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
        char hisname[4096] = "";
        int code, hismajor, hisminor = 0;
 
-       if(!recvline(mesh, sizeof mesh->line) || sscanf(mesh->line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(mesh, sizeof mesh->line) || !rstrip(mesh->line) || sscanf(mesh->line, "%d ", &code) != 1 || code != ACK || strlen(mesh->line) < 3) {
+       if(!recvline(mesh, sizeof(mesh)->line) || sscanf(mesh->line, "%d %s %d.%d", &code, hisname, &hismajor, &hisminor) < 3 || code != 0 || hismajor != PROT_MAJOR || !check_id(hisname) || !recvline(mesh, sizeof(mesh)->line) || !rstrip(mesh->line) || sscanf(mesh->line, "%d ", &code) != 1 || code != ACK || strlen(mesh->line) < 3) {
                logger(mesh, MESHLINK_DEBUG, "Cannot read greeting from peer\n");
                closesocket(mesh->sock);
                meshlink_errno = MESHLINK_ENETWORK;
@@ -1850,7 +1864,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
        }
 
        // Start an SPTPS session
-       if(!sptps_start(&mesh->sptps, mesh, true, false, key, hiskey, meshlink_invitation_label, sizeof meshlink_invitation_label, invitation_send, invitation_receive)) {
+       if(!sptps_start(&mesh->sptps, mesh, true, false, key, hiskey, meshlink_invitation_label, sizeof(meshlink_invitation_label), invitation_send, invitation_receive)) {
                meshlink_errno = MESHLINK_EINTERNAL;
                pthread_mutex_unlock(&(mesh->mesh_mutex));
                return false;
@@ -1865,7 +1879,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
 
        int len;
 
-       while((len = recv(mesh->sock, mesh->line, sizeof mesh->line, 0))) {
+       while((len = recv(mesh->sock, mesh->line, sizeof(mesh)->line, 0))) {
                if(len < 0) {
                        if(errno == EINTR)
                                continue;
@@ -1913,7 +1927,7 @@ char *meshlink_export(meshlink_handle_t *mesh) {
        pthread_mutex_lock(&(mesh->mesh_mutex));
 
        char filename[PATH_MAX];
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
+       snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name);
        FILE *f = fopen(filename, "r");
        if(!f) {
                logger(mesh, MESHLINK_DEBUG, "Could not open %s: %s\n", filename, strerror(errno));
@@ -1932,6 +1946,7 @@ char *meshlink_export(meshlink_handle_t *mesh) {
        if(fread(buf + len - fsize - 1, fsize, 1, f) != 1) {
                logger(mesh, MESHLINK_DEBUG, "Error reading from %s: %s\n", filename, strerror(errno));
                fclose(f);
+               free(buf);
                meshlink_errno = MESHLINK_ESTORAGE;
                pthread_mutex_unlock(&(mesh->mesh_mutex));
                return NULL;
@@ -1979,7 +1994,7 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
        }
 
        char filename[PATH_MAX];
-       snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+       snprintf(filename, sizeof(filename), "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
        if(!access(filename, F_OK)) {
                logger(mesh, MESHLINK_DEBUG, "File %s already exists, not importing\n", filename);
                meshlink_errno = MESHLINK_EEXIST;
@@ -2020,9 +2035,9 @@ void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) {
        pthread_mutex_lock(&(mesh->mesh_mutex));
 
        node_t *n;
-       n = (node_t*)node;
-       n->status.blacklisted=true;
-       logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n",node->name);
+       n = (node_t *)node;
+       n->status.blacklisted = true;
+       logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n", node->name);
 
        //Make blacklisting persistent in the config file
        append_config_file(mesh, n->name, "blacklisted", "yes");
@@ -2070,8 +2085,8 @@ void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const
 
        if(host && port) {
                xasprintf(&str, "%s %s", host, port);
-               if((strncmp("fe80",host,4) != 0) && (strncmp("127.",host,4) != 0) && (strcmp("localhost",host) !=0))
-                       append_config_file(mesh, node->name, "Address", str);
+               if((strncmp("fe80", host, 4) != 0) && (strncmp("127.", host, 4) != 0) && (strcmp("localhost", host) != 0))
+                       modify_config_file(mesh, node->name, "Address", str, 5);
                else
                        logger(mesh, MESHLINK_DEBUG, "Not adding Link Local IPv6 Address to config\n");
        }
@@ -2084,70 +2099,10 @@ void meshlink_hint_address(meshlink_handle_t *mesh, meshlink_node_t *node, const
        // @TODO do we want to fire off a connection attempt right away?
 }
 
-/* Return an array of edges in the current network graph.
- * Data captures the current state and will not be updated.
- * Caller must deallocate data when done.
- */
-meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink_edge_t **edges, size_t *nmemb) {
-       if(!mesh || !nmemb || (*nmemb && !edges)) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return NULL;
-       }
-
-       pthread_mutex_lock(&(mesh->mesh_mutex));
-
-       meshlink_edge_t **result = NULL;
-       meshlink_edge_t *copy = NULL;
-       int result_size = 0;
-
-       result_size = mesh->edges->count;
-
-       // if result is smaller than edges, we have to dealloc all the excess meshlink_edge_t
-       if(result_size > *nmemb)
-               result = realloc(edges, result_size * sizeof(meshlink_edge_t*));
-       else
-               result = edges;
-
-       if(result) {
-               meshlink_edge_t **p = result;
-               int n = 0;
-               for splay_each(edge_t, e, mesh->edges) {
-                       // skip edges that do not represent a two-directional connection
-                       if((!e->reverse) || (e->reverse->to != e->from)) {
-                               result_size--;
-                               continue;
-                       }
-                       n++;
-                       // the first *nmemb members of result can be re-used
-                       if(n > *nmemb)
-                               copy = xzalloc(sizeof *copy);
-                       else
-                               copy = *p;
-                       copy->from = (meshlink_node_t*)e->from;
-                       copy->to = (meshlink_node_t*)e->to;
-                       copy->address = e->address.storage;
-                       copy->options = e->options;
-                       copy->weight = e->weight;
-                       *p++ = copy;
-               }
-               // shrink result to the actual amount of memory used
-               for(int i = *nmemb; i > result_size; i--)
-                       free(result[i - 1]);
-               result = realloc(result, result_size * sizeof(meshlink_edge_t*));
-               *nmemb = result_size;
-       } else {
-               *nmemb = 0;
-               meshlink_errno = MESHLINK_ENOMEM;
-       }
-
-       pthread_mutex_unlock(&(mesh->mesh_mutex));
-
-       return result;
-}
-
 static bool channel_pre_accept(struct utcp *utcp, uint16_t port) {
-       //TODO: implement
-       return true;
+       node_t *n = utcp->priv;
+       meshlink_handle_t *mesh = n->mesh;
+       return mesh->channel_accept_cb;
 }
 
 static ssize_t channel_recv(struct utcp_connection *connection, const void *data, size_t len) {
@@ -2156,7 +2111,9 @@ static ssize_t channel_recv(struct utcp_connection *connection, const void *data
                abort();
        node_t *n = channel->node;
        meshlink_handle_t *mesh = n->mesh;
-       if(channel->receive_cb)
+       if(n->status.destroyed)
+               meshlink_channel_close(mesh, channel);
+       else if(channel->receive_cb)
                channel->receive_cb(mesh, channel, data, len);
        return len;
 }
@@ -2168,7 +2125,7 @@ static void channel_accept(struct utcp_connection *utcp_connection, uint16_t por
        meshlink_handle_t *mesh = n->mesh;
        if(!mesh->channel_accept_cb)
                return;
-       meshlink_channel_t *channel = xzalloc(sizeof *channel);
+       meshlink_channel_t *channel = xzalloc(sizeof(*channel));
        channel->node = n;
        channel->c = utcp_connection;
        if(mesh->channel_accept_cb(mesh, channel, port, NULL, 0))
@@ -2245,7 +2202,7 @@ meshlink_channel_t *meshlink_channel_open_ex(meshlink_handle_t *mesh, meshlink_n
                        return NULL;
                }
        }
-       meshlink_channel_t *channel = xzalloc(sizeof *channel);
+       meshlink_channel_t *channel = xzalloc(sizeof(*channel));
        channel->node = n;
        channel->receive_cb = cb;
        channel->c = utcp_connect_ex(n->utcp, port, channel_recv, channel, flags);
@@ -2351,7 +2308,7 @@ end:
 static void __attribute__((constructor)) meshlink_init(void) {
        crypto_init();
        unsigned int seed;
-       randomize(&seed, sizeof seed);
+       randomize(&seed, sizeof(seed));
        srand(seed);
 }
 
@@ -2360,7 +2317,7 @@ static void __attribute__((destructor)) meshlink_exit(void) {
 }
 
 /// Device class traits
-dev_class_traits_t dev_class_traits[_DEV_CLASS_MAX +1] = {
+dev_class_traits_t dev_class_traits[_DEV_CLASS_MAX + 1] = {
        { .min_connects = 3, .max_connects = 10000, .edge_weight = 1 }, // DEV_CLASS_BACKBONE
        { .min_connects = 3, .max_connects = 100, .edge_weight = 3 },   // DEV_CLASS_STATIONARY
        { .min_connects = 3, .max_connects = 3, .edge_weight = 6 },             // DEV_CLASS_PORTABLE