diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index d6c4032dc6..72c76a5afd 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -834,7 +834,7 @@ isc__nm_decstats(isc_nm_t *mgr, isc_statscounter_t counterid); */ isc_result_t -isc__nm_socket_freebind(const uv_handle_t *handle); +isc__nm_socket_freebind(uv_os_fd_t fd, sa_family_t sa_family); /*%< * Set the IP_FREEBIND (or equivalent) socket option on the uv_handle */ diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index e39c882408..02ad0b2c54 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1584,50 +1584,44 @@ isc__nm_decstats(isc_nm_t *mgr, isc_statscounter_t counterid) { setsockopt(socket, level, name, &(int){ 1 }, sizeof(int)) isc_result_t -isc__nm_socket_freebind(const uv_handle_t *handle) { +isc__nm_socket_freebind(uv_os_fd_t fd, sa_family_t sa_family) { /* * Set the IP_FREEBIND (or equivalent option) on the uv_handle. */ - isc_result_t result = ISC_R_SUCCESS; - uv_os_fd_t fd; - if (uv_fileno(handle, &fd) != 0) { - return (ISC_R_FAILURE); - } #ifdef IP_FREEBIND + UNUSED(sa_family); if (setsockopt_on(fd, IPPROTO_IP, IP_FREEBIND) == -1) { return (ISC_R_FAILURE); } + return (ISC_R_SUCCESS); #elif defined(IP_BINDANY) || defined(IPV6_BINDANY) - struct sockaddr_in sockfd; - - if (getsockname(fd, (struct sockaddr *)&sockfd, - &(socklen_t){ sizeof(sockfd) }) == -1) - { - return (ISC_R_FAILURE); - } + if (sa_family == AF_INET) { #if defined(IP_BINDANY) - if (sockfd.sin_family == AF_INET) { if (setsockopt_on(fd, IPPROTO_IP, IP_BINDANY) == -1) { return (ISC_R_FAILURE); } - } + return (ISC_R_SUCCESS); #endif + } else if (sa_family == AF_INET6) { #if defined(IPV6_BINDANY) - if (sockfd.sin_family == AF_INET6) { if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_BINDANY) == -1) { return (ISC_R_FAILURE); } - } + return (ISC_R_SUCCESS); #endif + } + return (ISC_R_NOTIMPLEMENTED); #elif defined(SO_BINDANY) + UNUSED(sa_family); if (setsockopt_on(fd, SOL_SOCKET, SO_BINDANY) == -1) { return (ISC_R_FAILURE); } + return (ISC_R_SUCCESS); #else - UNUSED(handle); - result = ISC_R_NOTIMPLEMENTED; + UNUSED(fd); + UNUSED(sa_family); + return (ISC_R_NOTIMPLEMENTED); #endif - return (result); } isc_result_t diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index fbfc5aebce..2540083702 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -318,6 +318,8 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { isc_nmsocket_t *sock = ievent->sock; struct sockaddr_storage sname; int r, flags = 0, snamelen = sizeof(sname); + sa_family_t sa_family; + uv_os_fd_t fd; REQUIRE(isc__nm_in_netthread()); REQUIRE(sock->type == isc_nm_tcplistener); @@ -334,14 +336,16 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) { isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPEN]); - if (sock->iface->addr.type.sa.sa_family == AF_INET6) { + sa_family = sock->iface->addr.type.sa.sa_family; + if (sa_family == AF_INET6) { flags = UV_TCP_IPV6ONLY; } r = uv_tcp_bind(&sock->uv_handle.tcp, &sock->iface->addr.type.sa, flags); if (r == UV_EADDRNOTAVAIL && - isc__nm_socket_freebind(&sock->uv_handle.handle) == ISC_R_SUCCESS) + uv_fileno(&sock->uv_handle.handle, &fd) == 0 && + isc__nm_socket_freebind(fd, sa_family) == ISC_R_SUCCESS) { /* * Retry binding with IP_FREEBIND (or equivalent option) if the diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 83ab7b54c9..e531857e1c 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -137,6 +137,7 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) { isc_nmsocket_t *sock = ievent->sock; int r, uv_bind_flags = 0; int uv_init_flags = 0; + sa_family_t sa_family; REQUIRE(sock->type == isc_nm_udpsocket); REQUIRE(sock->iface != NULL); @@ -158,14 +159,15 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) { isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]); } - if (sock->iface->addr.type.sa.sa_family == AF_INET6) { + sa_family = sock->iface->addr.type.sa.sa_family; + if (sa_family == AF_INET6) { uv_bind_flags |= UV_UDP_IPV6ONLY; } r = uv_udp_bind(&sock->uv_handle.udp, &sock->parent->iface->addr.type.sa, uv_bind_flags); if (r == UV_EADDRNOTAVAIL && - isc__nm_socket_freebind(&sock->uv_handle.handle) == ISC_R_SUCCESS) + isc__nm_socket_freebind(sock->fd, sa_family) == ISC_R_SUCCESS) { /* * Retry binding with IP_FREEBIND (or equivalent option) if the