$(libisc_la_HEADERS) \
netmgr/netmgr-int.h \
netmgr/netmgr.c \
+ netmgr/socket.c \
netmgr/tcp.c \
netmgr/tcpdns.c \
netmgr/timer.c \
* Platform independent closesocket() version
*/
-isc_result_t
-isc__nm_socket_freebind(uv_os_sock_t fd, sa_family_t sa_family);
-/*%<
- * Set the IP_FREEBIND (or equivalent) socket option on the uv_handle
- */
-
isc_result_t
isc__nm_socket_reuse(uv_os_sock_t fd);
/*%<
isc_error_fatal(__FILE__, __LINE__, "%s failed: %s", #func, \
uv_strerror(ret)); \
}
+
+/*
+ * Bind to the socket, but allow binding to IPv6 tentative addresses reported by
+ * the route socket by setting IP_FREEBIND (or equivalent).
+ */
+int
+isc__nm_udp_freebind(uv_udp_t *handle, const struct sockaddr *addr,
+ unsigned int flags);
+
+int
+isc__nm_tcp_freebind(uv_tcp_t *handle, const struct sockaddr *addr,
+ unsigned int flags);
}
}
-isc_result_t
-isc__nm_socket(int domain, int type, int protocol, uv_os_sock_t *sockp) {
- int sock = socket(domain, type, protocol);
- if (sock < 0) {
- return (isc_errno_toresult(errno));
- }
-
- *sockp = (uv_os_sock_t)sock;
- return (ISC_R_SUCCESS);
-}
-
-void
-isc__nm_closesocket(uv_os_sock_t sock) {
- close(sock);
-}
-
-#define setsockopt_on(socket, level, name) \
- setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))
-
-#define setsockopt_off(socket, level, name) \
- setsockopt(socket, level, name, &(int){ 0 }, sizeof(int))
-
-isc_result_t
-isc__nm_socket_freebind(uv_os_sock_t fd, sa_family_t sa_family) {
- /*
- * Set the IP_FREEBIND (or equivalent option) on the uv_handle.
- */
-#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)
- if (sa_family == AF_INET) {
-#if defined(IP_BINDANY)
- 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 (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(fd);
- UNUSED(sa_family);
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-isc_result_t
-isc__nm_socket_reuse(uv_os_sock_t fd) {
- /*
- * Generally, the SO_REUSEADDR socket option allows reuse of
- * local addresses.
- *
- * On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some
- * additional refinements for programs that use multicast.
- *
- * On Linux, SO_REUSEPORT has different semantics: it _shares_ the port
- * rather than steal it from the current listener, so we don't use it
- * here, but rather in isc__nm_socket_reuse_lb().
- *
- * On Windows, it also allows a socket to forcibly bind to a port in use
- * by another socket.
- */
-
-#if defined(SO_REUSEPORT) && !defined(__linux__)
- if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT) == -1) {
- return (ISC_R_FAILURE);
- }
- return (ISC_R_SUCCESS);
-#elif defined(SO_REUSEADDR)
- if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEADDR) == -1) {
- return (ISC_R_FAILURE);
- }
- return (ISC_R_SUCCESS);
-#else
- UNUSED(fd);
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-isc_result_t
-isc__nm_socket_reuse_lb(uv_os_sock_t fd) {
- /*
- * On FreeBSD 12+, SO_REUSEPORT_LB socket option allows sockets to be
- * bound to an identical socket address. For UDP sockets, the use of
- * this option can provide better distribution of incoming datagrams to
- * multiple processes (or threads) as compared to the traditional
- * technique of having multiple processes compete to receive datagrams
- * on the same socket.
- *
- * On Linux, the same thing is achieved simply with SO_REUSEPORT.
- */
-#if defined(SO_REUSEPORT_LB)
- if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT_LB) == -1) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#elif defined(SO_REUSEPORT) && defined(__linux__)
- if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT) == -1) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#else
- UNUSED(fd);
- return (ISC_R_NOTIMPLEMENTED);
-#endif
-}
-
-isc_result_t
-isc__nm_socket_incoming_cpu(uv_os_sock_t fd) {
-#ifdef SO_INCOMING_CPU
- if (setsockopt_on(fd, SOL_SOCKET, SO_INCOMING_CPU) == -1) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#else
- UNUSED(fd);
-#endif
- return (ISC_R_NOTIMPLEMENTED);
-}
-
-isc_result_t
-isc__nm_socket_disable_pmtud(uv_os_sock_t fd, sa_family_t sa_family) {
- /*
- * Disable the Path MTU Discovery on IP packets
- */
- if (sa_family == AF_INET6) {
-#if defined(IPV6_DONTFRAG)
- if (setsockopt_off(fd, IPPROTO_IPV6, IPV6_DONTFRAG) == -1) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#elif defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
- &(int){ IP_PMTUDISC_OMIT }, sizeof(int)) == -1)
- {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#else
- UNUSED(fd);
-#endif
- } else if (sa_family == AF_INET) {
-#if defined(IP_DONTFRAG)
- if (setsockopt_off(fd, IPPROTO_IP, IP_DONTFRAG) == -1) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
- if (setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER,
- &(int){ IP_PMTUDISC_OMIT }, sizeof(int)) == -1)
- {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#else
- UNUSED(fd);
-#endif
- } else {
- return (ISC_R_FAMILYNOSUPPORT);
- }
-
- return (ISC_R_NOTIMPLEMENTED);
-}
-
-isc_result_t
-isc__nm_socket_v6only(uv_os_sock_t fd, sa_family_t sa_family) {
- /*
- * Enable the IPv6-only option on IPv6 sockets
- */
- if (sa_family == AF_INET6) {
-#if defined(IPV6_V6ONLY)
- if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_V6ONLY) == -1) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#else
- UNUSED(fd);
-#endif
- }
- return (ISC_R_NOTIMPLEMENTED);
-}
-
isc_result_t
isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type) {
int proto, pf, addrlen, fd, r;
#define TIMEOUT_OPTNAME TCP_KEEPINIT
#endif
-isc_result_t
-isc__nm_socket_connectiontimeout(uv_os_sock_t fd, int timeout_ms) {
-#if defined(TIMEOUT_OPTNAME)
- TIMEOUT_TYPE timeout = timeout_ms / TIMEOUT_DIV;
-
- if (timeout == 0) {
- timeout = 1;
- }
-
- if (setsockopt(fd, IPPROTO_TCP, TIMEOUT_OPTNAME, &timeout,
- sizeof(timeout)) == -1)
- {
- return (ISC_R_FAILURE);
- }
-
- return (ISC_R_SUCCESS);
-#else
- UNUSED(fd);
- UNUSED(timeout_ms);
-
- return (ISC_R_SUCCESS);
-#endif
-}
-
-isc_result_t
-isc__nm_socket_tcp_nodelay(uv_os_sock_t fd) {
-#ifdef TCP_NODELAY
- if (setsockopt_on(fd, IPPROTO_TCP, TCP_NODELAY) == -1) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#else
- UNUSED(fd);
- return (ISC_R_SUCCESS);
-#endif
-}
-
-isc_result_t
-isc__nm_socket_tcp_maxseg(uv_os_sock_t fd, int size) {
-#ifdef TCP_MAXSEG
- if (setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (void *)&size,
- sizeof(size))) {
- return (ISC_R_FAILURE);
- } else {
- return (ISC_R_SUCCESS);
- }
-#else
- UNUSED(fd);
- UNUSED(size);
- return (ISC_R_SUCCESS);
-#endif
-}
-
-isc_result_t
-isc__nm_socket_min_mtu(uv_os_sock_t fd, sa_family_t sa_family) {
- if (sa_family != AF_INET6) {
- return (ISC_R_SUCCESS);
- }
-#ifdef IPV6_USE_MIN_MTU
- if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU) == -1) {
- return (ISC_R_FAILURE);
- }
-#elif defined(IPV6_MTU)
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &(int){ 1280 },
- sizeof(int)) == -1) {
- return (ISC_R_FAILURE);
- }
-#else
- UNUSED(fd);
-#endif
-
- return (ISC_R_SUCCESS);
-}
-
void
isc__nm_set_network_buffers(isc_nm_t *nm, uv_handle_t *handle) {
int32_t recv_buffer_size = 0;
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <isc/errno.h>
+
+#include "netmgr-int.h"
+#include "uv-compat.h"
+
+#define setsockopt_on(socket, level, name) \
+ setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))
+
+#define setsockopt_off(socket, level, name) \
+ setsockopt(socket, level, name, &(int){ 0 }, sizeof(int))
+
+static isc_result_t
+socket_freebind(uv_os_sock_t fd, sa_family_t sa_family) {
+ /*
+ * Set the IP_FREEBIND (or equivalent option) on the uv_handle.
+ */
+#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)
+ if (sa_family == AF_INET) {
+#if defined(IP_BINDANY)
+ 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 (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(fd);
+ UNUSED(sa_family);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+int
+isc__nm_udp_freebind(uv_udp_t *handle, const struct sockaddr *addr,
+ unsigned int flags) {
+ int r;
+ uv_os_sock_t fd;
+
+ r = uv_fileno((const uv_handle_t *)handle, (uv_os_fd_t *)&fd);
+ if (r < 0) {
+ return (r);
+ }
+
+ r = uv_udp_bind(handle, addr, flags);
+ if (r == UV_EADDRNOTAVAIL &&
+ socket_freebind(fd, addr->sa_family) == ISC_R_SUCCESS)
+ {
+ /*
+ * Retry binding with IP_FREEBIND (or equivalent option) if the
+ * address is not available. This helps with IPv6 tentative
+ * addresses which are reported by the route socket, although
+ * named is not yet able to properly bind to them.
+ */
+ r = uv_udp_bind(handle, addr, flags);
+ }
+
+ return (r);
+}
+
+static int
+tcp_bind_now(uv_tcp_t *handle, const struct sockaddr *addr,
+ unsigned int flags) {
+ int r;
+ struct sockaddr_storage sname;
+ int snamelen = sizeof(sname);
+
+ r = uv_tcp_bind(handle, addr, flags);
+ if (r < 0) {
+ return (r);
+ }
+
+ /*
+ * uv_tcp_bind() uses a delayed error, initially returning
+ * success even if bind() fails. By calling uv_tcp_getsockname()
+ * here we can find out whether the bind() call was successful.
+ */
+ r = uv_tcp_getsockname(handle, (struct sockaddr *)&sname, &snamelen);
+ if (r < 0) {
+ return (r);
+ }
+
+ return (0);
+}
+
+int
+isc__nm_tcp_freebind(uv_tcp_t *handle, const struct sockaddr *addr,
+ unsigned int flags) {
+ int r;
+ uv_os_sock_t fd;
+
+ r = uv_fileno((const uv_handle_t *)handle, (uv_os_fd_t *)&fd);
+ if (r < 0) {
+ return (r);
+ }
+
+ r = tcp_bind_now(handle, addr, flags);
+ if (r == UV_EADDRNOTAVAIL &&
+ socket_freebind(fd, addr->sa_family) == ISC_R_SUCCESS)
+ {
+ /*
+ * Retry binding with IP_FREEBIND (or equivalent option) if the
+ * address is not available. This helps with IPv6 tentative
+ * addresses which are reported by the route socket, although
+ * named is not yet able to properly bind to them.
+ */
+ r = tcp_bind_now(handle, addr, flags);
+ }
+
+ return (r);
+}
+
+isc_result_t
+isc__nm_socket(int domain, int type, int protocol, uv_os_sock_t *sockp) {
+ int sock = socket(domain, type, protocol);
+ if (sock < 0) {
+ return (isc_errno_toresult(errno));
+ }
+
+ *sockp = (uv_os_sock_t)sock;
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc__nm_closesocket(uv_os_sock_t sock) {
+ close(sock);
+}
+
+isc_result_t
+isc__nm_socket_reuse(uv_os_sock_t fd) {
+ /*
+ * Generally, the SO_REUSEADDR socket option allows reuse of
+ * local addresses.
+ *
+ * On the BSDs, SO_REUSEPORT implies SO_REUSEADDR but with some
+ * additional refinements for programs that use multicast.
+ *
+ * On Linux, SO_REUSEPORT has different semantics: it _shares_ the port
+ * rather than steal it from the current listener, so we don't use it
+ * here, but rather in isc__nm_socket_reuse_lb().
+ *
+ * On Windows, it also allows a socket to forcibly bind to a port in use
+ * by another socket.
+ */
+
+#if defined(SO_REUSEPORT) && !defined(__linux__)
+ if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT) == -1) {
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+#elif defined(SO_REUSEADDR)
+ if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEADDR) == -1) {
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+#else
+ UNUSED(fd);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+isc__nm_socket_reuse_lb(uv_os_sock_t fd) {
+ /*
+ * On FreeBSD 12+, SO_REUSEPORT_LB socket option allows sockets to be
+ * bound to an identical socket address. For UDP sockets, the use of
+ * this option can provide better distribution of incoming datagrams to
+ * multiple processes (or threads) as compared to the traditional
+ * technique of having multiple processes compete to receive datagrams
+ * on the same socket.
+ *
+ * On Linux, the same thing is achieved simply with SO_REUSEPORT.
+ */
+#if defined(SO_REUSEPORT_LB)
+ if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT_LB) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#elif defined(SO_REUSEPORT) && defined(__linux__)
+ if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+isc__nm_socket_incoming_cpu(uv_os_sock_t fd) {
+#ifdef SO_INCOMING_CPU
+ if (setsockopt_on(fd, SOL_SOCKET, SO_INCOMING_CPU) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+#endif
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+isc__nm_socket_disable_pmtud(uv_os_sock_t fd, sa_family_t sa_family) {
+ /*
+ * Disable the Path MTU Discovery on IP packets
+ */
+ if (sa_family == AF_INET6) {
+#if defined(IPV6_DONTFRAG)
+ if (setsockopt_off(fd, IPPROTO_IPV6, IPV6_DONTFRAG) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#elif defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
+ &(int){ IP_PMTUDISC_OMIT }, sizeof(int)) == -1)
+ {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+#endif
+ } else if (sa_family == AF_INET) {
+#if defined(IP_DONTFRAG)
+ if (setsockopt_off(fd, IPPROTO_IP, IP_DONTFRAG) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
+ if (setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER,
+ &(int){ IP_PMTUDISC_OMIT }, sizeof(int)) == -1)
+ {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+#endif
+ } else {
+ return (ISC_R_FAMILYNOSUPPORT);
+ }
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+isc__nm_socket_v6only(uv_os_sock_t fd, sa_family_t sa_family) {
+ /*
+ * Enable the IPv6-only option on IPv6 sockets
+ */
+ if (sa_family == AF_INET6) {
+#if defined(IPV6_V6ONLY)
+ if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_V6ONLY) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+#endif
+ }
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+isc__nm_socket_connectiontimeout(uv_os_sock_t fd, int timeout_ms) {
+#if defined(TIMEOUT_OPTNAME)
+ TIMEOUT_TYPE timeout = timeout_ms / TIMEOUT_DIV;
+
+ if (timeout == 0) {
+ timeout = 1;
+ }
+
+ if (setsockopt(fd, IPPROTO_TCP, TIMEOUT_OPTNAME, &timeout,
+ sizeof(timeout)) == -1)
+ {
+ return (ISC_R_FAILURE);
+ }
+
+ return (ISC_R_SUCCESS);
+#else
+ UNUSED(fd);
+ UNUSED(timeout_ms);
+
+ return (ISC_R_SUCCESS);
+#endif
+}
+
+isc_result_t
+isc__nm_socket_tcp_nodelay(uv_os_sock_t fd) {
+#ifdef TCP_NODELAY
+ if (setsockopt_on(fd, IPPROTO_TCP, TCP_NODELAY) == -1) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+ return (ISC_R_SUCCESS);
+#endif
+}
+
+isc_result_t
+isc__nm_socket_tcp_maxseg(uv_os_sock_t fd, int size) {
+#ifdef TCP_MAXSEG
+ if (setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (void *)&size,
+ sizeof(size))) {
+ return (ISC_R_FAILURE);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+#else
+ UNUSED(fd);
+ UNUSED(size);
+ return (ISC_R_SUCCESS);
+#endif
+}
+
+isc_result_t
+isc__nm_socket_min_mtu(uv_os_sock_t fd, sa_family_t sa_family) {
+ if (sa_family != AF_INET6) {
+ return (ISC_R_SUCCESS);
+ }
+#ifdef IPV6_USE_MIN_MTU
+ if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU) == -1) {
+ return (ISC_R_FAILURE);
+ }
+#elif defined(IPV6_MTU)
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &(int){ 1280 },
+ sizeof(int)) == -1) {
+ return (ISC_R_FAILURE);
+ }
+#else
+ UNUSED(fd);
+#endif
+
+ return (ISC_R_SUCCESS);
+}
}
if (mgr->load_balance_sockets) {
- r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
- &sock->iface.type.sa, flags);
+ r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
+ &sock->iface.type.sa, flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
} else {
if (sock->parent->fd == -1) {
- r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
- &sock->iface.type.sa, flags);
+ r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
+ &sock->iface.type.sa, flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
if (mgr->load_balance_sockets) {
- r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
- &sock->iface.type.sa, flags);
+ r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
+ &sock->iface.type.sa, flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
} else {
if (sock->parent->fd == -1) {
- r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
- &sock->iface.type.sa, flags);
+ r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
+ &sock->iface.type.sa, flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
if (mgr->load_balance_sockets) {
- r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
- &sock->iface.type.sa, flags);
+ r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
+ &sock->iface.type.sa, flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
} else {
if (sock->parent->fd == -1) {
- r = isc_uv_tcp_freebind(&sock->uv_handle.tcp,
- &sock->iface.type.sa, flags);
+ r = isc__nm_tcp_freebind(&sock->uv_handle.tcp,
+ &sock->iface.type.sa, flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
}
if (mgr->load_balance_sockets) {
- r = isc_uv_udp_freebind(&sock->uv_handle.udp,
- &sock->parent->iface.type.sa,
- uv_bind_flags);
+ r = isc__nm_udp_freebind(&sock->uv_handle.udp,
+ &sock->parent->iface.type.sa,
+ uv_bind_flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
} else {
if (sock->parent->fd == -1) {
/* This thread is first, bind the socket */
- r = isc_uv_udp_freebind(&sock->uv_handle.udp,
- &sock->parent->iface.type.sa,
- uv_bind_flags);
+ r = isc__nm_udp_freebind(&sock->uv_handle.udp,
+ &sock->parent->iface.type.sa,
+ uv_bind_flags);
if (r < 0) {
isc__nm_incstats(sock, STATID_BINDFAIL);
goto done;
return (0);
}
#endif /* UV_VERSION_HEX < UV_VERSION(1, 32, 0) */
-
-int
-isc_uv_udp_freebind(uv_udp_t *handle, const struct sockaddr *addr,
- unsigned int flags) {
- int r;
- uv_os_sock_t fd;
-
- r = uv_fileno((const uv_handle_t *)handle, (uv_os_fd_t *)&fd);
- if (r < 0) {
- return (r);
- }
-
- r = uv_udp_bind(handle, addr, flags);
- if (r == UV_EADDRNOTAVAIL &&
- isc__nm_socket_freebind(fd, addr->sa_family) == ISC_R_SUCCESS)
- {
- /*
- * Retry binding with IP_FREEBIND (or equivalent option) if the
- * address is not available. This helps with IPv6 tentative
- * addresses which are reported by the route socket, although
- * named is not yet able to properly bind to them.
- */
- r = uv_udp_bind(handle, addr, flags);
- }
-
- return (r);
-}
-
-static int
-isc__uv_tcp_bind_now(uv_tcp_t *handle, const struct sockaddr *addr,
- unsigned int flags) {
- int r;
- struct sockaddr_storage sname;
- int snamelen = sizeof(sname);
-
- r = uv_tcp_bind(handle, addr, flags);
- if (r < 0) {
- return (r);
- }
-
- /*
- * uv_tcp_bind() uses a delayed error, initially returning
- * success even if bind() fails. By calling uv_tcp_getsockname()
- * here we can find out whether the bind() call was successful.
- */
- r = uv_tcp_getsockname(handle, (struct sockaddr *)&sname, &snamelen);
- if (r < 0) {
- return (r);
- }
-
- return (0);
-}
-
-int
-isc_uv_tcp_freebind(uv_tcp_t *handle, const struct sockaddr *addr,
- unsigned int flags) {
- int r;
- uv_os_sock_t fd;
-
- r = uv_fileno((const uv_handle_t *)handle, (uv_os_fd_t *)&fd);
- if (r < 0) {
- return (r);
- }
-
- r = isc__uv_tcp_bind_now(handle, addr, flags);
- if (r == UV_EADDRNOTAVAIL &&
- isc__nm_socket_freebind(fd, addr->sa_family) == ISC_R_SUCCESS)
- {
- /*
- * Retry binding with IP_FREEBIND (or equivalent option) if the
- * address is not available. This helps with IPv6 tentative
- * addresses which are reported by the route socket, although
- * named is not yet able to properly bind to them.
- */
- r = isc__uv_tcp_bind_now(handle, addr, flags);
- }
-
- return (r);
-}
#define uv_os_setenv(name, value) setenv(name, value, 0)
#endif /* UV_VERSION_HEX < UV_VERSION(1, 12, 0) */
-
-int
-isc_uv_udp_freebind(uv_udp_t *handle, const struct sockaddr *addr,
- unsigned int flags);
-
-int
-isc_uv_tcp_freebind(uv_tcp_t *handle, const struct sockaddr *addr,
- unsigned int flags);
#include "../netmgr/http.c"
#include "../netmgr/netmgr-int.h"
+#include "../netmgr/socket.c"
#include "../netmgr/uv-compat.c"
#include "../netmgr/uv-compat.h"
#include "../netmgr_p.h"
#define KEEP_BEFORE
#include "../netmgr/netmgr-int.h"
+#include "../netmgr/socket.c"
#include "../netmgr/udp.c"
#include "../netmgr/uv-compat.c"
#include "../netmgr/uv-compat.h"