Commit bd024eee authored by Witold Krecicki's avatar Witold Krecicki
Browse files

Add runtime detection of SO_REUSEPORT, use it instead of dup() if available.

parent 89b18172
......@@ -1677,7 +1677,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);
......
......@@ -1010,6 +1010,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);
......
......@@ -4584,13 +4584,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
......@@ -5449,6 +5457,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)
......
......@@ -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
......
......@@ -3691,6 +3691,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 *
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment