From f9504dae81fde52bb1c1669fdd0c9e3aba818a75 Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Tue, 2 Apr 2013 15:41:54 +0200 Subject: [PATCH] Allow IPV6 addresses PAZ-841 for clients (databases). --- src/getaddrinfo.c | 95 ++++++++++++++++++++++------------------------------- 1 file changed, 40 insertions(+), 55 deletions(-) diff --git a/src/getaddrinfo.c b/src/getaddrinfo.c index 13f7c24..a5f6a3a 100644 --- a/src/getaddrinfo.c +++ b/src/getaddrinfo.c @@ -54,11 +54,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* Only use a threaded resolver on Unix that offers getaddrinfo. gethostbyname is NOT reentrant. */ -#if HAVE_GETADDRINFO #ifndef WIN32 #define USE_THREADED_RESOLVER 1 #endif -#endif struct work { char *hostport; /* hostport to be resolved in separate thread */ @@ -71,69 +69,56 @@ static int log_level = YLOG_LOG; void perform_getaddrinfo(struct work *w) { - int res = 0; - char *port; -#if HAVE_GETADDRINFO - struct addrinfo *addrinfo, hints; -#else - struct hostent *hp; -#endif - char *hostport = xstrdup(w->hostport); - if ((port = strchr(hostport, ':'))) - *(port++) = '\0'; - else - { - port = "210"; - } + struct addrinfo hints, *res; + char host[512], *cp; + const char *port = 0; + int error; -#if HAVE_GETADDRINFO hints.ai_flags = 0; - hints.ai_family = PF_INET; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = 0; - hints.ai_canonname = 0; - hints.ai_next = 0; - // This is not robust code. It assumes that getaddrinfo always - // returns AF_INET address. - if ((res = getaddrinfo(hostport, port, &hints, &addrinfo))) + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + strncpy(host, w->hostport, sizeof(host)-1); + host[sizeof(host)-1] = 0; + if ((cp = strrchr(host, ':'))) { - yaz_log(YLOG_WARN, "Failed to resolve %s %s", - w->hostport, gai_strerror(res)); + *cp = '\0'; + port = cp + 1; } - else - { - char ipport[128]; - unsigned char addrbuf[4]; - assert(addrinfo->ai_family == PF_INET); - memcpy(addrbuf, - &((struct sockaddr_in*)addrinfo->ai_addr)->sin_addr.s_addr, 4); - sprintf(ipport, "%u.%u.%u.%u:%s", - addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port); - freeaddrinfo(addrinfo); - w->ipport = xstrdup(ipport); - yaz_log(log_level, "Resolved %s -> %s", hostport, ipport); - } -#else - hp = gethostbyname(hostport); - if (!hp) + error = getaddrinfo(host, port ? port : "210", &hints, &res); + if (error) { - yaz_log(YLOG_WARN|YLOG_ERRNO, "Failed to resolve %s", hostport); + yaz_log(YLOG_WARN, "Failed to resolve %s: %s", + w->hostport, gai_strerror(error)); } else { - char ipport[128]; - unsigned char addrbuf[4]; - - memcpy(addrbuf, *hp->h_addr_list, 4 * sizeof(unsigned char)); - sprintf(ipport, "%u.%u.%u.%u:%s", - addrbuf[0], addrbuf[1], addrbuf[2], addrbuf[3], port); - w->ipport = xstrdup(ipport); - yaz_log(log_level, "Resolved %s -> %s", hostport, ipport); + if (getnameinfo((struct sockaddr *) res->ai_addr, res->ai_addrlen, + host, sizeof(host)-1, + 0, 0, + NI_NUMERICHOST) == 0) + { + w->ipport = xmalloc(strlen(host) + (port ? strlen(port) : 0) + 2); + strcpy(w->ipport, host); + if (port) + { + strcat(w->ipport, ":"); + strcat(w->ipport, port); + } + yaz_log(log_level, "Resolved %s -> %s", w->hostport, w->ipport); + } + else + { + yaz_log(YLOG_LOG|YLOG_ERRNO, "getnameinfo failed for %s", + w->hostport); + } + freeaddrinfo(res); } -#endif - xfree(hostport); } static void work_handler(void *vp) -- 1.7.10.4