summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2017-07-15 18:06:26 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2017-07-23 19:02:30 -0400
commit1836309209e1bc4268df02b7aaf06d2e89329581 (patch)
tree18fda592bcec14585bbad00631d80dc37c089406
parent0beb8b89d800f0569d6581f469baa64459188955 (diff)
downloadlighttpd-git-1836309209e1bc4268df02b7aaf06d2e89329581.tar.gz
[core] resolve DNS at startup for socket backends
resolve DNS at startup and use the first IP address returned by resolver Note: use of IP addresses is recommended instead of using DNS names. If DNS names are used, but DNS is slow or unavailable, then lighttpd will either appear to hang at startup or will fail to start up.
-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));