diff options
author | Glenn Strauss <gstrauss@gluelogic.com> | 2017-07-15 18:06:26 -0400 |
---|---|---|
committer | Glenn Strauss <gstrauss@gluelogic.com> | 2017-07-23 19:02:30 -0400 |
commit | 1836309209e1bc4268df02b7aaf06d2e89329581 (patch) | |
tree | 18fda592bcec14585bbad00631d80dc37c089406 | |
parent | 0beb8b89d800f0569d6581f469baa64459188955 (diff) | |
download | lighttpd-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.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)); |