autofs-5.1.9 - do_reconnect() expiry check of dclist BEFORE lookup using it

From: Patrick Cernko <pcernko@mpi-klsb.mpg.de>

this patch changes the behavior when to refresh LDAP SRV records. The
documentation states:

> The server list returned from an SRV RR lookup is refreshed according
> to the minimum ttl found in the SRV RR records or after one hour,
> whichever is less.

But the code in fact does not do any refreshing as long as at least one
server in the dclist still responds.

This issue became obvious in our setup, when we had to disable the first
two servers: autofs continued to contact ldap-a and ldap-b, running in
timeouts (~5sec) and finally got an answer from ldap-c. But due to the
timeouts every mount took >10sec resulting in slow responsiveness for
the whole system. Changing the SRV records (with TTLs of 7200) did not
help. As a workaround we had to signal all client's automount processes
with HUP.

The change invalidates the dclist if expired. This forces autofs to do
a new SRV record lookup before doing the LDAP lookup.

Signed-off-by: Patrick Cernko <pcernko@mpi-klsb.mpg.de>
Signed-off-by: Ian Kent <raven@themaw.net>
---
 CHANGELOG             |    1 +
 modules/lookup_ldap.c |   18 ++++++++++--------
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 04ac370e9..af7b2dde7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -86,6 +86,7 @@
 - fix fields not freed in clear_amd_entry().
 - initialise fields after free in clear_amd_entry().
 - fix some fields not copied in dup_defaults_entry().
+- do_reconnect() expiry check of dclist BEFORE lookup using it.
 
 02/11/2023 autofs-5.1.9
 - fix kernel mount status notification.
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index d27a6bb83..a266e752c 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1155,17 +1155,11 @@ static int do_reconnect(unsigned logopt,
 		return ret;
 	}
 
-	if (ctxt->dclist) {
-		dcrv = find_dc_server(logopt, conn, ctxt->dclist->uri, ctxt);
-		if (dcrv == NSS_STATUS_SUCCESS) {
-			ldapinit_mutex_unlock();
-			return dcrv;
-		}
-	}
-
 	uris_mutex_lock(ctxt);
 	if (ctxt->dclist) {
 		if (!conn->ldap || ctxt->dclist->expire < monotonic_time(NULL)) {
+			debug(logopt, MODPREFIX
+			      "dclist expired, removing it to force new lookup");
 			free_dclist(ctxt->dclist);
 			ctxt->dclist = NULL;
 		}
@@ -1176,6 +1170,14 @@ static int do_reconnect(unsigned logopt,
 	}
 	uris_mutex_unlock(ctxt);
 
+	if (ctxt->dclist) {
+		dcrv = find_dc_server(logopt, conn, ctxt->dclist->uri, ctxt);
+		if (dcrv == NSS_STATUS_SUCCESS) {
+			ldapinit_mutex_unlock();
+			return dcrv;
+		}
+	}
+
 	if (!ctxt->uri)
 		goto find_server;
 
