From 91169c529883e08d7a0245b709483a22a83245ad Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 5 Jun 2020 18:09:38 +0200 Subject: [PATCH] Fix meshlink_join() failing on Android. The adns_blocking_request() function did not pass a hint to getaddrinfo(). With glibc, the resulting struct addrinfo sets socktype and protocol to SOCK_STREAM and IPPROTO_TCP, and the call to connect() copied these values. However, bionic doesn't set the socktype and protocol to those values if no hint was specified. --- src/adns.c | 11 +++++++++-- src/adns.h | 2 +- src/meshlink.c | 8 ++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/adns.c b/src/adns.c index a0431014..01989ac5 100644 --- a/src/adns.c +++ b/src/adns.c @@ -138,6 +138,7 @@ struct adns_blocking_info { char *host; char *serv; struct addrinfo *ai; + int socktype; bool done; }; @@ -147,7 +148,12 @@ static void *adns_blocking_handler(void *data) { logger(info->mesh, MESHLINK_DEBUG, "Resolving %s port %s", info->host, info->serv); devtool_adns_resolve_probe(); - if(getaddrinfo(info->host, info->serv, NULL, &info->ai)) { + struct addrinfo hint = { + .ai_family = AF_UNSPEC, + .ai_socktype = info->socktype, + }; + + if(getaddrinfo(info->host, info->serv, &hint, &info->ai)) { info->ai = NULL; } @@ -171,12 +177,13 @@ static void *adns_blocking_handler(void *data) { return NULL; } -struct addrinfo *adns_blocking_request(meshlink_handle_t *mesh, char *host, char *serv, int timeout) { +struct addrinfo *adns_blocking_request(meshlink_handle_t *mesh, char *host, char *serv, int socktype, int timeout) { struct adns_blocking_info *info = xzalloc(sizeof(*info)); info->mesh = mesh; info->host = host; info->serv = serv; + info->socktype = socktype; struct timespec deadline; clock_gettime(CLOCK_REALTIME, &deadline); diff --git a/src/adns.h b/src/adns.h index 7f9aa908..ff3166d7 100644 --- a/src/adns.h +++ b/src/adns.h @@ -27,6 +27,6 @@ typedef void (*adns_cb_t)(meshlink_handle_t *mesh, char *host, char *serv, void void init_adns(meshlink_handle_t *mesh); void exit_adns(meshlink_handle_t *mesh); void adns_queue(meshlink_handle_t *mesh, char *host, char *serv, adns_cb_t cb, void *data, int timeout); -struct addrinfo *adns_blocking_request(meshlink_handle_t *mesh, char *host, char *serv, int timeout); +struct addrinfo *adns_blocking_request(meshlink_handle_t *mesh, char *host, char *serv, int socktype, int timeout); #endif diff --git a/src/meshlink.c b/src/meshlink.c index 22f5220d..9aca0677 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -257,7 +257,7 @@ char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int fami } logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n"); - struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(host), xstrdup(port ? port : "80"), 5); + struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(host), xstrdup(port ? port : "80"), SOCK_STREAM, 5); char line[256]; char *hostname = NULL; @@ -501,7 +501,7 @@ static char *get_my_hostname(meshlink_handle_t *mesh, uint32_t flags) { } // Convert what we have to a sockaddr - struct addrinfo *ai_in = adns_blocking_request(mesh, xstrdup(hostname[i]), xstrdup(port[i]), 5); + struct addrinfo *ai_in = adns_blocking_request(mesh, xstrdup(hostname[i]), xstrdup(port[i]), SOCK_STREAM, 5); if(!ai_in) { continue; @@ -2887,11 +2887,11 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { } // Connect to the meshlink daemon mentioned in the URL. - struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(address), xstrdup(port), 5); + struct addrinfo *ai = adns_blocking_request(mesh, xstrdup(address), xstrdup(port), SOCK_STREAM, 5); if(ai) { for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - state.sock = socket_in_netns(aip->ai_family, aip->ai_socktype, aip->ai_protocol, mesh->netns); + state.sock = socket_in_netns(aip->ai_family, SOCK_STREAM, IPPROTO_TCP, mesh->netns); if(state.sock == -1) { logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno)); -- 2.39.2