+static int asq_search_continue(struct ldb_handle *h)
+{
+ struct asq_context *ac;
+ int ret;
+
+ ac = talloc_get_type(h->private_data, struct asq_context);
+
+ switch (ac->step) {
+ case ASQ_INIT:
+ /* check the search is well formed */
+ if (ac->orig_req->op.search.scope != LDB_SCOPE_BASE) {
+ ac->asq_ret = ASQ_CTRL_UNWILLING_TO_PERFORM;
+ return asq_terminate(h);
+ }
+
+ ac->req_attrs = ac->orig_req->op.search.attrs;
+ ac->req_attribute = talloc_strdup(ac, ac->asq_ctrl->source_attribute);
+ if (ac->req_attribute == NULL)
+ return LDB_ERR_OPERATIONS_ERROR;
+
+ /* get the object to retrieve the DNs to search */
+ ret = asq_build_first_request(ac);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ac->step = ASQ_SEARCH_BASE;
+
+ return ldb_request(ac->module->ldb, ac->base_req);
+
+ case ASQ_SEARCH_BASE:
+
+ /* build up the requests call chain */
+ ret = asq_build_multiple_requests(ac, h);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ if (h->state == LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ ac->step = ASQ_SEARCH_MULTI;
+
+ /* no break nor return,
+ * the set of requests is performed in ASQ_SEARCH_MULTI
+ */
+ /* fall through */
+
+ case ASQ_SEARCH_MULTI:
+
+ if (ac->cur_req >= ac->num_reqs) {
+ return asq_terminate(h);
+ }
+
+ return ldb_request(ac->module->ldb, ac->reqs[ac->cur_req]);
+
+ default:
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ break;
+ }
+
+ /* this is reached only in case of error */
+ /* FIXME: fire an async reply ? */
+ h->status = ret;
+ h->state = LDB_ASYNC_DONE;
+ return ret;
+}
+
+static int asq_search(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_control *control;
+ struct asq_context *ac;
+ struct ldb_handle *h;
+
+ /* check if there's a paged request control */
+ control = get_control_from_list(req->controls, LDB_CONTROL_ASQ_OID);
+ if (control == NULL) {
+ /* not found go on */
+ return ldb_next_request(module, req);
+ }
+
+ req->handle = NULL;
+
+ if (!req->callback || !req->context) {
+ ldb_set_errstring(module->ldb,
+ "Async interface called with NULL callback function or NULL context");
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ h = init_handle(req, module);
+ if (!h) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ac = talloc_get_type(h->private_data, struct asq_context);
+
+ ac->asq_ctrl = talloc_get_type(control->data, struct ldb_asq_control);
+ if (!ac->asq_ctrl) {
+ return LDB_ERR_PROTOCOL_ERROR;
+ }
+
+ req->handle = h;
+
+ return asq_search_continue(h);
+}
+