mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
netmgr: retry binding with IP_FREEBIND when EADDRNOTAVAIL is returned.
When a new IPv6 interface/address appears it's first in a tentative state - in which we cannot bind to it, yet it's already being reported by the route socket. Because of that BIND9 is unable to listen on any newly detected IPv6 addresses. Fix it by setting IP_FREEBIND option (or equivalent option on other OSes) and then retrying bind() call.
This commit is contained in:
committed by
Ondřej Surý
parent
2ac7748d2b
commit
a0f7d28967
@@ -1519,3 +1519,54 @@ isc__nm_decstats(isc_nm_t *mgr, isc_statscounter_t counterid) {
|
||||
isc_stats_decrement(mgr->stats, counterid);
|
||||
}
|
||||
}
|
||||
|
||||
#define setsockopt_on(socket, level, name) \
|
||||
setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))
|
||||
|
||||
isc_result_t
|
||||
isc__nm_socket_freebind(const uv_handle_t *handle) {
|
||||
/*
|
||||
* 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
|
||||
if (setsockopt_on(fd, IPPROTO_IP, IP_FREEBIND) == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#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 defined(IP_BINDANY)
|
||||
if (sockfd.sin_family == AF_INET) {
|
||||
if (setsockopt_on(fd, IPPROTO_IP, IP_BINDANY) == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(IPV6_BINDANY)
|
||||
if (sockfd.sin_family == AF_INET6) {
|
||||
if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_BINDANY) == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#elif defined(SO_BINDANY)
|
||||
if (setsockopt_on(fd, SOL_SOCKET, SO_BINDANY) == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#else
|
||||
UNUSED(handle);
|
||||
UNUSED(fd);
|
||||
result = ISC_R_NOTIMPLEMENTED;
|
||||
#endif
|
||||
return (result);
|
||||
}
|
||||
|
Reference in New Issue
Block a user