dovecot-1.0: Reconnect if ldap_search() returns a failure relate...

dovecot at dovecot.org dovecot at dovecot.org
Mon Sep 10 09:24:15 EEST 2007


details:   http://hg.dovecot.org/dovecot-1.0/rev/3801a497f97b
changeset: 5400:3801a497f97b
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Sep 10 09:24:11 2007 +0300
description:
Reconnect if ldap_search() returns a failure related to connection problems.
Also if ldap_result() doesn't return a connection related failure, don't
reconnect.

diffstat:

1 file changed, 61 insertions(+), 23 deletions(-)
src/auth/db-ldap.c |   84 +++++++++++++++++++++++++++++++++++++---------------

diffs (140 lines):

diff -r 13b3b8c9eccc -r 3801a497f97b src/auth/db-ldap.c
--- a/src/auth/db-ldap.c	Sun Sep 09 07:18:59 2007 +0300
+++ b/src/auth/db-ldap.c	Mon Sep 10 09:24:11 2007 +0300
@@ -135,7 +135,7 @@ static int ldap_get_errno(struct ldap_co
 	if (ret != LDAP_SUCCESS) {
 		i_error("LDAP: Can't get error number: %s",
 			ldap_err2string(ret));
-		return -1;
+		return LDAP_UNAVAILABLE;
 	}
 
 	return err;
@@ -178,17 +178,66 @@ static void db_ldap_handle_next_delayed_
 	conn->retrying = FALSE;
 }
 
+static void ldap_conn_reconnect(struct ldap_connection *conn)
+{
+	ldap_conn_close(conn, FALSE);
+
+	if (db_ldap_connect(conn) < 0) {
+		/* failed to reconnect. fail all requests. */
+		ldap_conn_close(conn, TRUE);
+	}
+}
+
+static void ldap_handle_error(struct ldap_connection *conn)
+{
+	int err = ldap_get_errno(conn);
+
+	switch (err) {
+	case LDAP_SUCCESS:
+		i_unreached();
+	case LDAP_SIZELIMIT_EXCEEDED:
+	case LDAP_TIMELIMIT_EXCEEDED:
+	case LDAP_NO_SUCH_ATTRIBUTE:
+	case LDAP_UNDEFINED_TYPE:
+	case LDAP_INAPPROPRIATE_MATCHING:
+	case LDAP_CONSTRAINT_VIOLATION:
+	case LDAP_TYPE_OR_VALUE_EXISTS:
+	case LDAP_INVALID_SYNTAX:
+	case LDAP_NO_SUCH_OBJECT:
+	case LDAP_ALIAS_PROBLEM:
+	case LDAP_INVALID_DN_SYNTAX:
+	case LDAP_IS_LEAF:
+	case LDAP_ALIAS_DEREF_PROBLEM:
+	case LDAP_FILTER_ERROR:
+		/* invalid input */
+		break;
+	case LDAP_SERVER_DOWN:
+	case LDAP_TIMEOUT:
+	case LDAP_UNAVAILABLE:
+	case LDAP_BUSY:
+#ifdef LDAP_CONNECT_ERROR
+	case LDAP_CONNECT_ERROR:
+#endif
+	case LDAP_LOCAL_ERROR:
+	case LDAP_INVALID_CREDENTIALS:
+	default:
+		/* connection problems */
+		ldap_conn_reconnect(conn);
+		break;
+	}
+}
+
 void db_ldap_search(struct ldap_connection *conn, struct ldap_request *request,
 		    int scope)
 {
-	int msgid;
+	int try, msgid = -1;
 
 	if (db_ldap_connect(conn) < 0) {
 		request->callback(conn, request, NULL);
 		return;
 	}
 
-	if (conn->connected && !conn->binding) {
+	for (try = 0; conn->connected && !conn->binding && try < 2; try++) {
 		if (conn->last_auth_bind) {
 			/* switch back to the default dn before doing the
 			   search request. */
@@ -196,8 +245,7 @@ void db_ldap_search(struct ldap_connecti
 				request->callback(conn, request, NULL);
 				return;
 			}
-			db_ldap_add_delayed_request(conn, request);
-			return;
+			break;
 		}
 
 		msgid = ldap_search(conn->ld, request->base, scope,
@@ -205,13 +253,14 @@ void db_ldap_search(struct ldap_connecti
 		if (msgid == -1) {
 			i_error("LDAP: ldap_search() failed (filter %s): %s",
 				request->filter, ldap_get_error(conn));
-			request->callback(conn, request, NULL);
-			return;
-		}
+			ldap_handle_error(conn);
+		}
+	}
+
+	if (msgid != -1)
 		hash_insert(conn->requests, POINTER_CAST(msgid), request);
-	} else {
+	else
 		db_ldap_add_delayed_request(conn, request);
-	}
 }
 
 static void ldap_conn_retry_requests(struct ldap_connection *conn)
@@ -290,16 +339,6 @@ static void ldap_conn_retry_requests(str
 	i_assert(conn->delayed_requests_head == NULL);
 	conn->delayed_requests_tail = NULL;
 	conn->retrying = FALSE;
-}
-
-static void ldap_conn_reconnect(struct ldap_connection *conn)
-{
-	ldap_conn_close(conn, FALSE);
-
-	if (db_ldap_connect(conn) < 0) {
-		/* failed to reconnect. fail all requests. */
-		ldap_conn_close(conn, TRUE);
-	}
 }
 
 static void ldap_input(void *context)
@@ -340,9 +379,8 @@ static void ldap_input(void *context)
 	}
 
 	if (ret < 0) {
-		i_error("LDAP: ldap_result() failed: %s",
-			ldap_get_error(conn));
-		ldap_conn_reconnect(conn);
+		i_error("LDAP: ldap_result() failed: %s", ldap_get_error(conn));
+		ldap_handle_error(conn);
 	} else {
 		if (!conn->binding)
 			db_ldap_handle_next_delayed_request(conn);


More information about the dovecot-cvs mailing list