From 370bf84857d5674a092f46fa5932a0c92ad5bbf5 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Wed, 24 Nov 2021 17:25:18 +0100 Subject: [PATCH] ldap: add socket timeout During the discovery phase realmd tries to open LDAP connections to multiple DC addresses returned by DNS. When cleaning up we have to call ldap_destroy() to release the resources allocated for the LDAP context. ldap_destroy() tries to send a LDAP unbind request independent of the connection state. If the related address is block by a firewall or a not properly routed IPv6 address there might be no reply on the TCP level and the request might be stuck for quite some tome in the kernel. To avoid the unexpected long delays will block realmd this patch lowers the timeout considerably to 5s. As multiple other timeouts this value is currently hardcoded. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1817869 --- service/realm-ldap.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/service/realm-ldap.c b/service/realm-ldap.c index bdfb96c..f7b6d13 100644 --- a/service/realm-ldap.c +++ b/service/realm-ldap.c @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -179,6 +180,7 @@ static GSourceFuncs socket_source_funcs = { /* Not included in ldap.h but documented */ int ldap_init_fd (ber_socket_t fd, int proto, LDAP_CONST char *url, struct ldap **ldp); +#define LDAP_SOCKET_TIMEOUT 5 GSource * realm_ldap_connect_anonymous (GSocketAddress *address, @@ -202,6 +204,8 @@ realm_ldap_connect_anonymous (GSocketAddress *address, int opt_rc; int ldap_opt_val; const char *errmsg = NULL; + struct timeval tv = {LDAP_SOCKET_TIMEOUT, 0}; + unsigned int milli = LDAP_SOCKET_TIMEOUT * 1000; g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (address), NULL); @@ -244,6 +248,23 @@ realm_ldap_connect_anonymous (GSocketAddress *address, if (!g_unix_set_fd_nonblocking (ls->sock, FALSE, NULL)) g_warning ("couldn't set to blocking"); + /* Lower the kernel defaults which might be minutes to hours */ + rc = setsockopt (ls->sock, SOL_SOCKET, SO_RCVTIMEO, + &tv, sizeof (tv)); + if (rc != 0) { + g_warning ("couldn't set SO_RCVTIMEO"); + } + rc = setsockopt (ls->sock, SOL_SOCKET, SO_SNDTIMEO, + &tv, sizeof (tv)); + if (rc != 0) { + g_warning ("couldn't set SO_SNDTIMEO"); + } + rc = setsockopt (ls->sock, IPPROTO_TCP, TCP_USER_TIMEOUT, + &milli, sizeof (milli)); + if (rc != 0) { + g_warning ("couldn't set TCP_USER_TIMEOUT"); + } + if (family == G_SOCKET_FAMILY_IPV4) { url = g_strdup_printf ("%s://%s:%d", use_ldaps ? "ldaps" : "ldap", -- 2.34.1