]> git.meshlink.io Git - meshlink/blobdiff - src/meshlink.c
Avoid ports that are in use by not all address families.
[meshlink] / src / meshlink.c
index eb9142cc743d842c7f8967e0b9a4408aa170113e..c6b14b8f043c1b0bdb4c38b6db8aa687651659b7 100644 (file)
@@ -537,26 +537,52 @@ static bool try_bind(int port) {
                return false;
        }
 
-       //while(ai) {
+       bool success = false;
+
        for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
-               int fd = socket(aip->ai_family, SOCK_STREAM, IPPROTO_TCP);
+               /* Try to bind to TCP. */
 
-               if(!fd) {
-                       freeaddrinfo(ai);
-                       return false;
+               int tcp_fd = socket(aip->ai_family, SOCK_STREAM, IPPROTO_TCP);
+
+               if(tcp_fd == -1) {
+                       continue;
                }
 
-               int result = bind(fd, aip->ai_addr, aip->ai_addrlen);
-               closesocket(fd);
+               int result = bind(tcp_fd, aip->ai_addr, aip->ai_addrlen);
+               closesocket(tcp_fd);
 
                if(result) {
-                       freeaddrinfo(ai);
-                       return false;
+                       if(errno == EADDRINUSE) {
+                               /* If this port is in use for any address family, avoid it. */
+                               success = false;
+                               break;
+                       } else {
+                               continue;
+                       }
                }
+
+               /* If TCP worked, then we require that UDP works as well. */
+
+               int udp_fd = socket(aip->ai_family, SOCK_DGRAM, IPPROTO_UDP);
+
+               if(udp_fd == -1) {
+                       success = false;
+                       break;
+               }
+
+               result = bind(udp_fd, aip->ai_addr, aip->ai_addrlen);
+               closesocket(udp_fd);
+
+               if(result) {
+                       success = false;
+                       break;
+               }
+
+               success = true;
        }
 
        freeaddrinfo(ai);
-       return true;
+       return success;
 }
 
 static int check_port(meshlink_handle_t *mesh) {
@@ -743,6 +769,10 @@ static bool finalize_join(join_state_t *state, const void *buf, uint16_t len) {
                return false;
        }
 
+       if(!mesh->inviter_commits_first) {
+               devtool_set_inviter_commits_first(false);
+       }
+
        sptps_send_record(&state->sptps, 1, ecdsa_get_public_key(mesh->private_key), 32);
 
        logger(mesh, MESHLINK_DEBUG, "Configuration stored in: %s\n", mesh->confbase);
@@ -775,21 +805,44 @@ static bool invitation_receive(void *handle, uint8_t type, const void *msg, uint
        join_state_t *state = handle;
        meshlink_handle_t *mesh = state->mesh;
 
-       switch(type) {
-       case SPTPS_HANDSHAKE:
-               return sptps_send_record(&state->sptps, 0, state->cookie, 18);
+       if(mesh->inviter_commits_first) {
+               switch(type) {
+               case SPTPS_HANDSHAKE:
+                       return sptps_send_record(&state->sptps, 2, state->cookie, 18 + 32);
 
-       case 0:
-               return finalize_join(state, msg, len);
+               case 1:
+                       break;
 
-       case 1:
-               logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
-               shutdown(state->sock, SHUT_RDWR);
-               state->success = true;
-               break;
+               case 0:
+                       if(!finalize_join(state, msg, len)) {
+                               return false;
+                       }
 
-       default:
-               return false;
+                       logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
+                       shutdown(state->sock, SHUT_RDWR);
+                       state->success = true;
+                       break;
+
+               default:
+                       return false;
+               }
+       } else {
+               switch(type) {
+               case SPTPS_HANDSHAKE:
+                       return sptps_send_record(&state->sptps, 0, state->cookie, 18);
+
+               case 0:
+                       return finalize_join(state, msg, len);
+
+               case 1:
+                       logger(mesh, MESHLINK_DEBUG, "Invitation successfully accepted.\n");
+                       shutdown(state->sock, SHUT_RDWR);
+                       state->success = true;
+                       break;
+
+               default:
+                       return false;
+               }
        }
 
        return true;
@@ -1531,9 +1584,6 @@ static void *meshlink_main_loop(void *arg) {
 }
 
 bool meshlink_start(meshlink_handle_t *mesh) {
-       assert(mesh->self);
-       assert(mesh->private_key);
-
        if(!mesh) {
                meshlink_errno = MESHLINK_EINVAL;
                return false;
@@ -1543,6 +1593,8 @@ bool meshlink_start(meshlink_handle_t *mesh) {
 
        pthread_mutex_lock(&mesh->mutex);
 
+       assert(mesh->self);
+       assert(mesh->private_key);
        assert(mesh->self->ecdsa);
        assert(!memcmp((uint8_t *)mesh->self->ecdsa + 64, (uint8_t *)mesh->private_key + 64, 32));
 
@@ -2252,7 +2304,7 @@ bool meshlink_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *
 }
 
 bool meshlink_verify(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len, const void *signature, size_t siglen) {
-       if(!mesh || !data || !len || !signature) {
+       if(!mesh || !source || !data || !len || !signature) {
                meshlink_errno = MESHLINK_EINVAL;
                return false;
        }
@@ -2647,6 +2699,10 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
                goto invalid;
        }
 
+       if(mesh->inviter_commits_first) {
+               memcpy(state.cookie + 18, ecdsa_get_public_key(mesh->private_key), 32);
+       }
+
        // Generate a throw-away key for the invitation.
        key = ecdsa_generate();