X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fmeshlink.c;h=59776da25a36382b481995a68a2b9c9aa4c40adf;hb=b549eb9642b4b8b441b0e23cd3e0b4d7f39907ae;hp=b7379fc232a25ca0ba56a4c903eaef5548378518;hpb=86a858b3f9aa659c0d8c411c61f0ac2eeb3a2882;p=meshlink-tiny diff --git a/src/meshlink.c b/src/meshlink.c index b7379fc..59776da 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -149,285 +149,6 @@ static int socket_in_netns(int domain, int type, int protocol, int netns) { } -// Find out what local address a socket would use if we connect to the given address. -// We do this using connect() on a UDP socket, so the kernel has to resolve the address -// of both endpoints, but this will actually not send any UDP packet. -static bool getlocaladdr(const char *destaddr, sockaddr_t *sa, socklen_t *salen, int netns) { - struct addrinfo *rai = NULL; - const struct addrinfo hint = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_DGRAM, - .ai_protocol = IPPROTO_UDP, - .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV, - }; - - if(getaddrinfo(destaddr, "80", &hint, &rai) || !rai) { - return false; - } - - int sock = socket_in_netns(rai->ai_family, rai->ai_socktype, rai->ai_protocol, netns); - - if(sock == -1) { - freeaddrinfo(rai); - return false; - } - - if(connect(sock, rai->ai_addr, rai->ai_addrlen) && !sockwouldblock(errno)) { - closesocket(sock); - freeaddrinfo(rai); - return false; - } - - freeaddrinfo(rai); - - if(getsockname(sock, &sa->sa, salen)) { - closesocket(sock); - return false; - } - - closesocket(sock); - return true; -} - -static bool getlocaladdrname(const char *destaddr, char *host, socklen_t hostlen, int netns) { - sockaddr_t sa; - socklen_t salen = sizeof(sa); - - if(!getlocaladdr(destaddr, &sa, &salen, netns)) { - return false; - } - - if(getnameinfo(&sa.sa, salen, host, hostlen, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) { - return false; - } - - return true; -} - -char *meshlink_get_external_address(meshlink_handle_t *mesh) { - return meshlink_get_external_address_for_family(mesh, AF_UNSPEC); -} - -char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int family) { - logger(mesh, MESHLINK_DEBUG, "meshlink_get_external_address_for_family(%d)", family); - const char *url = mesh->external_address_url; - - if(!url) { - url = "http://meshlink.io/host.cgi"; - } - - /* Find the hostname part between the slashes */ - if(strncmp(url, "http://", 7)) { - abort(); - meshlink_errno = MESHLINK_EINTERNAL; - return NULL; - } - - const char *begin = url + 7; - - const char *end = strchr(begin, '/'); - - if(!end) { - end = begin + strlen(begin); - } - - /* Make a copy */ - char host[end - begin + 1]; - strncpy(host, begin, end - begin); - host[end - begin] = 0; - - char *port = strchr(host, ':'); - - if(port) { - *port++ = 0; - } - - logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n"); - struct addrinfo *ai = str2addrinfo(host, port ? port : "80", SOCK_STREAM); - char line[256]; - char *hostname = NULL; - - for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) { - if(family != AF_UNSPEC && aip->ai_family != family) { - continue; - } - - int s = socket_in_netns(aip->ai_family, aip->ai_socktype, aip->ai_protocol, mesh->netns); - -#ifdef SO_NOSIGPIPE - int nosigpipe = 1; - setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe)); -#endif - - if(s >= 0) { - set_timeout(s, 5000); - - if(connect(s, aip->ai_addr, aip->ai_addrlen)) { - closesocket(s); - s = -1; - } - } - - if(s >= 0) { - send(s, "GET ", 4, 0); - send(s, url, strlen(url), 0); - send(s, " HTTP/1.0\r\n\r\n", 13, 0); - int len = recv(s, line, sizeof(line) - 1, MSG_WAITALL); - - if(len > 0) { - line[len] = 0; - - if(line[len - 1] == '\n') { - line[--len] = 0; - } - - char *p = strrchr(line, '\n'); - - if(p && p[1]) { - hostname = xstrdup(p + 1); - } - } - - closesocket(s); - - if(hostname) { - break; - } - } - } - - if(ai) { - freeaddrinfo(ai); - } - - // Check that the hostname is reasonable - if(hostname && !is_valid_hostname(hostname)) { - free(hostname); - hostname = NULL; - } - - if(!hostname) { - meshlink_errno = MESHLINK_ERESOLV; - } - - return hostname; -} - -static bool is_localaddr(sockaddr_t *sa) { - switch(sa->sa.sa_family) { - case AF_INET: - return *(uint8_t *)(&sa->in.sin_addr.s_addr) == 127; - - case AF_INET6: { - uint16_t first = sa->in6.sin6_addr.s6_addr[0] << 8 | sa->in6.sin6_addr.s6_addr[1]; - return first == 0 || (first & 0xffc0) == 0xfe80; - } - - default: - return false; - } -} - -#ifdef HAVE_GETIFADDRS -struct getifaddrs_in_netns_params { - struct ifaddrs **ifa; - int netns; -}; - -#ifdef HAVE_SETNS -static void *getifaddrs_in_netns_thread(void *arg) { - struct getifaddrs_in_netns_params *params = arg; - - if(setns(params->netns, CLONE_NEWNET) == -1) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - if(getifaddrs(params->ifa) != 0) { - *params->ifa = NULL; - } - - return NULL; -} -#endif // HAVE_SETNS - -static int getifaddrs_in_netns(struct ifaddrs **ifa, int netns) { - if(netns == -1) { - return getifaddrs(ifa); - } - -#ifdef HAVE_SETNS - struct getifaddrs_in_netns_params params = {ifa, netns}; - pthread_t thr; - - if(pthread_create(&thr, NULL, getifaddrs_in_netns_thread, ¶ms) == 0) { - if(pthread_join(thr, NULL) != 0) { - abort(); - } - } - - return *params.ifa ? 0 : -1; -#else - return -1; -#endif // HAVE_SETNS - -} -#endif - -char *meshlink_get_local_address_for_family(meshlink_handle_t *mesh, int family) { - logger(mesh, MESHLINK_DEBUG, "meshlink_get_local_address_for_family(%d)", family); - - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return NULL; - } - - // Determine address of the local interface used for outgoing connections. - char localaddr[NI_MAXHOST]; - bool success = false; - - if(family == AF_INET) { - success = getlocaladdrname("93.184.216.34", localaddr, sizeof(localaddr), mesh->netns); - } else if(family == AF_INET6) { - success = getlocaladdrname("2606:2800:220:1:248:1893:25c8:1946", localaddr, sizeof(localaddr), mesh->netns); - } - -#ifdef HAVE_GETIFADDRS - - if(!success) { - struct ifaddrs *ifa = NULL; - getifaddrs_in_netns(&ifa, mesh->netns); - - for(struct ifaddrs *ifap = ifa; ifap; ifap = ifap->ifa_next) { - sockaddr_t *sa = (sockaddr_t *)ifap->ifa_addr; - - if(!sa || sa->sa.sa_family != family) { - continue; - } - - if(is_localaddr(sa)) { - continue; - } - - if(!getnameinfo(&sa->sa, SALEN(sa->sa), localaddr, sizeof(localaddr), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) { - success = true; - break; - } - } - - freeifaddrs(ifa); - } - -#endif - - if(!success) { - meshlink_errno = MESHLINK_ENETWORK; - return NULL; - } - - return xstrdup(localaddr); -} - static bool write_main_config_files(meshlink_handle_t *mesh) { if(!mesh->confbase) { return true; @@ -807,29 +528,6 @@ static struct timespec idle(event_loop_t *loop, void *data) { return tmin; } -// Get our local address(es) by simulating connecting to an Internet host. -static void add_local_addresses(meshlink_handle_t *mesh) { - sockaddr_t sa; - sa.storage.ss_family = AF_UNKNOWN; - socklen_t salen = sizeof(sa); - - // IPv4 example.org - - if(getlocaladdr("93.184.216.34", &sa, &salen, mesh->netns)) { - sa.in.sin_port = ntohs(atoi(mesh->myport)); - node_add_recent_address(mesh, mesh->self, &sa); - } - - // IPv6 example.org - - salen = sizeof(sa); - - if(getlocaladdr("2606:2800:220:1:248:1893:25c8:1946", &sa, &salen, mesh->netns)) { - sa.in6.sin6_port = ntohs(atoi(mesh->myport)); - node_add_recent_address(mesh, mesh->self, &sa); - } -} - static bool meshlink_setup(meshlink_handle_t *mesh) { if(!config_destroy(mesh->confbase, "new")) { logger(mesh, MESHLINK_ERROR, "Could not delete configuration in %s/new: %s\n", mesh->confbase, strerror(errno)); @@ -1405,8 +1103,6 @@ meshlink_handle_t *meshlink_open_ex(const meshlink_open_params_t *params) { return NULL; } - add_local_addresses(mesh); - if(!node_write_config(mesh, mesh->self, new_configuration)) { logger(NULL, MESHLINK_ERROR, "Cannot update configuration\n"); return NULL; @@ -2380,32 +2076,6 @@ bool meshlink_clear_canonical_address(meshlink_handle_t *mesh, meshlink_node_t * return config_sync(mesh, "current"); } -bool meshlink_add_address(meshlink_handle_t *mesh, const char *address) { - logger(mesh, MESHLINK_DEBUG, "meshlink_add_address(%s)", address ? address : "(null)"); - - return meshlink_set_canonical_address(mesh, (meshlink_node_t *)mesh->self, address, NULL); -} - -bool meshlink_add_external_address(meshlink_handle_t *mesh) { - logger(mesh, MESHLINK_DEBUG, "meshlink_add_external_address()"); - - if(!mesh) { - meshlink_errno = MESHLINK_EINVAL; - return false; - } - - char *address = meshlink_get_external_address(mesh); - - if(!address) { - return false; - } - - bool rval = meshlink_set_canonical_address(mesh, (meshlink_node_t *)mesh->self, address, NULL); - free(address); - - return rval; -} - bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) { logger(mesh, MESHLINK_DEBUG, "meshlink_join(%s)", invitation ? invitation : "(null)");