]> git.meshlink.io Git - meshlink/blobdiff - src/protocol_auth.c
Never automatically try to bind to ports >= 32768.
[meshlink] / src / protocol_auth.c
index 5632c5a216d23c044e07d820da8661fc4b501f8e..0a107e4c2820f19caa88dea3c6e5f41cab3f99c9 100644 (file)
 extern bool node_write_devclass(meshlink_handle_t *mesh, node_t *n);
 
 bool send_id(meshlink_handle_t *mesh, connection_t *c) {
-       return send_request(mesh, c, NULL, "%d %s %d.%d %s", ID, mesh->self->name, PROT_MAJOR, PROT_MINOR, mesh->appname);
+       return send_request(mesh, c, NULL, "%d %s %d.%d %s %u", ID, mesh->self->name, PROT_MAJOR, PROT_MINOR, mesh->appname, 0);
 }
 
 static bool commit_invitation(meshlink_handle_t *mesh, connection_t *c, const void *data) {
+       // Check if the node is known
+       node_t *n = lookup_node(mesh, c->name);
+
+       if(n) {
+               if(n->status.blacklisted) {
+                       logger(mesh, MESHLINK_ERROR, "Invitee %s is blacklisted", c->name);
+               } else {
+                       logger(mesh, MESHLINK_ERROR, "Invitee %s already known", c->name);
+               }
+
+               return false;
+       }
+
        // Create a new node
-       node_t *n = new_node();
+       n = new_node();
        n->name = xstrdup(c->name);
        n->devclass = DEV_CLASS_UNKNOWN;
        n->ecdsa = ecdsa_set_public_key(data);
@@ -58,7 +71,7 @@ static bool commit_invitation(meshlink_handle_t *mesh, connection_t *c, const vo
        // Remember its current address
        node_add_recent_address(mesh, n, &c->address);
 
-       if(!node_write_config(mesh, n) || !config_sync(mesh, "current")) {
+       if(!node_write_config(mesh, n, true) || !config_sync(mesh, "current")) {
                logger(mesh, MESHLINK_ERROR, "Error writing configuration file for invited node %s!\n", c->name);
                free_node(n);
                return false;
@@ -146,6 +159,9 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
        connection_t *c = handle;
        meshlink_handle_t *mesh = c->mesh;
 
+       // Extend the time for the invitation exchange upon receiving a valid message
+       c->last_ping_time = mesh->loop.now.tv_sec;
+
        if(type == SPTPS_HANDSHAKE) {
                // The peer should send its cookie first.
                return true;
@@ -172,7 +188,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
 
        char name[MAX_STRING_SIZE];
 
-       if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) {
+       if(sscanf(request, "%*d " MAX_STRING " %d.%d %*s %u", name, &c->protocol_major, &c->protocol_minor, &c->flags) < 2) {
                logger(mesh, MESHLINK_ERROR, "Got bad %s from %s", "ID", c->name);
                return false;
        }
@@ -207,6 +223,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
 
                c->protocol_minor = 2;
                c->allow_request = 1;
+               c->last_ping_time = mesh->loop.now.tv_sec;
 
                return sptps_start(&c->sptps, c, false, false, mesh->invitation_key, c->ecdsa, meshlink_invitation_label, sizeof(meshlink_invitation_label), send_meta_sptps, receive_invitation_sptps);
        }
@@ -250,11 +267,6 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                return false;
        }
 
-       if(n->status.blacklisted) {
-               logger(mesh, MESHLINK_WARNING, "Peer %s is blacklisted", c->name);
-               return false;
-       }
-
        if(!node_read_public_key(mesh, n)) {
                logger(mesh, MESHLINK_ERROR, "No key known for peer %s", c->name);
 
@@ -275,6 +287,7 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
        }
 
        c->allow_request = ACK;
+       c->last_ping_time = mesh->loop.now.tv_sec;
        char label[sizeof(meshlink_tcp_label) + strlen(mesh->self->name) + strlen(c->name) + 2];
 
        if(c->outgoing) {
@@ -283,14 +296,25 @@ bool id_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                snprintf(label, sizeof(label), "%s %s %s", meshlink_tcp_label, c->name, mesh->self->name);
        }
 
-       char buf1[1024], buf2[1024];
-       bin2hex((uint8_t *)mesh->private_key + 64, buf1, 32);
-       bin2hex((uint8_t *)n->ecdsa + 64, buf2, 32);
-       logger(mesh, MESHLINK_DEBUG, "Connection to %s mykey %s hiskey %s", c->name, buf1, buf2);
+       if(mesh->log_level <= MESHLINK_DEBUG) {
+               char buf1[1024], buf2[1024];
+               bin2hex((uint8_t *)mesh->private_key + 64, buf1, 32);
+               bin2hex((uint8_t *)n->ecdsa + 64, buf2, 32);
+               logger(mesh, MESHLINK_DEBUG, "Connection to %s mykey %s hiskey %s", c->name, buf1, buf2);
+       }
+
        return sptps_start(&c->sptps, c, c->outgoing, false, mesh->private_key, n->ecdsa, label, sizeof(label) - 1, send_meta_sptps, receive_meta_sptps);
 }
 
 bool send_ack(meshlink_handle_t *mesh, connection_t *c) {
+       node_t *n = lookup_node(mesh, c->name);
+
+       if(n && n->status.blacklisted) {
+               logger(mesh, MESHLINK_WARNING, "Peer %s is blacklisted", c->name);
+               return send_error(mesh, c, BLACKLISTED, "blacklisted");
+       }
+
+       c->last_ping_time = mesh->loop.now.tv_sec;
        return send_request(mesh, c, NULL, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, OPTION_PMTU_DISCOVERY | (PROT_MINOR << 24));
 }
 
@@ -298,7 +322,7 @@ static void send_everything(meshlink_handle_t *mesh, connection_t *c) {
        /* Send all known subnets and edges */
 
        for splay_each(node_t, n, mesh->nodes) {
-               for splay_each(edge_t, e, n->edge_tree) {
+               for inner_splay_each(edge_t, e, n->edge_tree) {
                        send_add_edge(mesh, c, e, 0);
                }
        }
@@ -334,7 +358,7 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
        } else {
                if(n->connection) {
                        /* Oh dear, we already have a connection to this node. */
-                       logger(mesh, MESHLINK_DEBUG, "Established a second connection with %s, closing old connection", n->connection->name);
+                       logger(mesh, MESHLINK_INFO, "Established a second connection with %s, closing old connection", n->connection->name);
 
                        if(n->connection->outgoing) {
                                if(c->outgoing) {
@@ -356,22 +380,50 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
 
        n->devclass = devclass;
        n->status.dirty = true;
+       n->status.tiny = c->flags & PROTOCOL_TINY;
 
        n->last_successfull_connection = mesh->loop.now.tv_sec;
 
        n->connection = c;
+       n->nexthop = n;
        c->node = n;
 
        /* Activate this connection */
 
        c->allow_request = ALL;
+       c->last_key_renewal = mesh->loop.now.tv_sec;
        c->status.active = true;
 
        logger(mesh, MESHLINK_INFO, "Connection with %s activated", c->name);
 
+       if(mesh->meta_status_cb) {
+               mesh->meta_status_cb(mesh, (meshlink_node_t *)n, true);
+       }
+
+       /*  Terminate any connections to this node that are not activated yet */
+
+       for list_each(connection_t, other, mesh->connections) {
+               if(!other->status.active && !strcmp(other->name, c->name)) {
+                       if(other->outgoing) {
+                               if(c->outgoing) {
+                                       logger(mesh, MESHLINK_WARNING, "Two outgoing connections to the same node!");
+                               } else {
+                                       c->outgoing = other->outgoing;
+                               }
+
+                               other->outgoing = NULL;
+                       }
+
+                       logger(mesh, MESHLINK_DEBUG, "Terminating pending second connection with %s", n->name);
+                       terminate_connection(mesh, other, false);
+               }
+       }
+
        /* Send him everything we know */
 
-       send_everything(mesh, c);
+       if(!(c->flags & PROTOCOL_TINY)) {
+               send_everything(mesh, c);
+       }
 
        /* Create an edge_t for this connection */
 
@@ -384,6 +436,7 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
        c->edge->weight = mesh->dev_class_traits[devclass].edge_weight;
        c->edge->connection = c;
 
+       node_add_recent_address(mesh, n, &c->address);
        edge_add(mesh, c->edge);
 
        /* Notify everyone of the new edge */
@@ -394,5 +447,11 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
 
        graph(mesh);
 
+       /* Request a session key to jump start UDP traffic */
+
+       if(c->status.initiator) {
+               send_req_key(mesh, n);
+       }
+
        return true;
 }