]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Move socket related functions to netmgr/socket.c
authorOndřej Surý <ondrej@isc.org>
Wed, 27 Apr 2022 15:41:47 +0000 (17:41 +0200)
committerOndřej Surý <ondrej@isc.org>
Tue, 3 May 2022 07:52:49 +0000 (09:52 +0200)
Move the netmgr socket related functions from netmgr/netmgr.c and
netmgr/uv-compat.c to netmgr/socket.c, so they are all present all in
the same place.  Adjust the names of couple interal functions
accordingly.

12 files changed:
lib/isc/Makefile.am
lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/netmgr.c
lib/isc/netmgr/socket.c [new file with mode: 0644]
lib/isc/netmgr/tcp.c
lib/isc/netmgr/tcpdns.c
lib/isc/netmgr/tlsdns.c
lib/isc/netmgr/udp.c
lib/isc/netmgr/uv-compat.c
lib/isc/netmgr/uv-compat.h
lib/isc/tests/doh_test.c
lib/isc/tests/netmgr_test.c

index c0bb69fa4ab3d33c33cc1c99a4192656146409a4..7ac556adaabbe7ff513dbbdabe2197cab2eb66e0 100644 (file)
@@ -103,6 +103,7 @@ libisc_la_SOURCES =         \
        $(libisc_la_HEADERS)    \
        netmgr/netmgr-int.h     \
        netmgr/netmgr.c         \
+       netmgr/socket.c         \
        netmgr/tcp.c            \
        netmgr/tcpdns.c         \
        netmgr/timer.c          \
index 10c56514af5e703a8e72046405e9e94662015d8c..0594faa5f6091975d9e1eaabbafcce1fe110c5c8 100644 (file)
@@ -1875,12 +1875,6 @@ isc__nm_closesocket(uv_os_sock_t sock);
  * 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);
 /*%<
@@ -2160,3 +2154,15 @@ isc__nmsocket_writetimeout_cb(void *data, isc_result_t eresult);
                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);
index f7444630c869100e6fe5b900092ea482fc3f2ee5..0b250fe1dc8074de50496bd0fdf83efe6c6a74e1 100644 (file)
@@ -2978,213 +2978,6 @@ isc__nm_decstats(isc_nmsocket_t *sock, isc__nm_statid_t id) {
        }
 }
 
-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;
@@ -3242,81 +3035,6 @@ isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type) {
 #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;
diff --git a/lib/isc/netmgr/socket.c b/lib/isc/netmgr/socket.c
new file mode 100644 (file)
index 0000000..291ac99
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * 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);
+}
index e7eb77feb565823d066f7415debc39dd185aed4e..1ef80d4e2ec8c7f526729b7311a7886e06a4fac6 100644 (file)
@@ -550,16 +550,16 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
        }
 
        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;
index 73753742eaf8e7634c2cccbe233ecf0e9dc4cd59..0d928069abe040a0680191210df876fa59b9fb23 100644 (file)
@@ -516,16 +516,16 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
        }
 
        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;
index 68fbca67fe242520775f304417089f9cc533138f..3529c356160ad1f028839f877b88904252864b0c 100644 (file)
@@ -603,16 +603,16 @@ isc__nm_async_tlsdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
        }
 
        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;
index 29a603a0dd2c8b8c8273dacc5788591e673dfb5c..df4312fba25d71f4e87ccaf0e6b53197905053f0 100644 (file)
@@ -463,9 +463,9 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
        }
 
        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;
@@ -473,9 +473,9 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
        } 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;
index b7c0f7b0e29250297a8d52f56f0e093e9ba10232..39ec0cfed2f882fa604d6a8c769b8a8abca60c9e 100644 (file)
@@ -59,82 +59,3 @@ uv_tcp_close_reset(uv_tcp_t *handle, uv_close_cb close_cb) {
        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);
-}
index 3a103874e4ab2ab9554eba87014a74043ec78073..91e5d2c107c395e9b39fe459aeac30d8b046bd28 100644 (file)
@@ -116,11 +116,3 @@ uv_os_getenv(const char *name, char *buffer, size_t *size) {
 
 #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);
index 2d7907d5006dd6c1d311462ec049e4b44dacb7dd..a2625a0a97a9e87b948aa2f7076c00b1307f8df2 100644 (file)
@@ -43,6 +43,7 @@
 
 #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"
index 62353dd0b7401b89f299c8552e3c5b4b1677d66d..c9c6a7504d61f3d21c8fefcc0dda087dcf2129e4 100644 (file)
@@ -35,6 +35,7 @@
 #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"