r13609: Get in the initial work on making ldb async
authorSimo Sorce <idra@samba.org>
Wed, 22 Feb 2006 01:31:35 +0000 (01:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:51:59 +0000 (13:51 -0500)
Currently only ldb_ildap is async, the plan
is to first make all backend support the async calls,
and then remove the sync functions from backends and
keep the only in the API.

Modules will need to be transformed along the way.

Simo
(This used to be commit 1e2c13b2d52de7c534493dd79a2c0596a3e8c1f5)

17 files changed:
source4/ldap_server/ldap_backend.c
source4/lib/ldb/common/ldb.c
source4/lib/ldb/common/ldb_modules.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/include/ldb_private.h
source4/lib/ldb/ldb_ildap/ldb_ildap.c
source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
source4/lib/ldb/ldb_tdb/ldb_index.c
source4/lib/ldb/ldb_tdb/ldb_search.c
source4/lib/ldb/tools/cmdline.c
source4/lib/ldb/tools/ldbsearch.c
source4/libcli/ldap/ldap.c
source4/libcli/ldap/ldap.h
source4/libcli/ldap/ldap_client.c
source4/libcli/ldap/ldap_client.h
source4/libcli/ldap/ldap_controls.c
source4/libcli/ldap/ldap_ildap.c

index 1399ac18e48fff30cb3caa08ab79d424768845e9..713d99a2ea47d0021b09d43632b3df8e7555acb8 100644 (file)
@@ -44,44 +44,6 @@ static int map_ldb_error(struct ldb_context *ldb, int err, const char **errstrin
        return err;
 }
 
-/*
-  map controls
-*/
-static int get_ldb_controls(void *mem_ctx, struct ldap_Control **controls, struct ldb_control ***lcontrols)
-{
-       struct ldb_control **lctrl;
-       int i, l;
-
-       if (controls == NULL || controls[0] == NULL) {
-               *lcontrols = NULL;
-               return LDB_SUCCESS;
-       }
-
-       l = 0;
-       lctrl = NULL;
-       *lcontrols = NULL;
-       
-       for (i = 0; controls[i] != NULL; i++) {
-               lctrl = talloc_realloc(mem_ctx, lctrl, struct ldb_control *, l + 2);
-               if (lctrl == NULL) {
-                       return LDB_ERR_OTHER;
-               }
-               lctrl[l] = talloc(lctrl, struct ldb_control);
-               if (lctrl[l] == NULL) {
-                       return LDB_ERR_OTHER;
-               }
-               lctrl[l]->oid = controls[i]->oid;
-               lctrl[l]->critical = controls[i]->critical;
-               lctrl[l]->data = controls[i]->value;
-               l++;
-       }       
-       lctrl[l] = NULL;
-
-       *lcontrols = lctrl;
-
-       return LDB_SUCCESS;
-}
-
 /*
   connect to the sam database
 */
@@ -217,14 +179,7 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
        lreq.op.search.tree = req->tree;
        lreq.op.search.attrs = attrs;
 
-       ldb_ret = get_ldb_controls(local_ctx, call->request->controls, &lreq.controls);
-
-       if (ldb_ret != LDB_SUCCESS) {
-               /* get_ldb_controls fails only on a critical internal error or when
-                * a control is defined as critical but it is not supported
-                */
-               goto reply;
-       }
+       lreq.controls = call->request->controls;
 
        ldb_ret = ldb_request(samdb, &lreq);
 
@@ -281,7 +236,7 @@ reply:
                        errstr = ldb_errstring(samdb);
                }
                if (res->controls) {
-                       done_r->msg->controls = (struct ldap_Control **)(res->controls);
+                       done_r->msg->controls = res->controls;
                        talloc_steal(done_r, res->controls);
                }
        } else {
index 0857c07ad4efdb44709d975c88ac04ee0ba91d19..68722cde96fdbdbef748c73dbb65403943758293 100644 (file)
@@ -106,7 +106,15 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co
        return LDB_SUCCESS;
 }
 
-static void ldb_reset_err_string(struct ldb_context *ldb)
+void ldb_set_errstring(struct ldb_module *module, char *err_string)
+{
+       if (module->ldb->err_string) {
+               talloc_free(module->ldb->err_string);
+       }
+       module->ldb->err_string = talloc_steal(module->ldb, err_string);
+}
+
+void ldb_reset_err_string(struct ldb_context *ldb)
 {
        if (ldb->err_string) {
                talloc_free(ldb->err_string);
@@ -211,6 +219,14 @@ int ldb_transaction_cancel(struct ldb_context *ldb)
        return status;
 }
 
+int ldb_async_wait(struct ldb_context *ldb, struct ldb_async_handle *handle, enum ldb_async_wait_type type)
+{
+       if (ldb->async_wait != NULL)
+               return ldb->async_wait(handle, type);
+
+       return LDB_ERR_OPERATIONS_ERROR;
+}
+
 /*
   check for an error return from an op 
   if an op fails, but has not setup an error string, then setup one now
@@ -279,6 +295,9 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *request)
        if (request->operation == LDB_REQ_SEARCH) {
                request->op.search.res = talloc_steal(ldb, r->op.search.res);
        }
+       if (request->operation == LDB_ASYNC_SEARCH) {
+               request->async.handle = r->async.handle;
+       }
        talloc_free(r);
 
        if (started_transaction) {
index ddbdddedcc41820c3e3e8d809587ceb8e06dfb87..922506ea4d6e2bc9abc564c2a162f425060ca9e5 100644 (file)
@@ -263,13 +263,3 @@ int ldb_next_del_trans(struct ldb_module *module)
        FIND_OP(module, del_transaction);
        return module->ops->del_transaction(module);
 }
-
-void ldb_set_errstring(struct ldb_module *module, char *err_string)
-{
-       if (module->ldb->err_string) {
-               talloc_free(module->ldb->err_string);
-       }
-
-       module->ldb->err_string = talloc_steal(module->ldb, err_string);
-}
-
index a6cec7f774f1526eeada6fc12310e364698f2648..4a40e34363279bea59b83d282c424944a6c5a948 100644 (file)
@@ -560,15 +560,51 @@ enum ldb_request_type {
        LDB_REQ_MODIFY,
        LDB_REQ_DELETE,
        LDB_REQ_RENAME,
+       LDB_ASYNC_SEARCH,
+       LDB_ASYNC_ADD,
+       LDB_ASYNC_MODIFY,
+       LDB_ASYNC_DELETE,
+       LDB_ASYNC_RENAME,
+
        LDB_REQ_REGISTER
 };
 
+enum ldb_reply_type {
+       LDB_REPLY_ENTRY,
+       LDB_REPLY_REFERRAL,
+       LDB_REPLY_DONE
+};
+
+enum ldb_async_wait_type {
+       LDB_WAIT_ALL,
+       LDB_WAIT_NONE
+};
+
+enum ldb_async_state {
+       LDB_ASYNC_PENDING,
+       LDB_ASYNC_DONE
+};
+
 struct ldb_result {
        unsigned int count;
        struct ldb_message **msgs;
+       char **refs;
        struct ldb_control **controls;
 };
 
+struct ldb_async_result {
+       enum ldb_reply_type type;
+       struct ldb_message *message;
+       char *referral;
+       struct ldb_control **controls;
+};
+
+struct ldb_async_handle {
+       int status;
+       enum ldb_async_state state;
+       void *private_data;
+};
+
 struct ldb_search {
        const struct ldb_dn *base;
        enum ldb_scope scope;
@@ -613,10 +649,20 @@ struct ldb_request {
 
        struct ldb_control **controls;
        struct ldb_credentials *creds;
+
+       struct {
+               void *context;
+               int (*callback)(struct ldb_context *, void *, struct ldb_async_result *);
+
+               time_t timeout;
+               struct ldb_async_handle *handle;
+       } async;
 };
 
 int ldb_request(struct ldb_context *ldb, struct ldb_request *request);
 
+int ldb_async_wait(struct ldb_context *ldb, struct ldb_async_handle *handle, enum ldb_async_wait_type type);
+
 /**
   Initialise an ldb context
 
index 90632744edc2f9ead78b2fd0123c5701f8eab97a..db34b5885876a7fa34a3503866327d7a7b185556 100644 (file)
@@ -105,6 +105,8 @@ struct ldb_context {
        char *err_string;
 
        int transaction_active;
+
+       int (*async_wait)(struct ldb_async_handle *, enum ldb_async_wait_type);
 };
 
 /* the modules init function */
@@ -132,6 +134,7 @@ int ldb_next_del_trans(struct ldb_module *module);
 int ldb_next_second_stage_init(struct ldb_module *module);
 
 void ldb_set_errstring(struct ldb_module *module, char *err_string);
+void ldb_reset_err_string(struct ldb_context *ldb);
 
 /* The following definitions come from lib/ldb/common/ldb_debug.c  */
 void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
index a6a5822c9e881daec56a4448046dcc1a0569e582..33d3954a73ae00b8b99eef00244cc9fd9208cb97 100644 (file)
@@ -2,6 +2,7 @@
    ldb database library - ildap backend
 
    Copyright (C) Andrew Tridgell  2005
+   Copyright (C) Simo Sorce       2006
 
      ** NOTE! The following LGPL license applies to the ldb
      ** library. This does NOT imply that all of Samba is released
@@ -32,6 +33,7 @@
 #include "includes.h"
 #include "ldb/include/includes.h"
 
+#include "lib/events/events.h"
 #include "libcli/ldap/ldap.h"
 #include "libcli/ldap/ldap_client.h"
 #include "lib/cmdline/popt_common.h"
@@ -43,6 +45,66 @@ struct ildb_private {
        struct ldb_context *ldb;
 };
 
+struct ildb_async_context {
+       struct ldb_module *module;
+       struct ldap_request *req;
+       void *context;
+       int (*callback)(struct ldb_context *, void *, struct ldb_async_result *);
+};
+
+/*
+  convert a ldb_message structure to a list of ldap_mod structures
+  ready for ildap_add() or ildap_modify()
+*/
+static struct ldap_mod **ildb_msg_to_mods(void *mem_ctx, int *num_mods,
+                                         const struct ldb_message *msg, int use_flags)
+{
+       struct ldap_mod **mods;
+       unsigned int i;
+       int n = 0;
+
+       /* allocate maximum number of elements needed */
+       mods = talloc_array(mem_ctx, struct ldap_mod *, msg->num_elements+1);
+       if (!mods) {
+               errno = ENOMEM;
+               return NULL;
+       }
+       mods[0] = NULL;
+
+       for (i = 0; i < msg->num_elements; i++) {
+               const struct ldb_message_element *el = &msg->elements[i];
+
+               mods[n] = talloc(mods, struct ldap_mod);
+               if (!mods[n]) {
+                       goto failed;
+               }
+               mods[n + 1] = NULL;
+               mods[n]->type = 0;
+               mods[n]->attrib = *el;
+               if (use_flags) {
+                       switch (el->flags & LDB_FLAG_MOD_MASK) {
+                       case LDB_FLAG_MOD_ADD:
+                               mods[n]->type = LDAP_MODIFY_ADD;
+                               break;
+                       case LDB_FLAG_MOD_DELETE:
+                               mods[n]->type = LDAP_MODIFY_DELETE;
+                               break;
+                       case LDB_FLAG_MOD_REPLACE:
+                               mods[n]->type = LDAP_MODIFY_REPLACE;
+                               break;
+                       }
+               }
+               n++;
+       }
+
+       *num_mods = n;
+       return mods;
+
+failed:
+       talloc_free(mods);
+       return NULL;
+}
+
 
 /*
   map an ildap NTSTATUS to a ldb error code
@@ -60,330 +122,661 @@ static int ildb_map_error(struct ildb_private *ildb, NTSTATUS status)
        return LDB_ERR_OPERATIONS_ERROR;
 }
 
-/*
-  rename a record
-*/
-static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
+static void ildb_request_timeout(struct event_context *ev, struct timed_event *te,
+                                struct timeval t, void *private_data)
 {
-       TALLOC_CTX *local_ctx;
-       struct ildb_private *ildb = module->private_data;
-       int ret = 0;
-       char *old_dn;
-       char *newrdn, *parentdn;
-       NTSTATUS status;
+       struct ldb_async_handle *handle = talloc_get_type(private_data, struct ldb_async_handle);
+       struct ildb_async_context *ac = talloc_get_type(handle->private_data, struct ildb_async_context);
 
-       /* ignore ltdb specials */
-       if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
-               return LDB_SUCCESS;
+       if (ac->req->state == LDAP_REQUEST_PENDING) {
+               DLIST_REMOVE(ac->req->conn->pending, ac->req);
        }
 
-       local_ctx = talloc_named(ildb, 0, "ildb_rename local context");
-       if (local_ctx == NULL) {
-               ret = LDB_ERR_OPERATIONS_ERROR;
-               goto failed;
-       }
+       handle->status = LDB_ERR_OPERATIONS_ERROR;
 
-       old_dn = ldb_dn_linearize(local_ctx, olddn);
-       if (old_dn == NULL) {
-               ret = LDB_ERR_INVALID_DN_SYNTAX;
-               goto failed;
-       }
+       return;
+}
 
-       newrdn = talloc_asprintf(local_ctx, "%s=%s",
-                                           newdn->components[0].name,
-                                           ldb_dn_escape_value(ildb, newdn->components[0].value));
-       if (newrdn == NULL) {
-               ret = LDB_ERR_OPERATIONS_ERROR;
-               goto failed;
-       }
+static void ildb_async_callback(struct ldap_request *req)
+{
+       struct ldb_async_handle *handle = talloc_get_type(req->async.private_data, struct ldb_async_handle);
+       struct ildb_async_context *ac = talloc_get_type(handle->private_data, struct ildb_async_context);
+       struct ildb_private *ildb = ac->module->private_data;
+       NTSTATUS status;
+       int i;
 
-       parentdn = ldb_dn_linearize(local_ctx, ldb_dn_get_parent(ildb, newdn));
-       if (parentdn == NULL) {
-               ret = LDB_ERR_INVALID_DN_SYNTAX;
-               goto failed;
+       handle->status = LDB_SUCCESS;
+
+       if (!NT_STATUS_IS_OK(req->status)) {
+               handle->status = ildb_map_error(ildb, req->status);
+               return;
        }
 
-       status = ildap_rename(ildb->ldap, old_dn, newrdn, parentdn, True);
-       ret = ildb_map_error(ildb, status);
+       if (req->num_replies < 1) {
+               handle->status = LDB_ERR_OPERATIONS_ERROR;
+               return;
+       } 
+               
+       switch (req->type) {
 
-failed:
-       talloc_free(local_ctx);
-       return ret;
+       case LDAP_TAG_ModifyRequest:
+               if (req->replies[0]->type != LDAP_TAG_ModifyResponse) {
+                       handle->status = LDB_ERR_PROTOCOL_ERROR;
+                       return;
+               }
+               status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult);
+               handle->status = ildb_map_error(ildb, status);
+               handle->state = LDB_ASYNC_DONE;
+               break;
+
+       case LDAP_TAG_AddRequest:
+               if (req->replies[0]->type != LDAP_TAG_AddResponse) {
+                       handle->status = LDB_ERR_PROTOCOL_ERROR;
+                       return;
+               }
+               status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult);
+               handle->status = ildb_map_error(ildb, status);
+               handle->state = LDB_ASYNC_DONE;
+               break;
+
+       case LDAP_TAG_DelRequest:
+               if (req->replies[0]->type != LDAP_TAG_DelResponse) {
+                       handle->status = LDB_ERR_PROTOCOL_ERROR;
+                       return;
+               }
+               status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult);
+               handle->status = ildb_map_error(ildb, status);
+               handle->state = LDB_ASYNC_DONE;
+               break;
+
+       case LDAP_TAG_ModifyDNRequest:
+               if (req->replies[0]->type != LDAP_TAG_ModifyDNResponse) {
+                       handle->status = LDB_ERR_PROTOCOL_ERROR;
+                       return;
+               }
+               status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult);
+               handle->status = ildb_map_error(ildb, status);
+               handle->state = LDB_ASYNC_DONE;
+               break;
+
+       case LDAP_TAG_SearchRequest:
+               /* loop over all messages */
+               for (i = 0; i < req->num_replies; i++) {
+                       struct ldap_SearchResEntry *search;
+                       struct ldb_async_result *ares = NULL;
+                       struct ldap_message *msg;
+                       int ret;
+
+                       ares = talloc_zero(ac, struct ldb_async_result);
+                       if (!ares) {
+                               handle->status = LDB_ERR_OPERATIONS_ERROR;
+                               return;
+                       }
+
+                       msg = req->replies[i];
+                       switch (msg->type) {
+
+                       case LDAP_TAG_SearchResultDone:
+
+                               status = ldap_check_response(req->conn, &msg->r.GeneralResult);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Error: %s\n" ,ldap_errstr(req->conn, status));
+                                       handle->status = ildb_map_error(ildb, status);
+                                       return;
+                               }
+                               
+                               if (msg->controls) {
+                                       ares->controls = talloc_steal(ares, msg->controls);
+                               }
+                               if (msg->r.SearchResultDone.resultcode) {
+                                       if (msg->r.SearchResultDone.errormessage) {
+                                               ldb_set_errstring(ac->module, talloc_strdup(ac->module, msg->r.SearchResultDone.errormessage));
+                                       }
+                               }
+
+                               handle->status = msg->r.SearchResultDone.resultcode;
+                               handle->state = LDB_ASYNC_DONE;
+                               ares->type = LDB_REPLY_DONE;
+                               break;
+
+                       case LDAP_TAG_SearchResultEntry:
+
+
+                               ares->message = ldb_msg_new(ares);
+                               if (!ares->message) {
+                                       handle->status = LDB_ERR_OPERATIONS_ERROR;;
+                                       return;
+                               }
+
+                               search = &(msg->r.SearchResultEntry);
+               
+                               ares->message->dn = ldb_dn_explode_or_special(ares->message, search->dn);
+                               if (ares->message->dn == NULL) {
+                                       handle->status = LDB_ERR_OPERATIONS_ERROR;
+                                       return;
+                               }
+                               ares->message->num_elements = search->num_attributes;
+                               ares->message->elements = talloc_steal(ares->message, search->attributes);
+
+                               handle->status = LDB_SUCCESS;
+                               handle->state = LDB_ASYNC_PENDING;
+                               ares->type = LDB_REPLY_ENTRY;
+                               break;
+
+                       case LDAP_TAG_SearchResultReference:
+
+                               ares->referral = talloc_strdup(ares, msg->r.SearchResultReference.referral);
+                               
+                               handle->status = LDB_SUCCESS;
+                               handle->state = LDB_ASYNC_PENDING;
+                               ares->type = LDB_REPLY_REFERRAL;
+                               break;
+
+                       default:
+                               /* TAG not handled, fail ! */
+                               handle->status = LDB_ERR_PROTOCOL_ERROR;
+                               return;
+                       }
+
+                       ret = ac->callback(ac->module->ldb, ac->context, ares);
+                       if (ret) {
+                               handle->status = ret;
+                       }
+               }
+
+               talloc_free(req->replies);
+               req->replies = NULL;
+               req->num_replies = 0;
+
+               break;
+               
+       default:
+               handle->status = LDB_ERR_PROTOCOL_ERROR;
+               return;
+       }
 }
 
-/*
-  delete a record
-*/
-static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn)
+static int ildb_request_send(struct ldb_module *module, struct ldap_message *msg,
+                            void *context,
+                            int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+                            int timeout,
+                            struct ldb_async_handle **handle)
 {
        struct ildb_private *ildb = module->private_data;
-       char *del_dn;
-       int ret = 0;
-       NTSTATUS status;
+       struct ildb_async_context *ildb_ac;
+       struct ldb_async_handle *h;
+       struct ldap_request *req;
 
-       /* ignore ltdb specials */
-       if (ldb_dn_is_special(dn)) {
-               return LDB_SUCCESS;
+       h = talloc_zero(ildb->ldap, struct ldb_async_handle);
+       if (h == NULL) {
+               ldb_set_errstring(module, talloc_asprintf(module, "Out of Memory"));
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       
-       del_dn = ldb_dn_linearize(ildb, dn);
-       if (del_dn == NULL) {
-               return LDB_ERR_INVALID_DN_SYNTAX;
+
+       ildb_ac = talloc(h, struct ildb_async_context);
+       if (ildb_ac == NULL) {
+               ldb_set_errstring(module, talloc_asprintf(module, "Out of Memory"));
+               talloc_free(h);
+               return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       status = ildap_delete(ildb->ldap, del_dn);
-       ret = ildb_map_error(ildb, status);
+       h->private_data = (void *)ildb_ac;
 
-       talloc_free(del_dn);
+       req = ldap_request_send(ildb->ldap, msg);
+       if (req == NULL) {
+               ldb_set_errstring(module, talloc_asprintf(module, "async send request failed"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
-       return ret;
-}
+       ildb_ac->req = talloc_steal(ildb_ac, req);
+       ildb_ac->module = module;
+       ildb_ac->context = context;
+       ildb_ac->callback = callback;
 
+       req->async.fn = ildb_async_callback;
+       req->async.private_data = (void *)h;
 
-static void ildb_rootdse(struct ldb_module *module);
+       talloc_free(req->time_event);
+       req->time_event = NULL;
+       if (timeout) {
+               req->time_event = event_add_timed(req->conn->event.event_ctx, h, 
+                                                 timeval_current_ofs(timeout, 0),
+                                                 ildb_request_timeout, ildb_ac);
+       }
+
+       *handle = h;
+
+       return LDB_SUCCESS;
+
+}
 
 /*
-  search for matching records using a ldb_parse_tree
-*/
-static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
+  search for matching records using an asynchronous function
+ */
+static int ildb_search_async(struct ldb_module *module, const struct ldb_dn *base,
                              enum ldb_scope scope, struct ldb_parse_tree *tree,
                              const char * const *attrs,
                              struct ldb_control **control_req,
-                             struct ldb_result **res)
+                             void *context,
+                             int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+                             int timeout,
+                             struct ldb_async_handle **handle)
 {
        struct ildb_private *ildb = module->private_data;
-       int count, i;
-       struct ldap_message **ldapres, *msg;
-       struct ldap_Control **controls = NULL;
-       char *search_base;
-       NTSTATUS status;
+       struct ldap_message *msg;
+       int n;
 
-       if (scope == LDB_SCOPE_DEFAULT) {
-               scope = LDB_SCOPE_SUBTREE;
+       *handle = NULL;
+
+       if (!callback || !context) {
+               ldb_set_errstring(module, talloc_asprintf(module, "Async interface called with NULL callback function or NULL context"));
+               return LDB_ERR_OPERATIONS_ERROR;
        }
        
+       if (tree == NULL) {
+               ldb_set_errstring(module, talloc_asprintf(module, "Invalid expression parse tree"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       msg = new_ldap_message(ildb);
+       if (msg == NULL) {
+               ldb_set_errstring(module, talloc_asprintf(module, "Out of Memory"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       msg->type = LDAP_TAG_SearchRequest;
+
        if (base == NULL) {
-               if (ildb->rootDSE == NULL) {
-                       ildb_rootdse(module);
-               }
                if (ildb->rootDSE != NULL) {
-                       search_base = talloc_strdup(ildb,
-                                               ldb_msg_find_string(ildb->rootDSE, 
-                                                               "defaultNamingContext", ""));
+                       msg->r.SearchRequest.basedn =
+                               talloc_strdup(msg, ldb_msg_find_string(ildb->rootDSE, "defaultNamingContext", ""));
                } else {
-                       search_base = talloc_strdup(ildb, "");
+                       msg->r.SearchRequest.basedn = talloc_strdup(msg, "");
                }
        } else {
-               search_base = ldb_dn_linearize(ildb, base);
+               msg->r.SearchRequest.basedn  = ldb_dn_linearize(msg, base);
        }
-       if (search_base == NULL) {
+       if (msg->r.SearchRequest.basedn == NULL) {
                ldb_set_errstring(module, talloc_asprintf(module, "Unable to determine baseDN"));
-               return LDB_ERR_OTHER;
+               talloc_free(msg);
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       if (tree == NULL) {
-               ldb_set_errstring(module, talloc_asprintf(module, "Invalid expression parse tree"));
-               return LDB_ERR_OTHER;
+
+       if (scope == LDB_SCOPE_DEFAULT) {
+               msg->r.SearchRequest.scope = LDB_SCOPE_SUBTREE;
+       } else {
+               msg->r.SearchRequest.scope = scope;
        }
+       
+       msg->r.SearchRequest.deref  = LDAP_DEREFERENCE_NEVER;
+       msg->r.SearchRequest.timelimit = 0;
+       msg->r.SearchRequest.sizelimit = 0;
+       msg->r.SearchRequest.attributesonly = 0;
+       msg->r.SearchRequest.tree = tree;
+       
+       for (n = 0; attrs && attrs[n]; n++) /* noop */ ;
+       msg->r.SearchRequest.num_attributes = n;
+       msg->r.SearchRequest.attributes = discard_const(attrs);
+       msg->controls = control_req;
 
-       (*res) = talloc(ildb, struct ldb_result);
-       if (! *res) {
-               return LDB_ERR_OTHER;
+       return ildb_request_send(module, msg, context, callback, timeout, handle);
+}
+
+struct ildb_sync_context {
+       struct ldb_result *res;
+       int status;
+       int done;
+};
+
+static int ildb_search_sync_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
+{
+       struct ldb_result *res;
+       int n;
+       
+       if (!context) {
+               ldb_set_errstring(ldb->modules, talloc_asprintf(ldb, "NULL Context in callback"));
+               return LDB_ERR_OPERATIONS_ERROR;
+       }       
+
+       res = *((struct ldb_result **)context);
+
+       if (!res || !ares) {
+               goto error;
        }
-       (*res)->count = 0;
-       (*res)->msgs = NULL;
-       (*res)->controls = NULL;
 
-       status = ildap_search_bytree(ildb->ldap, search_base, scope, tree, attrs, 0,
-                                    (struct ldap_Control **)control_req,
-                                    &controls,
-                                    &ldapres);
-       talloc_free(search_base);
-       if (!NT_STATUS_IS_OK(status)) {
-               ildb_map_error(ildb, status);
-               return LDB_ERR_OTHER;
+       if (ares->type == LDB_REPLY_ENTRY) {
+               res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
+               if (! res->msgs) {
+                       goto error;
+               }
+
+               res->msgs[res->count + 1] = NULL;
+
+               res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
+               if (! res->msgs[res->count]) {
+                       goto error;
+               }
+
+               res->count++;
        }
 
-       count = ildap_count_entries(ildb->ldap, ldapres);
-       if (count == -1) {
-               talloc_free(ldapres);
-               return LDB_ERR_OTHER;
+       if (ares->type == LDB_REPLY_REFERRAL) {
+               if (res->refs) {
+                       for (n = 0; res->refs[n]; n++) /*noop*/ ;
+               } else {
+                       n = 0;
+               }
+
+               res->refs = talloc_realloc(res, res->refs, char *, n + 2);
+               if (! res->refs) {
+                       goto error;
+               }
+
+               res->refs[n] = talloc_steal(res->refs, ares->referral);
+               res->refs[n + 1] = NULL;
        }
 
-       if (count == 0) {
-               talloc_free(ldapres);
-               return LDB_SUCCESS;
+       if (ares->type == LDB_REPLY_DONE) {
+               if (ares->controls) {
+                       res->controls = talloc_steal(res, ares->controls);
+                       if (! res->controls) {
+                               goto error;
+                       }
+               }
        }
 
-       (*res)->msgs = talloc_array(*res, struct ldb_message *, count + 1);
-       if (! (*res)->msgs) {
-               talloc_free(ldapres);
-               return LDB_ERR_OTHER;
+       talloc_free(ares);
+       return LDB_SUCCESS;
+
+error:
+       talloc_free(ares);
+       talloc_free(res);
+       *((struct ldb_result **)context) = NULL;
+       return LDB_ERR_OPERATIONS_ERROR;
+}
+
+/*
+  search for matching records using a synchronous function
+ */
+static int ildb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
+                             enum ldb_scope scope, struct ldb_parse_tree *tree,
+                             const char * const *attrs,
+                             struct ldb_control **control_req,
+                             struct ldb_result **res)
+{
+       struct ildb_private *ildb = module->private_data;
+       struct ldb_async_handle *handle;
+       int ret;
+
+       *res = talloc_zero(ildb, struct ldb_result);
+       if (! *res) {
+               return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       (*res)->msgs[0] = NULL;
+       ret = ildb_search_async(module, base, scope, tree, attrs, control_req,
+                               res, &ildb_search_sync_callback, ildb->ldap->timeout, &handle);
 
-       /* loop over all messages */
-       for (i=0;i<count;i++) {
-               struct ldap_SearchResEntry *search;
+       if (ret != LDB_SUCCESS)
+               return ret;
 
-               msg = ldapres[i];
-               search = &msg->r.SearchResultEntry;
+       return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+}
 
-               (*res)->msgs[i] = talloc((*res)->msgs, struct ldb_message);
-               if (!(*res)->msgs[i]) {
-                       goto failed;
-               }
-               (*res)->msgs[i+1] = NULL;
+/*
+  add a record
+*/
+static int ildb_add_async(struct ldb_module *module, const struct ldb_message *ldb_msg,
+                         void *context,
+                         int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+                         int timeout,
+                         struct ldb_async_handle **handle)
+{
+       struct ildb_private *ildb = module->private_data;
+       struct ldap_message *msg;
+       struct ldap_mod **mods;
+       int i,n;
 
-               (*res)->msgs[i]->dn = ldb_dn_explode_or_special((*res)->msgs[i], search->dn);
-               if ((*res)->msgs[i]->dn == NULL) {
-                       goto failed;
-               }
-               (*res)->msgs[i]->num_elements = search->num_attributes;
-               (*res)->msgs[i]->elements = talloc_steal((*res)->msgs[i], search->attributes);
-               (*res)->msgs[i]->private_data = NULL;
+       *handle = NULL;
+
+       /* ignore ltdb specials */
+       if (ldb_dn_is_special(ldb_msg->dn)) {
+               return LDB_SUCCESS;
        }
 
-       talloc_free(ldapres);
+       msg = new_ldap_message(ildb->ldap);
+       if (msg == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
-       (*res)->count = count;
+       msg->type = LDAP_TAG_AddRequest;
 
-       if (controls) {
-               (*res)->controls = (struct ldb_control **)talloc_steal(*res, controls);
+       msg->r.AddRequest.dn = ldb_dn_linearize(msg, ldb_msg->dn);
+       if (msg->r.AddRequest.dn == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_INVALID_DN_SYNTAX;
        }
 
-       return LDB_SUCCESS;
+       mods = ildb_msg_to_mods(msg, &n, ldb_msg, 0);
+       if (mods == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
-failed:
-       if (*res) talloc_free(*res);
-       return LDB_ERR_OTHER;
+       msg->r.AddRequest.num_attributes = n;
+       msg->r.AddRequest.attributes = talloc_array(msg, struct ldb_message_element, n);
+       if (msg->r.AddRequest.attributes == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       for (i = 0; i < n; i++) {
+               msg->r.AddRequest.attributes[i] = mods[i]->attrib;
+       }
+
+       return ildb_request_send(module, msg, context, callback, timeout, handle);
 }
 
+static int ildb_add(struct ldb_module *module, const struct ldb_message *msg)
+{
+       struct ildb_private *ildb = module->private_data;
+       struct ldb_async_handle *handle;
+       int ret;
+
+       ret = ildb_add_async(module, msg,
+                               NULL, NULL, ildb->ldap->timeout, &handle);
+
+       if (ret != LDB_SUCCESS)
+               return ret;
+
+       return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+}
 
 /*
-  convert a ldb_message structure to a list of ldap_mod structures
-  ready for ildap_add() or ildap_modify()
+  modify a record
 */
-static struct ldap_mod **ildb_msg_to_mods(struct ldb_context *ldb,
-                                         const struct ldb_message *msg, int use_flags)
+static int ildb_modify_async(struct ldb_module *module, const struct ldb_message *ldb_msg,
+                            void *context,
+                            int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+                            int timeout,
+                            struct ldb_async_handle **handle)
 {
+       struct ildb_private *ildb = module->private_data;
+       struct ldap_message *msg;
        struct ldap_mod **mods;
-       unsigned int i;
-       int num_mods = 0;
+       int i,n;
 
-       /* allocate maximum number of elements needed */
-       mods = talloc_array(ldb, struct ldap_mod *, msg->num_elements+1);
-       if (!mods) {
-               errno = ENOMEM;
-               return NULL;
+       *handle = NULL;
+
+       /* ignore ltdb specials */
+       if (ldb_dn_is_special(ldb_msg->dn)) {
+               return LDB_SUCCESS;
        }
-       mods[0] = NULL;
 
-       for (i=0;i<msg->num_elements;i++) {
-               const struct ldb_message_element *el = &msg->elements[i];
+       msg = new_ldap_message(ildb->ldap);
+       if (msg == NULL) {
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
-               mods[num_mods] = talloc(ldb, struct ldap_mod);
-               if (!mods[num_mods]) {
-                       goto failed;
-               }
-               mods[num_mods+1] = NULL;
-               mods[num_mods]->type = 0;
-               mods[num_mods]->attrib = *el;
-               if (use_flags) {
-                       switch (el->flags & LDB_FLAG_MOD_MASK) {
-                       case LDB_FLAG_MOD_ADD:
-                               mods[num_mods]->type = LDAP_MODIFY_ADD;
-                               break;
-                       case LDB_FLAG_MOD_DELETE:
-                               mods[num_mods]->type = LDAP_MODIFY_DELETE;
-                               break;
-                       case LDB_FLAG_MOD_REPLACE:
-                               mods[num_mods]->type = LDAP_MODIFY_REPLACE;
-                               break;
-                       }
-               }
-               num_mods++;
+       msg->type = LDAP_TAG_ModifyRequest;
+
+       msg->r.ModifyRequest.dn = ldb_dn_linearize(msg, ldb_msg->dn);
+       if (msg->r.ModifyRequest.dn == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_INVALID_DN_SYNTAX;
        }
 
-       return mods;
+       mods = ildb_msg_to_mods(msg, &n, ldb_msg, 1);
+       if (mods == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
-failed:
-       talloc_free(mods);
-       return NULL;
+       msg->r.ModifyRequest.num_mods = n;
+       msg->r.ModifyRequest.mods = talloc_array(msg, struct ldap_mod, n);
+       if (msg->r.ModifyRequest.mods == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+
+       for (i = 0; i < n; i++) {
+               msg->r.ModifyRequest.mods[i] = *mods[i];
+       }
+
+       return ildb_request_send(module, msg, context, callback, timeout, handle);
 }
 
+static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg)
+{
+       struct ildb_private *ildb = module->private_data;
+       struct ldb_async_handle *handle;
+       int ret;
+
+       ret = ildb_modify_async(module, msg,
+                               NULL, NULL, ildb->ldap->timeout, &handle);
+
+       if (ret != LDB_SUCCESS)
+               return ret;
+
+       return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+}
 
 /*
-  add a record
+  delete a record
 */
-static int ildb_add(struct ldb_module *module, const struct ldb_message *msg)
+static int ildb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
+                            void *context,
+                            int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+                            int timeout,
+                            struct ldb_async_handle **handle)
 {
-       struct ldb_context *ldb = module->ldb;
        struct ildb_private *ildb = module->private_data;
-       struct ldap_mod **mods;
-       char *dn;
-       int ret = 0;
-       NTSTATUS status;
+       struct ldap_message *msg;
+
+       *handle = NULL;
 
        /* ignore ltdb specials */
-       if (ldb_dn_is_special(msg->dn)) {
+       if (ldb_dn_is_special(dn)) {
                return LDB_SUCCESS;
        }
 
-       mods = ildb_msg_to_mods(ldb, msg, 0);
-       if (mods == NULL) {
+       msg = new_ldap_message(ildb->ldap);
+       if (msg == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       dn = ldb_dn_linearize(mods, msg->dn);
-       if (dn == NULL) {
-               talloc_free(mods);
+       msg->type = LDAP_TAG_DelRequest;
+       
+       msg->r.DelRequest.dn = ldb_dn_linearize(msg, dn);
+       if (msg->r.DelRequest.dn == NULL) {
+               talloc_free(msg);
                return LDB_ERR_INVALID_DN_SYNTAX;
        }
 
-       status = ildap_add(ildb->ldap, dn, mods);
-       ret = ildb_map_error(ildb, status);
+       return ildb_request_send(module, msg, context, callback, timeout, handle);
+}
 
-       talloc_free(mods);
+static int ildb_delete(struct ldb_module *module, const struct ldb_dn *dn)
+{
+       struct ildb_private *ildb = module->private_data;
+       struct ldb_async_handle *handle;
+       int ret;
 
-       return ret;
-}
+       ret = ildb_delete_async(module, dn,
+                               NULL, NULL, ildb->ldap->timeout, &handle);
 
+       if (ret != LDB_SUCCESS)
+               return ret;
+
+       return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
+}
 
 /*
-  modify a record
+  rename a record
 */
-static int ildb_modify(struct ldb_module *module, const struct ldb_message *msg)
+static int ildb_rename_async(struct ldb_module *module,
+                            const struct ldb_dn *olddn, const struct ldb_dn *newdn,
+                            void *context,
+                            int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
+                            int timeout,
+                            struct ldb_async_handle **handle)
 {
-       struct ldb_context *ldb = module->ldb;
        struct ildb_private *ildb = module->private_data;
-       struct ldap_mod **mods;
-       char *dn;
-       int ret = 0;
-       NTSTATUS status;
+       struct ldap_message *msg;
+
+       *handle = NULL;
 
        /* ignore ltdb specials */
-       if (ldb_dn_is_special(msg->dn)) {
+       if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
                return LDB_SUCCESS;
        }
 
-       mods = ildb_msg_to_mods(ldb, msg, 1);
-       if (mods == NULL) {
+       msg = new_ldap_message(ildb->ldap);
+       if (msg == NULL) {
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
-       dn = ldb_dn_linearize(mods, msg->dn);
-       if (dn == NULL) {
-               talloc_free(mods);
+       msg->type = LDAP_TAG_ModifyDNRequest;
+       msg->r.ModifyDNRequest.dn = ldb_dn_linearize(msg, olddn);
+       if (msg->r.ModifyDNRequest.dn == NULL) {
+               talloc_free(msg);
                return LDB_ERR_INVALID_DN_SYNTAX;
        }
 
-       status = ildap_modify(ildb->ldap, dn, mods);
-       ret = ildb_map_error(ildb, status);
+       msg->r.ModifyDNRequest.newrdn = 
+               talloc_asprintf(msg, "%s=%s",
+                               newdn->components[0].name,
+                               ldb_dn_escape_value(msg, newdn->components[0].value));
+       if (msg->r.ModifyDNRequest.newrdn == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
 
-       talloc_free(mods);
+       msg->r.ModifyDNRequest.newsuperior =
+               ldb_dn_linearize(msg,
+                                ldb_dn_get_parent(msg, newdn));
+       if (msg->r.ModifyDNRequest.newsuperior == NULL) {
+               talloc_free(msg);
+               return LDB_ERR_INVALID_DN_SYNTAX;
+       }
+
+       msg->r.ModifyDNRequest.deleteolddn = True;
+
+       return ildb_request_send(module, msg, context, callback, timeout, handle);
+}
+
+static int ildb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
+{
+       struct ildb_private *ildb = module->private_data;
+       struct ldb_async_handle *handle;
+       int ret;
+
+       ret = ildb_rename_async(module, olddn, newdn,
+                               NULL, NULL, ildb->ldap->timeout, &handle);
 
-       return ret;
+       if (ret != LDB_SUCCESS)
+               return ret;
+
+       return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
 }
 
 static int ildb_start_trans(struct ldb_module *module)
@@ -434,14 +827,75 @@ static int ildb_request(struct ldb_module *module, struct ldb_request *req)
                                        req->op.rename.olddn,
                                        req->op.rename.newdn);
 
+       case LDB_ASYNC_SEARCH:
+               return ildb_search_async(module,
+                                       req->op.search.base,
+                                       req->op.search.scope, 
+                                       req->op.search.tree, 
+                                       req->op.search.attrs,
+                                       req->controls,
+                                       req->async.context,
+                                       req->async.callback,
+                                       req->async.timeout,
+                                       &req->async.handle);
+
+       case LDB_ASYNC_ADD:
+               return ildb_add_async(module,
+                                       req->op.add.message,
+                                       req->async.context,
+                                       req->async.callback,
+                                       req->async.timeout,
+                                       &req->async.handle);
+
+       case LDB_ASYNC_MODIFY:
+               return ildb_modify_async(module,
+                                       req->op.mod.message,
+                                       req->async.context,
+                                       req->async.callback,
+                                       req->async.timeout,
+                                       &req->async.handle);
+
+       case LDB_ASYNC_DELETE:
+               return ildb_delete_async(module,
+                                       req->op.del.dn,
+                                       req->async.context,
+                                       req->async.callback,
+                                       req->async.timeout,
+                                       &req->async.handle);
+
+       case LDB_ASYNC_RENAME:
+               return ildb_rename_async(module,
+                                       req->op.rename.olddn,
+                                       req->op.rename.newdn,
+                                       req->async.context,
+                                       req->async.callback,
+                                       req->async.timeout,
+                                       &req->async.handle);
+
        default:
                return -1;
 
        }
 }
 
+/*
+  fetch the rootDSE for later use
+*/
 static int ildb_init_2(struct ldb_module *module)
 {
+       struct ildb_private *ildb = module->private_data;
+       struct ldb_result *res = NULL;
+       struct ldb_dn *empty_dn = ldb_dn_new(ildb);
+       int ret;
+       ret = ildb_search_bytree(module, empty_dn, LDB_SCOPE_BASE, 
+                                ldb_parse_tree(empty_dn, "dn=dc=rootDSE"), 
+                                NULL, NULL, &res);
+       if (ret == LDB_SUCCESS && res->count == 1) {
+               ildb->rootDSE = talloc_steal(ildb, res->msgs[0]);
+       }
+       if (ret == LDB_SUCCESS) talloc_free(res);
+       talloc_free(empty_dn);
+
        return LDB_SUCCESS;
 }
 
@@ -455,25 +909,33 @@ static const struct ldb_module_ops ildb_ops = {
 };
 
 
-/*
-  fetch the rootDSE
-*/
-static void ildb_rootdse(struct ldb_module *module)
+static int ildb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
 {
-       struct ildb_private *ildb = module->private_data;
-       struct ldb_result *res = NULL;
-       struct ldb_dn *empty_dn = ldb_dn_new(ildb);
-       int ret;
-       ret = ildb_search_bytree(module, empty_dn, LDB_SCOPE_BASE, 
-                                ldb_parse_tree(empty_dn, "dn=dc=rootDSE"), 
-                                NULL, NULL, &res);
-       if (ret == LDB_SUCCESS && res->count == 1) {
-               ildb->rootDSE = talloc_steal(ildb, res->msgs[0]);
+       struct ildb_async_context *ac = talloc_get_type(handle->private_data, struct ildb_async_context);
+
+       if (!ac) {
+               return LDB_ERR_OPERATIONS_ERROR;
        }
-       if (ret == LDB_SUCCESS) talloc_free(res);
-       talloc_free(empty_dn);
-}
 
+       switch(type) {
+       case LDB_WAIT_NONE:
+               if (event_loop_once(ac->req->conn->event.event_ctx) != 0) {
+                       return LDB_ERR_OTHER;
+               }
+               break;
+       case LDB_WAIT_ALL:
+               while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) {
+                       if (event_loop_once(ac->req->conn->event.event_ctx) != 0) {
+                               return LDB_ERR_OTHER;
+                       }
+               }
+               break;
+       default:
+               return LDB_ERR_OPERATIONS_ERROR;
+       }
+       
+       return handle->status;
+}
 
 /*
   connect to the database
@@ -546,6 +1008,8 @@ int ildb_connect(struct ldb_context *ldb, const char *url,
                }
        }
 
+       ldb->async_wait = &ildb_async_wait;
+
        return 0;
 
 failed:
index 3e24093118e1973ff75a1865c4c0021f881b842d..48d849746fe2479f8d0f5955d6a4d33e7d12f4da 100644 (file)
@@ -964,6 +964,7 @@ static int lsqlite3_search_bytree(struct ldb_module * module, const struct ldb_d
 
        (*res)->msgs = talloc_steal(*res, msgs.msgs);
        (*res)->count = msgs.count;
+       (*res)->refs = NULL;
        (*res)->controls = NULL;
 
        talloc_free(local_ctx);
index 5c601f9ea8a1ef20339a9d79024a38b9196d34e6..b1b82d03606f4b2db615064cae586e188c9605f2 100644 (file)
@@ -709,6 +709,7 @@ int ltdb_search_indexed(struct ldb_module *module,
        }
        (*res)->count = 0;
        (*res)->msgs = NULL;
+       (*res)->refs = NULL;
        (*res)->controls = NULL;
 
        if (scope == LDB_SCOPE_BASE) {
index e43125d588351c0ddf8be03752b0d02c6a048025..d468f02e77fc2403986c2af1708bcff55f58b04b 100644 (file)
@@ -441,6 +441,7 @@ static int ltdb_search_full(struct ldb_module *module,
        }
 
        result->controls = NULL;
+       result->refs = NULL;
        result->msgs = talloc_steal(result, sinfo->msgs);
        result->count = sinfo->count;
        *res = result;
index 24005c450cff9d610c6a860f6bbc956a91f8cd80..a67c41e67f7522f56233fa9b2a1b36923cfe3d51 100644 (file)
@@ -596,10 +596,6 @@ int handle_controls_reply(struct ldb_control **reply, struct ldb_control **reque
                        cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len);
                        printf("# DIRSYNC cookie returned was:\n# %s\n", cookie);
 
-                       sleep(120);
-                       
-                       ret = 1;
-
                        continue;
                }
 
index b4120c0dce0c3575434823df533b9684831c2679..c380862c5d6da3cd3b0199e98d355d66bc8b97b3 100644 (file)
@@ -64,9 +64,10 @@ static int do_search(struct ldb_context *ldb,
                     const char *expression,
                     const char * const *attrs)
 {
-       int ret, i;
+       int ret, i, n;
        int loop = 0;
        int total = 0;
+       int refs = 0;
        struct ldb_request req;
        struct ldb_result *result = NULL;
 
@@ -94,7 +95,6 @@ static int do_search(struct ldb_context *ldb,
                }
 
                result = req.op.search.res;
-               printf("# returned %d records\n", result->count);
 
                if (options->sorted) {
                        ldb_qsort(result->msgs, result->count, sizeof(struct ldb_message *),
@@ -120,6 +120,12 @@ static int do_search(struct ldb_context *ldb,
                        ldb_ldif_write_file(ldb, stdout, &ldif);
                }
 
+               if (result->refs) {
+                       for(n = 0;result->refs[n]; n++, refs++) {
+                               printf("# referral %d\nref: %s\n\n", refs + 1, result->refs[n]);
+                       }
+               }
+               
                if (result->controls) {
                        if (handle_controls_reply(result->controls, req.controls) == 1)
                                loop = 1;
@@ -137,6 +143,8 @@ static int do_search(struct ldb_context *ldb,
                
        } while(loop);
 
+       printf("# returned %d records\n# %d entries\n# %d referrals\n", total + refs, total, refs);
+
        return 0;
 }
 
index 55f1361e163bd1dc572eb43bba9b26090acd1274..42cad3a63edb78936108682fa1c04b316bdf7e43 100644 (file)
@@ -1309,19 +1309,19 @@ BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
 
        if (asn1_peek_tag(data, ASN1_CONTEXT(0))) {
                int i;
-               struct ldap_Control **ctrl = NULL;
+               struct ldb_control **ctrl = NULL;
 
                asn1_start_tag(data, ASN1_CONTEXT(0));
 
                for (i=0; asn1_peek_tag(data, ASN1_SEQUENCE(0)); i++) {
                        /* asn1_start_tag(data, ASN1_SEQUENCE(0)); */
 
-                       ctrl = talloc_realloc(msg, ctrl, struct ldap_Control *, i+2);
+                       ctrl = talloc_realloc(msg, ctrl, struct ldb_control *, i+2);
                        if (!ctrl) {
                                return False;
                        }
 
-                       ctrl[i] = talloc(ctrl, struct ldap_Control);
+                       ctrl[i] = talloc(ctrl, struct ldb_control);
                        if (!ctrl[i]) {
                                return False;
                        }
@@ -1348,7 +1348,7 @@ BOOL ldap_decode(struct asn1_data *data, struct ldap_message *msg)
   return NT_STATUS_OK if a blob has enough bytes in it to be a full
   ldap packet. Set packet_size if true.
 */
-NTSTATUS ldap_full_packet(void *private, DATA_BLOB blob, size_t *packet_size)
+NTSTATUS ldap_full_packet(void *private_data, DATA_BLOB blob, size_t *packet_size)
 {
        return asn1_full_tag(blob, ASN1_SEQUENCE(0), packet_size);
 }
index de284d23d1583b63df9138a7962c1adbb2a63ab8..1deabf0b10221b97a2cb3463ff90abfd2a6a873a 100644 (file)
@@ -240,17 +240,11 @@ union ldap_Request {
        struct ldap_ExtendedResponse    ExtendedResponse;
 };
 
-struct ldap_Control {
-       const char *oid;
-       BOOL        critical;
-       void       *value;
-};
-
 struct ldap_message {
        int                     messageid;
        enum ldap_request_tag   type;
        union ldap_Request      r;
-       struct ldap_Control    **controls;
+       struct ldb_control    **controls;
 };
 
 #include "libcli/ldap/ldap_proto.h"
index 9103e939e706d95b81b3e2f40f2856989d5f9991..364961cf47010c5a2dd212b982211bb270b3be3b 100644 (file)
@@ -90,9 +90,9 @@ static void ldap_connection_dead(struct ldap_connection *conn)
 /*
   handle packet errors
 */
-static void ldap_error_handler(void *private, NTSTATUS status)
+static void ldap_error_handler(void *private_data, NTSTATUS status)
 {
-       struct ldap_connection *conn = talloc_get_type(private, 
+       struct ldap_connection *conn = talloc_get_type(private_data
                                                       struct ldap_connection);
        ldap_connection_dead(conn);
 }
@@ -155,14 +155,14 @@ static void ldap_match_message(struct ldap_connection *conn, struct ldap_message
   check if a blob is a complete ldap packet
   handle wrapper or unwrapped connections
 */
-NTSTATUS ldap_complete_packet(void *private, DATA_BLOB blob, size_t *size)
+NTSTATUS ldap_complete_packet(void *private_data, DATA_BLOB blob, size_t *size)
 {
-       struct ldap_connection *conn = talloc_get_type(private
+       struct ldap_connection *conn = talloc_get_type(private_data,
                                                       struct ldap_connection);
        if (conn->enable_wrap) {
-               return packet_full_request_u32(private, blob, size);
+               return packet_full_request_u32(private_data, blob, size);
        }
-       return ldap_full_packet(private, blob, size);
+       return ldap_full_packet(private_data, blob, size);
 }
 
 /*
@@ -234,9 +234,9 @@ static NTSTATUS ldap_decode_wrapped(struct ldap_connection *conn, DATA_BLOB blob
 /*
   handle ldap recv events
 */
-static NTSTATUS ldap_recv_handler(void *private, DATA_BLOB blob)
+static NTSTATUS ldap_recv_handler(void *private_data, DATA_BLOB blob)
 {
-       struct ldap_connection *conn = talloc_get_type(private, 
+       struct ldap_connection *conn = talloc_get_type(private_data
                                                       struct ldap_connection);
        if (conn->enable_wrap) {
                return ldap_decode_wrapped(conn, blob);
@@ -250,9 +250,9 @@ static NTSTATUS ldap_recv_handler(void *private, DATA_BLOB blob)
   handle ldap socket events
 */
 static void ldap_io_handler(struct event_context *ev, struct fd_event *fde, 
-                           uint16_t flags, void *private)
+                           uint16_t flags, void *private_data)
 {
-       struct ldap_connection *conn = talloc_get_type(private, 
+       struct ldap_connection *conn = talloc_get_type(private_data
                                                       struct ldap_connection);
        if (flags & EVENT_FD_WRITE) {
                packet_queue_run(conn->packet);
@@ -433,9 +433,9 @@ static int ldap_request_destructor(void *ptr)
   called on timeout of a ldap request
 */
 static void ldap_request_timeout(struct event_context *ev, struct timed_event *te, 
-                                     struct timeval t, void *private)
+                                     struct timeval t, void *private_data)
 {
-       struct ldap_request *req = talloc_get_type(private, struct ldap_request);
+       struct ldap_request *req = talloc_get_type(private_data, struct ldap_request);
        req->status = NT_STATUS_IO_TIMEOUT;
        if (req->state == LDAP_REQUEST_PENDING) {
                DLIST_REMOVE(req->conn->pending, req);
@@ -451,9 +451,9 @@ static void ldap_request_timeout(struct event_context *ev, struct timed_event *t
   called on completion of a one-way ldap request
 */
 static void ldap_request_complete(struct event_context *ev, struct timed_event *te, 
-                                 struct timeval t, void *private)
+                                 struct timeval t, void *private_data)
 {
-       struct ldap_request *req = talloc_get_type(private, struct ldap_request);
+       struct ldap_request *req = talloc_get_type(private_data, struct ldap_request);
        if (req->async.fn) {
                req->async.fn(req);
        }
@@ -534,9 +534,9 @@ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
        DLIST_ADD(conn->pending, req);
 
        /* put a timeout on the request */
-       event_add_timed(conn->event.event_ctx, req, 
-                       timeval_current_ofs(conn->timeout, 0),
-                       ldap_request_timeout, req);
+       req->time_event = event_add_timed(conn->event.event_ctx, req, 
+                                         timeval_current_ofs(conn->timeout, 0),
+                                         ldap_request_timeout, req);
 
        return req;
 
index ee458dc5b076816230bda2e0258aded3c7567e65..3f71c42f226a90d45d356d22c4c1718affc436bc 100644 (file)
@@ -42,8 +42,10 @@ struct ldap_request {
        DATA_BLOB data;
        struct {
                void (*fn)(struct ldap_request *);
-               void *private;
+               void *private_data;
        } async;
+
+       struct timed_event *time_event;
 };
 
 
index 5bd46cf7a94feb40b76be719995162be1708ee5b..373b71d3709ea594e0897c838dd3a4e807f971e8 100644 (file)
@@ -381,10 +381,14 @@ static BOOL decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
                return False;
        }
 
-       if (asn1_peek_tag(&data, ASN1_SEQUENCE(0))) {
+       if (asn1_peek_tag(&data, ASN1_CONTEXT(0))) {
 
                lvrc->type = 0;
                
+               if (!asn1_start_tag(&data, ASN1_CONTEXT(0))) {
+                       return False;
+               }
+
                if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) {
                        return False;
                }
@@ -397,7 +401,11 @@ static BOOL decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
                        return False;
                }
 
-               if (!asn1_end_tag(&data)) {
+               if (!asn1_end_tag(&data)) { /*SEQUENCE*/
+                       return False;
+               }
+
+               if (!asn1_end_tag(&data)) { /*CONTEXT*/
                        return False;
                }
 
@@ -405,6 +413,10 @@ static BOOL decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
 
                lvrc->type = 1;
 
+               if (!asn1_start_tag(&data, ASN1_CONTEXT(1))) {
+                       return False;
+               }
+
                if (!asn1_read_OctetString(&data, &assertion_value)) {
                        return False;
                }
@@ -418,6 +430,10 @@ static BOOL decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out)
                } else {
                        lvrc->match.gtOrEq.value = NULL;
                }
+
+               if (!asn1_end_tag(&data)) { /*CONTEXT*/
+                       return False;
+               }
        }
 
        if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) {
@@ -755,6 +771,10 @@ static BOOL encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
        }
 
        if (lvrc->type == 0) {
+               if (!asn1_push_tag(&data, ASN1_CONTEXT(0))) {
+                       return False;
+               }
+               
                if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) {
                        return False;
                }
@@ -767,14 +787,25 @@ static BOOL encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out)
                        return False;
                }
 
-               if (!asn1_pop_tag(&data)) {
+               if (!asn1_pop_tag(&data)) { /*SEQUENCE*/
+                       return False;
+               }
+
+               if (!asn1_pop_tag(&data)) { /*CONTEXT*/
                        return False;
                }
        } else {
+               if (!asn1_push_tag(&data, ASN1_CONTEXT(1))) {
+                       return False;
+               }
                
                if (!asn1_write_OctetString(&data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) {
                        return False;
                }
+
+               if (!asn1_pop_tag(&data)) { /*CONTEXT*/
+                       return False;
+               }
        }
 
        if (lvrc->ctxid_len) {
@@ -850,7 +881,7 @@ struct control_handler ldap_known_controls[] = {
        { NULL, NULL, NULL }
 };
 
-BOOL ldap_decode_control(void *mem_ctx, struct asn1_data *data, struct ldap_Control *ctrl)
+BOOL ldap_decode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
 {
        int i;
        DATA_BLOB oid;
@@ -876,7 +907,7 @@ BOOL ldap_decode_control(void *mem_ctx, struct asn1_data *data, struct ldap_Cont
                ctrl->critical = False;
        }
 
-       ctrl->value = NULL;
+       ctrl->data = NULL;
 
        if (!asn1_peek_tag(data, ASN1_OCTET_STRING)) {
                goto end_tag;
@@ -888,7 +919,7 @@ BOOL ldap_decode_control(void *mem_ctx, struct asn1_data *data, struct ldap_Cont
 
        for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
                if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
-                       if (!ldap_known_controls[i].decode(mem_ctx, value, &ctrl->value)) {
+                       if (!ldap_known_controls[i].decode(mem_ctx, value, &ctrl->data)) {
                                return False;
                        }
                        break;
@@ -906,7 +937,7 @@ end_tag:
        return True;
 }
 
-BOOL ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldap_Control *ctrl)
+BOOL ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldb_control *ctrl)
 {
        DATA_BLOB value;
        int i;
@@ -925,13 +956,13 @@ BOOL ldap_encode_control(void *mem_ctx, struct asn1_data *data, struct ldap_Cont
                }
        }
 
-       if (!ctrl->value) {
+       if (!ctrl->data) {
                goto pop_tag;
        }
 
        for (i = 0; ldap_known_controls[i].oid != NULL; i++) {
                if (strcmp(ldap_known_controls[i].oid, ctrl->oid) == 0) {
-                       if (!ldap_known_controls[i].encode(mem_ctx, ctrl->value, &value)) {
+                       if (!ldap_known_controls[i].encode(mem_ctx, ctrl->data, &value)) {
                                return False;
                        }
                        break;
index a5227ec37f58d812c1317617fff0b9a00dc81620..f26fb7db78c33e2f64e03ac1a2d3c0396622f92e 100644 (file)
@@ -152,13 +152,13 @@ int ildap_count_entries(struct ldap_connection *conn, struct ldap_message **res)
 
 
 /*
-  perform a ldap search
+  perform a synchronous ldap search
 */
 NTSTATUS ildap_search_bytree(struct ldap_connection *conn, const char *basedn, 
                             int scope, struct ldb_parse_tree *tree,
                             const char * const *attrs, BOOL attributesonly, 
-                            struct ldap_Control **control_req,
-                            struct ldap_Control ***control_res,
+                            struct ldb_control **control_req,
+                            struct ldb_control ***control_res,
                             struct ldap_message ***results)
 {
        struct ldap_message *msg;
@@ -203,7 +203,9 @@ NTSTATUS ildap_search_bytree(struct ldap_connection *conn, const char *basedn,
                        break;
                }
 
-               if (res->type != LDAP_TAG_SearchResultEntry) continue;
+               if (res->type != LDAP_TAG_SearchResultEntry &&
+                   res->type != LDAP_TAG_SearchResultReference)
+                       continue;
                
                (*results) = talloc_realloc(conn, *results, struct ldap_message *, n+2);
                if (*results == NULL) {
@@ -228,8 +230,8 @@ NTSTATUS ildap_search_bytree(struct ldap_connection *conn, const char *basedn,
 NTSTATUS ildap_search(struct ldap_connection *conn, const char *basedn, 
                      int scope, const char *expression, 
                      const char * const *attrs, BOOL attributesonly, 
-                     struct ldap_Control **control_req,
-                     struct ldap_Control ***control_res,
+                     struct ldb_control **control_req,
+                     struct ldb_control ***control_res,
                      struct ldap_message ***results)
 {
        struct ldb_parse_tree *tree = ldb_parse_tree(conn, expression);