]> git.meshlink.io Git - meshlink/commitdiff
Allow nodes to learn their own reflexive UDP address.
authorGuus Sliepen <guus@meshlink.io>
Thu, 31 Oct 2019 21:26:25 +0000 (22:26 +0100)
committerGuus Sliepen <guus@meshlink.io>
Thu, 31 Oct 2019 21:26:25 +0000 (22:26 +0100)
When a node gets a succesful UDP probe reply, it informs the peer of the
UDP address and port that it has. The peer can then use this information to
inform other nodes it wants to communicate with.

Currently, this is only done to close the time window where two nodes have
established an SPTPS session via a third node, while the third node hasn't
learned of the two nodes' UDP addresses, in which case it was too late for
the third node to assist with hole punching.

src/net_packet.c
src/protocol_key.c

index 0510b54be8def584f8b9f33d78329b4d852baaa7..a2709553fb9893f555d548cc57a8c62372730289 100644 (file)
@@ -185,7 +185,14 @@ static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet
                   is possible using the address and socket that the reply
                   packet used. */
 
-               n->status.udp_confirmed = true;
+               if(!n->status.udp_confirmed) {
+                       char *address, *port;
+                       sockaddr2str(&n->address, &address, &port);
+                       send_request(mesh, n->nexthop->connection, NULL, "%d %s %s . -1 -1 -1 0 %s %s", ANS_KEY, n->name, n->name, address, port);
+                       free(address);
+                       free(port);
+                       n->status.udp_confirmed = true;
+               }
 
                /* If we haven't established the PMTU yet, restart the discovery process. */
 
index f912c0fb44431c6f33ee625fda372eb5fa3187e0..641e2b969434c8941a5ca752b9dca69822175dea 100644 (file)
@@ -324,6 +324,12 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                        return true;
                }
 
+               if(from == to) {
+                       logger(mesh, MESHLINK_WARNING, "Got %s from %s from %s to %s",
+                              "ANS_KEY", c->name, from_name, to_name);
+                       return true;
+               }
+
                /* Append the known UDP address of the from node, if we have a confirmed one */
                if(!*address && from->status.udp_confirmed && from->address.sa.sa_family != AF_UNSPEC) {
                        char *address, *port;
@@ -338,6 +344,37 @@ bool ans_key_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                return send_request(mesh, to->nexthop->connection, NULL, "%s", request);
        }
 
+       /* Is this an ANS_KEY informing us of our own reflexive UDP address? */
+
+       if(from == mesh->self) {
+               if(*key == '.' && *address && *port) {
+                       logger(mesh, MESHLINK_DEBUG, "Learned our own reflexive UDP address from %s: %s port %s", c->name, address, port);
+
+                       /* Inform all other nodes we want to communicate with and which are reachable via this connection */
+                       for splay_each(node_t, n, mesh->nodes) {
+                               if(n->nexthop == c->node) {
+                                       continue;
+                               }
+
+                               if(n->status.udp_confirmed) {
+                                       continue;
+                               }
+
+                               if(!n->status.waitingforkey && !n->status.validkey) {
+                                       continue;
+                               }
+
+                               logger(mesh, MESHLINK_DEBUG, "Forwarding our own reflexive UDP address to %s", n->name);
+                               send_request(mesh, c, NULL, "%d %s %s . -1 -1 -1 0 %s %s", ANS_KEY, mesh->self->name, n->name, address, port);
+                       }
+               } else {
+                       logger(mesh, MESHLINK_WARNING, "Got %s from %s from %s to %s",
+                              "ANS_KEY", c->name, from_name, to_name);
+               }
+
+               return true;
+       }
+
        /* Process SPTPS data if present */
 
        if(*key != '.') {