diff options
-rw-r--r-- | src/gw_backend.c | 22 | ||||
-rw-r--r-- | src/inet_ntop_cache.c | 41 |
2 files changed, 53 insertions, 10 deletions
diff --git a/src/gw_backend.c b/src/gw_backend.c index 440bac0b..c74841e7 100644 --- a/src/gw_backend.c +++ b/src/gw_backend.c @@ -369,20 +369,22 @@ static int gw_proc_sockaddr_init(server *srv, gw_host *host, gw_proc *proc) { } buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("unix:")); buffer_append_string_buffer(proc->connection_name, proc->unixsocket); - } else { - if (1 != sock_addr_from_buffer_hints_numeric(srv, &addr, &addrlen, - host->host, host->family, - proc->port)) { + } + else { + /*(note: name resolution here is *blocking* if IP string not supplied)*/ + if (1 != sock_addr_from_str_hints(srv, &addr, &addrlen, + host->host->ptr, 0, proc->port)) { errno = EINVAL; return -1; } - buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("tcp:")); - if (!buffer_string_is_empty(host->host)) { - buffer_append_string_buffer(proc->connection_name, host->host); - } else { - buffer_append_string_len(proc->connection_name, - CONST_STR_LEN("localhost")); + else { + /* overwrite host->host buffer with IP addr string so that + * any further use of gw_host does not block on DNS lookup */ + sock_addr_inet_ntop_copy_buffer(host->host, &addr); + host->family = addr.plain.sa_family; } + buffer_copy_string_len(proc->connection_name, CONST_STR_LEN("tcp:")); + buffer_append_string_buffer(proc->connection_name, host->host); buffer_append_string_len(proc->connection_name, CONST_STR_LEN(":")); buffer_append_int(proc->connection_name, proc->port); } diff --git a/src/inet_ntop_cache.c b/src/inet_ntop_cache.c index 14e783ac..53665e8b 100644 --- a/src/inet_ntop_cache.c +++ b/src/inet_ntop_cache.c @@ -154,6 +154,47 @@ int sock_addr_from_str_hints(server *srv, sock_addr *addr, socklen_t *len, const { /*(note: name resolution here is *blocking*)*/ switch(family) { + case AF_UNSPEC: + if (0 == strcmp(str, "localhost")) { + /*(special-case "localhost" to IPv4 127.0.0.1)*/ + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->ipv4.sin_family = AF_INET; + addr->ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + return 1; + } + #ifdef HAVE_IPV6 + else { + struct addrinfo hints, *res; + int r; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (0 != (r = getaddrinfo(str, NULL, &hints, &res))) { + log_error_write(srv, __FILE__, __LINE__, + "sssss", "getaddrinfo failed: ", + gai_strerror(r), "'", str, "'"); + return 0; + } + + memcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + if (AF_INET6 == addr->plain.sa_family) { + addr->ipv6.sin6_port = htons(port); + *len = sizeof(struct sockaddr_in6); + } + else { /* AF_INET */ + addr->ipv4.sin_port = htons(port); + *len = sizeof(struct sockaddr_in); + } + return 1; + } + #else + /* fall through */ + #endif #ifdef HAVE_IPV6 case AF_INET6: memset(addr, 0, sizeof(struct sockaddr_in6)); |