From af60e5f5164b28495c4a441f38c86e8f6b184a38 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Wed, 30 Dec 2020 14:50:56 +0100 Subject: [PATCH] Use the canonical address during UDP probes. 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 | 21 +++++++++++++++++++-- src/netutl.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/netutl.h | 1 + 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/net_packet.c b/src/net_packet.c index b32c78f7..ce1eb626 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -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)) { diff --git a/src/netutl.c b/src/netutl.c index 5406bbb8..9988b123 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -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]; diff --git a/src/netutl.h b/src/netutl.h index bce0aaee..69346bca 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -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__)); -- 2.39.5