From: Evan Hunt Date: Fri, 10 Jan 2020 22:25:30 +0000 (-0800) Subject: netmgr fixes: X-Git-Tag: v9.15.8~14^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e38004457c504a40b9662644b569fdebde16e220;p=thirdparty%2Fbind9.git netmgr fixes: - use UV_{TC,UD}P_IPV6ONLY for IPv6 sockets, keeping the pre-netmgr behaviour. - add a new listening_error bool flag which is set if the child listener fails to start listening. This fixes a bug where named would hang if, e.g., we failed to bind to a TCP socket. --- diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 68f3f399b85..a451012e16e 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -390,6 +390,7 @@ struct isc_nmsocket { */ atomic_bool closed; atomic_bool listening; + atomic_bool listen_error; isc_refcount_t references; /*% diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 46c612ab832..bab631533f8 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -180,7 +180,8 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, (isc__netievent_t *) ievent); LOCK(&nsock->lock); - while (!atomic_load(&nsock->listening)) { + while (!atomic_load(&nsock->listening) && + !atomic_load(&nsock->listen_error)) { WAIT(&nsock->cond, &nsock->lock); } UNLOCK(&nsock->lock); @@ -213,7 +214,7 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { (isc__netievent_tcplisten_t *) ev0; isc_nmsocket_t *sock = ievent->sock; struct sockaddr_storage sname; - int r, snamelen = sizeof(sname); + int r, flags = 0, snamelen = sizeof(sname); REQUIRE(isc__nm_in_netthread()); REQUIRE(sock->type == isc_nm_tcplistener); @@ -241,13 +242,19 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { /* It was never opened */ atomic_store(&sock->closed, true); sock->result = isc__nm_uverr2result(r); + atomic_store(&sock->listen_error, true); goto done; } + if (sock->iface->addr.type.sa.sa_family == AF_INET6) { + flags = UV_TCP_IPV6ONLY; + } - r = uv_tcp_bind(&sock->uv_handle.tcp, &sock->iface->addr.type.sa, 0); + r = uv_tcp_bind(&sock->uv_handle.tcp, + &sock->iface->addr.type.sa, flags); if (r != 0) { uv_close(&sock->uv_handle.handle, tcp_close_cb); sock->result = isc__nm_uverr2result(r); + atomic_store(&sock->listen_error, true); goto done; } @@ -257,10 +264,12 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { * initially returning success even if bind() fails, and this * could cause a deadlock later if we didn't check first.) */ - r = uv_tcp_getsockname(&sock->uv_handle.tcp, &sname, &snamelen); + r = uv_tcp_getsockname(&sock->uv_handle.tcp, + (struct sockaddr*) &sname, &snamelen); if (r != 0) { uv_close(&sock->uv_handle.handle, tcp_close_cb); sock->result = isc__nm_uverr2result(r); + atomic_store(&sock->listen_error, true); goto done; } diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index abd950a2790..2731ce24970 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -130,8 +130,12 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) { (isc_nmsocket_t **)&sock->uv_handle.udp.data); uv_udp_open(&sock->uv_handle.udp, sock->fd); + int flags = 0; + if (sock->iface->addr.type.sa.sa_family == AF_INET6) { + flags = UV_UDP_IPV6ONLY; + } uv_udp_bind(&sock->uv_handle.udp, - &sock->parent->iface->addr.type.sa, 0); + &sock->parent->iface->addr.type.sa, flags); uv_recv_buffer_size(&sock->uv_handle.handle, &(int){16 * 1024 * 1024}); uv_send_buffer_size(&sock->uv_handle.handle,