Blame SOURCES/0001-ldap-add-socket-timeout.patch

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