summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gw_backend.c22
-rw-r--r--src/inet_ntop_cache.c41
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));