From 968dff4d576ca102525c81beddb36a623890424b Mon Sep 17 00:00:00 2001 From: Stephen Sinclair Date: Tue, 29 Aug 2017 14:32:24 -0300 Subject: [PATCH] Resolve hostname using getnameinfo for ipv6 support. Iterates on interfaces, possibly searching for a pre-selected interface, and resolves the hostname associated with non-localhost addresses. Fixes #56, fix compilation with --enable-ipv6. --- src/server.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- src/testlo.c | 7 ++++++ 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/src/server.c b/src/server.c index cf20495..4aff673 100644 --- a/src/server.c +++ b/src/server.c @@ -55,6 +55,10 @@ #endif #include #include +#include +#ifdef HAVE_GETIFADDRS +#include +#endif #endif #if defined(WIN32) || defined(_MSC_VER) @@ -298,20 +302,72 @@ void lo_server_resolve_hostname(lo_server s) /* Set hostname to empty string */ hostname[0] = '\0'; -#ifdef ENABLE_IPV6 +#if defined(ENABLE_IPV6) && defined(HAVE_GETIFADDRS) /* Try it the IPV6 friendly way first */ - for (it = ai; it; it = it->ai_next) { - if (getnameinfo(it->ai_addr, it->ai_addrlen, hostname, - sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0) { + do { + struct ifaddrs *ifa, *ifa_list; + if (getifaddrs(&ifa_list)) break; + ifa = ifa_list; + + while (ifa) { + if (!ifa->ifa_addr) { + ifa = ifa->ifa_next; + continue; + } + + if (s->addr_if.iface) { + if (s->addr_if.size == sizeof(struct in_addr) + && (ifa->ifa_addr->sa_family == AF_INET)) + { + struct sockaddr_in *sin = (struct sockaddr_in*)ifa->ifa_addr; + if (memcmp(&sin->sin_addr, &s->addr_if.a.addr, sizeof(struct in_addr))!=0 + || (s->addr_if.iface && ifa->ifa_name + && strcmp(s->addr_if.iface, ifa->ifa_name)!=0)) + { + ifa = ifa->ifa_next; + continue; + } + } + else if (s->addr_if.size == sizeof(struct in6_addr) + && (ifa->ifa_addr->sa_family == AF_INET6)) + { + struct sockaddr_in6 *sin = (struct sockaddr_in6*)ifa->ifa_addr; + if (memcmp(&sin->sin6_addr, &s->addr_if.a.addr6, + sizeof(struct in6_addr))!=0 + || (s->addr_if.iface && ifa->ifa_name + && strcmp(s->addr_if.iface, ifa->ifa_name)!=0)) + { + ifa = ifa->ifa_next; + continue; + } + } + } + + if ((ifa->ifa_addr->sa_family == AF_INET + && (!s->addr_if.iface || s->addr_if.size == sizeof(struct in_addr)) + && (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), hostname, + sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0)) + || (ifa->ifa_addr->sa_family == AF_INET6 + && (!s->addr_if.iface || s->addr_if.size == sizeof(struct in6_addr)) + && (getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), hostname, + sizeof(hostname), NULL, 0, NI_NAMEREQD) == 0))) + { + /* check to make sure getnameinfo() didn't just set the hostname to "::". + Needed on Darwin. */ + if (hostname[0] == ':') + hostname[0] = '\0'; + else if (strcmp(hostname, "localhost")==0) + hostname[0] = '\0'; + else + break; + } + ifa = ifa->ifa_next; } - } - /* check to make sure getnameinfo() didn't just set the hostname to "::". - Needed on Darwin. */ - if (hostname[0] == ':') { - hostname[0] = '\0'; + freeifaddrs(ifa_list); } + while (0); #endif /* Fallback to the oldschool (i.e. more reliable) way */ diff --git a/src/testlo.c b/src/testlo.c index c128d10..c69570c 100644 --- a/src/testlo.c +++ b/src/testlo.c @@ -704,6 +704,13 @@ void test_multicast(lo_server_thread st) DOING("test_multicast"); +#ifdef ENABLE_IPV6 + // Print a warning but we let it fail, prefer to actually fix IPv6 + // support rather than just skip the test! + printf("WARNING: Compiled with --enable-ipv6, multicast not supported;" + "failure expected.\n"); +#endif + /* test multicast server and sender */ /* message is sent from st otherwise reply doesn't work */ ms = lo_server_new_multicast("224.0.1.1", "15432", error); -- 2.14.1