svn commit: samba r15238 - in branches/SAMBA_4_0/source/libcli/ldap: .

idra at samba.org idra at samba.org
Tue Apr 25 11:50:32 GMT 2006


Author: idra
Date: 2006-04-25 11:50:32 +0000 (Tue, 25 Apr 2006)
New Revision: 15238

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15238

Log:

Add some code to automatically reconnect if we want to.


Modified:
   branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap_client.h


Changeset:
Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c	2006-04-25 11:36:15 UTC (rev 15237)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c	2006-04-25 11:50:32 UTC (rev 15238)
@@ -28,6 +28,39 @@
 #include "lib/tls/tls.h"
 #include "auth/auth.h"
 
+struct ldap_simple_creds {
+	const char *dn;
+	const char *pw;
+};
+
+NTSTATUS ldap_rebind(struct ldap_connection *conn)
+{
+	NTSTATUS status;
+	struct ldap_simple_creds *creds;
+
+	switch (conn->bind.type) {
+	case LDAP_BIND_SASL:
+		status = ldap_bind_sasl(conn, (struct cli_credentials *)conn->bind.creds);
+		break;
+		
+	case LDAP_BIND_SIMPLE:
+		creds = (struct ldap_simple_creds *)conn->bind.creds;
+
+		if (creds == NULL) {
+			return NT_STATUS_UNSUCCESSFUL;
+		}
+
+		status = ldap_bind_simple(conn, creds->dn, creds->pw);
+		break;
+
+	default:
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+
+	return status;
+}
+
+
 static struct ldap_message *new_ldap_simple_bind_msg(struct ldap_connection *conn, 
 						     const char *dn, const char *pw)
 {
@@ -110,6 +143,20 @@
 
 	talloc_free(req);
 
+	if (NT_STATUS_IS_OK(status)) {
+		struct ldap_simple_creds *creds = talloc(conn, struct ldap_simple_creds);
+		if (creds == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		creds->dn = talloc_strdup(creds, dn);
+		creds->pw = talloc_strdup(creds, pw);
+		if (creds->dn == NULL || creds->pw == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		conn->bind.type = LDAP_BIND_SIMPLE;
+		conn->bind.creds = creds;
+	}
+
 	return status;
 }
 
@@ -325,6 +372,12 @@
 	}
 
 	talloc_free(tmp_ctx);
+
+	if (NT_STATUS_IS_OK(status)) {
+		conn->bind.type = LDAP_BIND_SASL;
+		conn->bind.creds = creds;
+	}
+
 	return status;
 
 failed:

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c	2006-04-25 11:36:15 UTC (rev 15237)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_client.c	2006-04-25 11:50:32 UTC (rev 15238)
@@ -33,6 +33,7 @@
 #include "libcli/composite/composite.h"
 #include "lib/stream/packet.h"
 #include "auth/gensec/gensec.h"
+#include "system/time.h"
 
 
 /*
@@ -62,10 +63,12 @@
 	/* set a reasonable request timeout */
 	conn->timeout = 60;
 
+	/* explicitly avoid reconnections by default */
+	conn->reconnect.max_retries = 0;
+	
 	return conn;
 }
 
-
 /*
   the connection is dead
 */
@@ -73,6 +76,7 @@
 {
 	struct ldap_request *req;
 
+	/* return an error for any pending request ... */
 	while (conn->pending) {
 		req = conn->pending;
 		DLIST_REMOVE(req->conn->pending, req);
@@ -84,9 +88,16 @@
 	}	
 
 	talloc_free(conn->tls);
+	talloc_free(conn->sock); /* this will also free event.fde */
+	talloc_free(conn->packet);
 	conn->tls = NULL;
+	conn->sock = NULL;
+	conn->event.fde = NULL;
+	conn->packet = NULL;
 }
 
+static void ldap_reconnect(struct ldap_connection *conn);
+
 /*
   handle packet errors
 */
@@ -95,6 +106,9 @@
 	struct ldap_connection *conn = talloc_get_type(private_data, 
 						       struct ldap_connection);
 	ldap_connection_dead(conn);
+
+	/* but try to reconnect so that the ldb client can go on */
+	ldap_reconnect(conn);
 }
 
 
@@ -325,6 +339,11 @@
 	struct composite_context *result, *ctx;
 	struct ldap_connect_state *state;
 
+	if (conn->reconnect.url == NULL) {
+		conn->reconnect.url = talloc_strdup(conn, url);
+		if (conn->reconnect.url == NULL) goto failed;
+	}
+
 	result = talloc_zero(NULL, struct composite_context);
 	if (result == NULL) goto failed;
 	result->state = COMPOSITE_STATE_IN_PROGRESS;
@@ -419,6 +438,40 @@
 	return ldap_connect_recv(ctx);
 }
 
+/* Actually this function is NOT ASYNC safe, FIXME? */
+static void ldap_reconnect(struct ldap_connection *conn)
+{
+	NTSTATUS status;
+	time_t now = time(NULL);
+
+	/* do we have set up reconnect ? */
+	if (conn->reconnect.max_retries == 0) return;
+
+	/* is the retry time expired ? */
+	if (now > conn->reconnect.previous + 30) {
+		conn->reconnect.retries = 0;
+		conn->reconnect.previous = now;
+	}
+
+	/* are we reconnectind too often and too fast? */
+	if (conn->reconnect.retries > conn->reconnect.max_retries) return;
+
+	/* keep track of the number of reconnections */
+	conn->reconnect.retries++;
+
+	/* reconnect */
+	status = ldap_connect(conn, conn->reconnect.url);
+	if ( ! NT_STATUS_IS_OK(status)) {
+		return;
+	}
+
+	/* rebind */
+	status = ldap_rebind(conn);
+	if ( ! NT_STATUS_IS_OK(status)) {
+		ldap_connection_dead(conn);
+	}
+}
+
 /* destroy an open ldap request */
 static int ldap_request_destructor(void *ptr)
 {
@@ -466,15 +519,16 @@
 				       struct ldap_message *msg)
 {
 	struct ldap_request *req;
-	NTSTATUS status;
+	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 
+	req = talloc_zero(conn, struct ldap_request);
+	if (req == NULL) return NULL;
+
 	if (conn->tls == NULL) {
-		return NULL;
+		status = NT_STATUS_INVALID_CONNECTION;
+		goto failed;
 	}
 
-	req = talloc_zero(conn, struct ldap_request);
-	if (req == NULL) goto failed;
-
 	req->state       = LDAP_REQUEST_SEND;
 	req->conn        = conn;
 	req->messageid   = conn->next_messageid++;
@@ -541,8 +595,12 @@
 	return req;
 
 failed:
-	talloc_free(req);
-	return NULL;
+	req->status = status;
+	req->state = LDAP_REQUEST_ERROR;
+	event_add_timed(conn->event.event_ctx, req, timeval_zero(),
+			ldap_request_complete, req);
+
+	return req;
 }
 
 
@@ -552,7 +610,7 @@
 */
 NTSTATUS ldap_request_wait(struct ldap_request *req)
 {
-	while (req->state != LDAP_REQUEST_DONE) {
+	while (req->state <= LDAP_REQUEST_DONE) {
 		if (event_loop_once(req->conn->event.event_ctx) != 0) {
 			req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
 			break;
@@ -665,7 +723,7 @@
 
 	NT_STATUS_HAVE_NO_MEMORY(req);
 
-	while (req->state != LDAP_REQUEST_DONE && n >= req->num_replies) {
+	while (req->state <= LDAP_REQUEST_DONE && n >= req->num_replies) {
 		if (event_loop_once(req->conn->event.event_ctx) != 0) {
 			return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
 		}

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_client.h
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_client.h	2006-04-25 11:36:15 UTC (rev 15237)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_client.h	2006-04-25 11:50:32 UTC (rev 15238)
@@ -23,7 +23,7 @@
 
 #include "libcli/ldap/ldap.h"
 
-enum ldap_request_state {LDAP_REQUEST_SEND, LDAP_REQUEST_PENDING, LDAP_REQUEST_DONE};
+enum ldap_request_state { LDAP_REQUEST_SEND=1, LDAP_REQUEST_PENDING=2, LDAP_REQUEST_DONE=3, LDAP_REQUEST_ERROR=4 };
 
 /* this is the handle that the caller gets when an async ldap message
    is sent */
@@ -60,6 +60,18 @@
 	const char *auth_dn;
 	const char *simple_pw;
 
+	struct {
+		char *url;
+		int max_retries;
+		int retries;
+		time_t previous;
+	} reconnect;
+
+	struct {
+		enum { LDAP_BIND_SIMPLE, LDAP_BIND_SASL } type;
+		void *creds;
+	} bind;
+
 	/* next message id to assign */
 	unsigned next_messageid;
 



More information about the samba-cvs mailing list