From: Witold Kręcicki Date: Thu, 23 Aug 2018 07:42:30 +0000 (+0200) Subject: Add runtime detection of SO_REUSEPORT, use it if available (instead of dup) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b5abac4e9aecb7a5201058157d832b6a82899c2;p=thirdparty%2Fbind9.git Add runtime detection of SO_REUSEPORT, use it if available (instead of dup) --- diff --git a/bin/tests/system/rpzrecurse/setup.sh b/bin/tests/system/rpzrecurse/setup.sh index 36786a72dee..7deefd8427f 100644 --- a/bin/tests/system/rpzrecurse/setup.sh +++ b/bin/tests/system/rpzrecurse/setup.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -x # # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # diff --git a/bin/tests/system/rpzrecurse/tests.sh b/bin/tests/system/rpzrecurse/tests.sh index 38dead46e23..ed1f3143f6c 100644 --- a/bin/tests/system/rpzrecurse/tests.sh +++ b/bin/tests/system/rpzrecurse/tests.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -x # # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 6202a778ec8..670be5a7194 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -1678,7 +1678,7 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, result = isc_socket_open(sock); if (result != ISC_R_SUCCESS) return (result); - } else if (dup_socket != NULL) { + } else if (dup_socket != NULL && !isc_socket_hasreuseport()) { result = isc_socket_dup(dup_socket, &sock); if (result != ISC_R_SUCCESS) return (result); diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index 588a355d59b..450ee3e16f5 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -1037,6 +1037,12 @@ isc_socketmgr_maxudp(isc_socketmgr_t *mgr, int maxudp); * Test interface. Drop UDP packet > 'maxudp'. */ +bool +isc_socket_hasreuseport(void); +/*%< + * Return true if there is SO_REUSEPORT support + */ + #ifdef HAVE_LIBXML2 int isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer); diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index aa2ba8c5f2b..8c831334586 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -4802,13 +4802,21 @@ isc_socket_bind(isc_socket_t *sock0, const isc_sockaddr_t *sockaddr, goto bind_socket; #endif if ((options & ISC_SOCKET_REUSEADDRESS) != 0 && - isc_sockaddr_getport(sockaddr) != (in_port_t)0 && - setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, + isc_sockaddr_getport(sockaddr) != (in_port_t)0) { + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) < 0) { - UNEXPECTED_ERROR(__FILE__, __LINE__, + UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d) %s", sock->fd, isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_FAILED, "failed")); + } + if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, + sizeof(on)) < 0) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "setsockopt(%d) %s", sock->fd, + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + } /* Press on... */ } #ifdef AF_UNIX @@ -5667,6 +5675,38 @@ isc_socket_getfd(isc_socket_t *socket0) { return ((short) sock->fd); } +static isc_once_t hasreuseport_once = ISC_ONCE_INIT; +static bool hasreuseport = false; + +static void +init_hasreuseport() { +#ifdef SO_REUSEPORT + int sock, yes = 1; + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + close(sock); + return; + } else if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, + sizeof(yes)) < 0) { + close(sock); + return; + } else if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (void *)&yes, + sizeof(yes)) < 0) { + close(sock); + return; + } + hasreuseport = true; +#endif +} + +bool +isc_socket_hasreuseport() { + RUNTIME_CHECK(isc_once_do(&hasreuseport_once, init_hasreuseport) + == ISC_R_SUCCESS); + return (hasreuseport); +} + + #if defined(HAVE_LIBXML2) || defined(HAVE_JSON) static const char * _socktype(isc_sockettype_t type) diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index e15bdacd2bc..6c74f62c899 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -78,6 +78,7 @@ isc_socket_getpeername isc_socket_getsockname isc_socket_gettag isc_socket_gettype +isc_socket_hasreuseport isc_socket_ipv6only isc_socket_listen isc_socket_open diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index 8e568268a85..a64f11d9ebe 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -3941,6 +3941,11 @@ isc_socket_socketevent(isc_mem_t *mctx, void *sender, return (allocate_socketevent(mctx, sender, eventtype, action, arg)); } +bool +isc_socket_hasreuseport() { + return (false); +} + #ifdef HAVE_LIBXML2 static const char *