From 9d093f76a82c88647df1cd0ef08b3e8f82e26abb Mon Sep 17 00:00:00 2001 From: Alan Hicks Date: Fri, 30 Sep 2016 17:17:05 +0100 Subject: [PATCH 09/33] Rework temporary connection failures --- src/modules/authldap.c | 102 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 35 deletions(-) diff --git src/modules/authldap.c src/modules/authldap.c index 19802c8..2073768 100644 --- src/modules/authldap.c +++ src/modules/authldap.c @@ -110,18 +110,48 @@ static gpointer authldap_once(gpointer UNUSED data) return (gpointer)NULL; } -/* - lookup thread-local ldap connection -*/ +/* + * ldap_con_get() + * + * Lookup thread-local ldap connection and bind using config credentials + * retrying a few times if the server is temporarily unavailable + * + * returns connection on success, NULL on failure + */ static LDAP * ldap_con_get(void) { - LDAP * c = (LDAP *)g_static_private_get(&ldap_conn_key); - if (! c) { - authldap_connect(); - c = (LDAP *)g_static_private_get(&ldap_conn_key); + LDAP * ld = (LDAP *)g_static_private_get(&ldap_conn_key); + if (ld) { + TRACE(TRACE_DEBUG, "connection [%p]", ld); + return ld; } - TRACE(TRACE_DEBUG, "connection [%p]", c); - return c; + int c = 0; + int err = -1; // Start wanting success + while (err != 0 && c++ < 5) { + // Loop until success or too many retries + TRACE(TRACE_DEBUG, "No connection trying [%d]", c); + + err = authldap_connect(); + + switch (err) { + case LDAP_SUCCESS: + ld = (LDAP *)g_static_private_get(&ldap_conn_key); + TRACE(TRACE_DEBUG, "connection [%p]", ld); + break; + case LDAP_SERVER_DOWN: + TRACE(TRACE_WARNING, "LDAP gone away: %s. Trying to reconnect(%d/5).", ldap_err2string(err),c); + sleep(2); // reconnect failed. wait before trying again + break; + default: + TRACE(TRACE_ERR, "LDAP error(%d): %s", err, ldap_err2string(err)); + break; + } + } + if (! ld) { + TRACE(TRACE_ERR, "Unable to connect to LDAP giving up"); + } + TRACE(TRACE_DEBUG, "connection [%p]", ld); + return ld; } /* @@ -140,6 +170,13 @@ static void authldap_free(gpointer data) sigaction(SIGPIPE, &oldact, 0); } +/* + * auth_ldap_bind() + * + * Bind to server using config credentials + * + * returns 0 on success, -1 on failure + */ static int auth_ldap_bind(void) { int err; @@ -153,7 +190,6 @@ static int auth_ldap_bind(void) } return 0; - } /* @@ -213,44 +249,40 @@ static int authldap_connect(void) return auth_ldap_bind(); } -static int authldap_reconnect(void) -{ - LDAP *c; - if ((c = ldap_con_get())) authldap_free((gpointer)c); - return authldap_connect(); -} - +/* + * authldap_search() + * + * Perform an LDAP search + * + * returns search results on success, NULL on failure + */ static LDAPMessage * authldap_search(const gchar *query) { LDAPMessage *ldap_res; int _ldap_attrsonly = 0; char **_ldap_attrs = NULL; - int c=0, err; + int err; LDAP *_ldap_conn; g_return_val_if_fail(query!=NULL, NULL); _ldap_conn = ldap_con_get(); - while (c++ < 5) { - TRACE(TRACE_DEBUG, " [%s]", query); - err = ldap_search_s(_ldap_conn, _ldap_cfg.base_dn, _ldap_cfg.scope_int, - query, _ldap_attrs, _ldap_attrsonly, &ldap_res); + TRACE(TRACE_DEBUG, " [%s]", query); + err = ldap_search_s(_ldap_conn, _ldap_cfg.base_dn, _ldap_cfg.scope_int, + query, _ldap_attrs, _ldap_attrsonly, &ldap_res); - if (! err) - return ldap_res; + if (! err) + return ldap_res; - switch (err) { - case LDAP_SERVER_DOWN: - TRACE(TRACE_WARNING, "LDAP gone away: %s. Try to reconnect(%d/5).", ldap_err2string(err),c); - if (authldap_reconnect()) - sleep(2); // reconnect failed. wait before trying again - break; - default: - TRACE(TRACE_ERR, "LDAP error(%d): %s", err, ldap_err2string(err)); - return NULL; - break; - } + switch (err) { + case LDAP_SERVER_DOWN: + TRACE(TRACE_WARNING, "LDAP gone away: %s).", ldap_err2string(err)); + break; + default: + TRACE(TRACE_ERR, "LDAP error(%d): %s", err, ldap_err2string(err)); + return NULL; + break; } TRACE(TRACE_EMERG,"unrecoverable error while talking to ldap server"); -- 2.10.1 (Apple Git-78)