]> git.meshlink.io Git - meshlink/commitdiff
Use the canonical address during UDP probes.
authorGuus Sliepen <guus@meshlink.io>
Wed, 30 Dec 2020 13:50:56 +0000 (14:50 +0100)
committerGuus Sliepen <guus@meshlink.io>
Wed, 30 Dec 2020 13:50:56 +0000 (14:50 +0100)
It is possible that a node has a canonical address, but due to NAT or other
reasons, the meta-connections with that node use other addresses. If UDP is
only possible to the canonical address, then we need to include that during
the initial UDP probing phase.

src/net_packet.c
src/netutl.c
src/netutl.h

index b32c78f7d467456166e9551ca211242a651361f7..ce1eb62680bd1c25fcb2038dc50892069ab21cce 100644 (file)
@@ -305,7 +305,7 @@ static void send_sptps_packet(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *
        return;
 }
 
-static void choose_udp_address(meshlink_handle_t *mesh, const node_t *n, const sockaddr_t **sa, int *sock) {
+static void choose_udp_address(meshlink_handle_t *mesh, const node_t *n, const sockaddr_t **sa, int *sock, sockaddr_t *sa_buf) {
        /* Latest guess */
        *sa = &n->address;
        *sock = n->sock;
@@ -330,6 +330,22 @@ static void choose_udp_address(meshlink_handle_t *mesh, const node_t *n, const s
                goto check_socket;
        }
 
+       /* Else, if we have a canonical address, try this once every batch */
+       if(mesh->udp_choice == 1 && n->canonical_address) {
+               char *host = xstrdup(n->canonical_address);
+               char *port = strchr(host, ' ');
+
+               if(port) {
+                       *port++ = 0;
+                       *sa_buf = str2sockaddr_random(mesh, host, port);
+                       *sa = sa_buf;
+                       free(host);
+                       goto check_socket;
+               }
+
+               free(host);
+       }
+
        /* Otherwise, address are found in edges to this node.
           So we pick a random edge and a random socket. */
 
@@ -422,13 +438,14 @@ bool send_sptps_data(void *handle, uint8_t type, const void *data, size_t len) {
 
        /* Otherwise, send the packet via UDP */
 
+       sockaddr_t sa_buf;
        const sockaddr_t *sa;
        int sock;
 
        if(to->status.broadcast) {
                choose_broadcast_address(mesh, to, &sa, &sock);
        } else {
-               choose_udp_address(mesh, to, &sa, &sock);
+               choose_udp_address(mesh, to, &sa, &sock, &sa_buf);
        }
 
        if(sendto(mesh->listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
index 5406bbb85e983f6fcfe1a48c0666c722a098e3e6..9988b123728aff79fe08ac8d7a4d16db6aef4f2f 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "system.h"
 
+#include "meshlink_internal.h"
 #include "net.h"
 #include "netutl.h"
 #include "logger.h"
@@ -77,6 +78,45 @@ sockaddr_t str2sockaddr(const char *address, const char *port) {
        return result;
 }
 
+sockaddr_t str2sockaddr_random(struct meshlink_handle *mesh, const char *address, const char *port) {
+       struct addrinfo *ai;
+       sockaddr_t result;
+       int err;
+
+       memset(&result, 0, sizeof(result));
+
+       struct addrinfo hint = {
+               .ai_family = AF_UNSPEC,
+               .ai_flags = NI_NUMERICHOST | NI_NUMERICSERV,
+               .ai_socktype = SOCK_STREAM,
+       };
+
+       err = getaddrinfo(address, port, &hint, &ai);
+
+       if(err || !ai) {
+               logger(NULL, MESHLINK_DEBUG, "Unknown type address %s port %s", address, port);
+               result.sa.sa_family = AF_UNKNOWN;
+               result.unknown.address = xstrdup(address);
+               result.unknown.port = xstrdup(port);
+               return result;
+       }
+
+       int count = 0;
+
+       for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
+               count++;
+       }
+
+       struct addrinfo *aip = ai;
+
+       for(count = prng(mesh, count); count--; aip = aip->ai_next);
+
+       memcpy(&result, aip->ai_addr, aip->ai_addrlen);
+       freeaddrinfo(ai);
+
+       return result;
+}
+
 void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
        char address[NI_MAXHOST];
        char port[NI_MAXSERV];
index bce0aaee039369d6b8e9f95a210ec5abcc408595..69346bca542e2819d5d77d9b1520c9e07e89a01d 100644 (file)
@@ -25,6 +25,7 @@
 
 struct addrinfo *str2addrinfo(const char *, const char *, int) __attribute__((__malloc__));
 sockaddr_t str2sockaddr(const char *, const char *);
+sockaddr_t str2sockaddr_random(struct meshlink_handle *mesh, const char *, const char *);
 void sockaddr2str(const sockaddr_t *, char **, char **);
 char *sockaddr2hostname(const sockaddr_t *) __attribute__((__malloc__));
 int sockaddrcmp(const sockaddr_t *, const sockaddr_t *) __attribute__((__warn_unused_result__));