4 Copyright (C) Andrew Tridgell 2004
5 Copyright (C) Simo Sorce 2006
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * Component: ldb ldap backend
31 * Description: core files for LDAP backend
33 * Author: Andrew Tridgell
37 * - description: make the module use asyncronous calls
43 #include "ldb/include/includes.h"
52 struct lldb_async_context {
53 struct ldb_module *module;
57 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *);
60 static int lldb_ldap_to_ldb(int err) {
61 /* Ldap errors and ldb errors are defined to the same values */
65 static struct ldb_async_handle *init_handle(struct lldb_private *lldb, struct ldb_module *module,
67 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
70 struct lldb_async_context *ac;
71 struct ldb_async_handle *h;
73 h = talloc_zero(lldb, struct ldb_async_handle);
75 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
79 ac = talloc(h, struct lldb_async_context);
81 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
86 h->private_data = (void *)ac;
89 ac->context = context;
90 ac->callback = callback;
91 ac->timeout = timeout;
97 convert a ldb_message structure to a list of LDAPMod structures
98 ready for ldap_add() or ldap_modify()
100 static LDAPMod **lldb_msg_to_mods(void *mem_ctx, const struct ldb_message *msg, int use_flags)
106 /* allocate maximum number of elements needed */
107 mods = talloc_array(mem_ctx, LDAPMod *, msg->num_elements+1);
114 for (i=0;i<msg->num_elements;i++) {
115 const struct ldb_message_element *el = &msg->elements[i];
117 mods[num_mods] = talloc(mods, LDAPMod);
118 if (!mods[num_mods]) {
121 mods[num_mods+1] = NULL;
122 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
124 switch (el->flags & LDB_FLAG_MOD_MASK) {
125 case LDB_FLAG_MOD_ADD:
126 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
128 case LDB_FLAG_MOD_DELETE:
129 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
131 case LDB_FLAG_MOD_REPLACE:
132 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
136 mods[num_mods]->mod_type = discard_const_p(char, el->name);
137 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods],
140 if (!mods[num_mods]->mod_vals.modv_bvals) {
144 for (j=0;j<el->num_values;j++) {
145 mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
147 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
150 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
151 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
153 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
165 add a single set of ldap message values to a ldb_message
167 static int lldb_add_msg_attr(struct ldb_context *ldb,
168 struct ldb_message *msg,
169 const char *attr, struct berval **bval)
172 struct ldb_message_element *el;
174 count = ldap_count_values_len(bval);
180 el = talloc_realloc(msg, msg->elements, struct ldb_message_element,
181 msg->num_elements + 1);
189 el = &msg->elements[msg->num_elements];
191 el->name = talloc_strdup(msg->elements, attr);
199 el->values = talloc_array(msg->elements, struct ldb_val, count);
205 for (i=0;i<count;i++) {
206 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
207 if (!el->values[i].data) {
210 el->values[i].length = bval[i]->bv_len;
220 search for matching records
222 static int lldb_search_async(struct ldb_module *module, const struct ldb_dn *base,
223 enum ldb_scope scope, struct ldb_parse_tree *tree,
224 const char * const *attrs,
225 struct ldb_control **control_req,
227 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
229 struct ldb_async_handle **handle)
231 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
232 struct lldb_async_context *lldb_ac;
239 if (!callback || !context) {
240 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Async interface called with NULL callback function or NULL context"));
241 return LDB_ERR_OPERATIONS_ERROR;
245 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Invalid expression parse tree"));
246 return LDB_ERR_OPERATIONS_ERROR;
249 if (control_req != NULL) {
250 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");
253 *handle = init_handle(lldb, module, context, callback, timeout);
254 if (*handle == NULL) {
255 talloc_free(*handle);
256 return LDB_ERR_OPERATIONS_ERROR;
259 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
261 search_base = ldb_dn_linearize(lldb_ac, base);
263 search_base = talloc_strdup(lldb_ac, "");
265 if (search_base == NULL) {
266 talloc_free(*handle);
267 return LDB_ERR_OPERATIONS_ERROR;
270 expression = ldb_filter_from_tree(lldb_ac, tree);
271 if (expression == NULL) {
272 talloc_free(*handle);
273 return LDB_ERR_OPERATIONS_ERROR;
278 ldap_scope = LDAP_SCOPE_BASE;
280 case LDB_SCOPE_ONELEVEL:
281 ldap_scope = LDAP_SCOPE_ONELEVEL;
284 ldap_scope = LDAP_SCOPE_SUBTREE;
291 ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope,
293 discard_const_p(char *, attrs),
301 if (ret != LDAP_SUCCESS) {
302 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
303 talloc_free(*handle);
307 return lldb_ldap_to_ldb(ret);
310 static int lldb_search_sync_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
312 struct ldb_result *res;
316 ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context in callback"));
317 return LDB_ERR_OPERATIONS_ERROR;
320 res = *((struct ldb_result **)context);
326 if (ares->type == LDB_REPLY_ENTRY) {
327 res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
332 res->msgs[res->count + 1] = NULL;
334 res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
335 if (! res->msgs[res->count]) {
342 if (ares->type == LDB_REPLY_REFERRAL) {
344 for (n = 0; res->refs[n]; n++) /*noop*/ ;
349 res->refs = talloc_realloc(res, res->refs, char *, n + 2);
354 res->refs[n] = talloc_steal(res->refs, ares->referral);
355 res->refs[n + 1] = NULL;
358 if (ares->type == LDB_REPLY_DONE) {
359 if (ares->controls) {
360 res->controls = talloc_steal(res, ares->controls);
361 if (! res->controls) {
373 *((struct ldb_result **)context) = NULL;
374 return LDB_ERR_OPERATIONS_ERROR;
378 search for matching records using a synchronous function
380 static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
381 enum ldb_scope scope, struct ldb_parse_tree *tree,
382 const char * const *attrs,
383 struct ldb_control **control_req,
384 struct ldb_result **res)
386 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
387 struct ldb_async_handle *handle;
390 *res = talloc_zero(lldb, struct ldb_result);
392 return LDB_ERR_OPERATIONS_ERROR;
395 ret = lldb_search_async(module, base, scope, tree, attrs, control_req,
396 res, &lldb_search_sync_callback, lldb->timeout, &handle);
398 if (ret != LDB_SUCCESS)
401 return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
407 static int lldb_add_async(struct ldb_module *module, const struct ldb_message *msg,
409 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
411 struct ldb_async_handle **handle)
413 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
414 struct lldb_async_context *lldb_ac;
419 /* ltdb specials should not reach this point */
420 if (ldb_dn_is_special(msg->dn)) {
421 return LDB_ERR_INVALID_DN_SYNTAX;
424 *handle = init_handle(lldb, module, context, callback, timeout);
425 if (*handle == NULL) {
426 return LDB_ERR_OPERATIONS_ERROR;
429 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
431 mods = lldb_msg_to_mods(lldb_ac, msg, 0);
433 talloc_free(*handle);
434 return LDB_ERR_OPERATIONS_ERROR;
437 dn = ldb_dn_linearize(lldb_ac, msg->dn);
439 talloc_free(*handle);
440 return LDB_ERR_OPERATIONS_ERROR;
443 ret = ldap_add_ext(lldb->ldap, dn, mods,
448 if (ret != LDAP_SUCCESS) {
449 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
450 talloc_free(*handle);
453 return lldb_ldap_to_ldb(ret);
456 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
458 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
459 struct ldb_async_handle *handle;
462 /* ldap does not understand ltdb specials */
463 if (ldb_dn_is_special(msg->dn)) {
467 ret = lldb_add_async(module, msg, NULL, NULL, lldb->timeout, &handle);
469 if (ret != LDB_SUCCESS)
472 return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
479 static int lldb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
481 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
483 struct ldb_async_handle **handle)
485 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
486 struct lldb_async_context *lldb_ac;
491 /* ltdb specials should not reach this point */
492 if (ldb_dn_is_special(msg->dn)) {
493 return LDB_ERR_INVALID_DN_SYNTAX;
496 *handle = init_handle(lldb, module, context, callback, timeout);
497 if (*handle == NULL) {
498 return LDB_ERR_OPERATIONS_ERROR;
501 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
503 mods = lldb_msg_to_mods(lldb_ac, msg, 1);
505 talloc_free(*handle);
506 return LDB_ERR_OPERATIONS_ERROR;
509 dn = ldb_dn_linearize(lldb_ac, msg->dn);
511 talloc_free(*handle);
512 return LDB_ERR_OPERATIONS_ERROR;
515 ret = ldap_modify_ext(lldb->ldap, dn, mods,
520 if (ret != LDAP_SUCCESS) {
521 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
522 talloc_free(*handle);
525 return lldb_ldap_to_ldb(ret);
528 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
530 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
531 struct ldb_async_handle *handle;
534 /* ldap does not understand ltdb specials */
535 if (ldb_dn_is_special(msg->dn)) {
539 ret = lldb_modify_async(module, msg, NULL, NULL, lldb->timeout, &handle);
541 if (ret != LDB_SUCCESS)
544 return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
550 static int lldb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
552 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
554 struct ldb_async_handle **handle)
556 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
557 struct lldb_async_context *lldb_ac;
561 /* ltdb specials should not reach this point */
562 if (ldb_dn_is_special(dn)) {
563 return LDB_ERR_INVALID_DN_SYNTAX;
566 *handle = init_handle(lldb, module, context, callback, timeout);
567 if (*handle == NULL) {
568 return LDB_ERR_OPERATIONS_ERROR;
571 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
573 dnstr = ldb_dn_linearize(lldb_ac, dn);
575 ret = ldap_delete_ext(lldb->ldap, dnstr,
580 if (ret != LDAP_SUCCESS) {
581 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
582 talloc_free(*handle);
585 return lldb_ldap_to_ldb(ret);
588 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *dn)
590 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
591 struct ldb_async_handle *handle;
594 /* ignore ltdb specials */
595 if (ldb_dn_is_special(dn)) {
599 ret = lldb_delete_async(module, dn, NULL, NULL, lldb->timeout, &handle);
601 if (ret != LDB_SUCCESS)
604 return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
610 static int lldb_rename_async(struct ldb_module *module,
611 const struct ldb_dn *olddn, const struct ldb_dn *newdn,
613 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
615 struct ldb_async_handle **handle)
617 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
618 struct lldb_async_context *lldb_ac;
624 /* ltdb specials should not reach this point */
625 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
626 return LDB_ERR_INVALID_DN_SYNTAX;
629 *handle = init_handle(lldb, module, context, callback, timeout);
630 if (*handle == NULL) {
631 return LDB_ERR_OPERATIONS_ERROR;
634 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
636 old_dn = ldb_dn_linearize(lldb_ac, olddn);
637 if (old_dn == NULL) {
638 talloc_free(*handle);
639 return LDB_ERR_OPERATIONS_ERROR;
642 newrdn = talloc_asprintf(lldb_ac, "%s=%s",
643 newdn->components[0].name,
644 ldb_dn_escape_value(lldb, newdn->components[0].value));
646 talloc_free(*handle);
647 return LDB_ERR_OPERATIONS_ERROR;
650 parentdn = ldb_dn_linearize(lldb_ac, ldb_dn_get_parent(lldb_ac, newdn));
652 talloc_free(*handle);
653 return LDB_ERR_OPERATIONS_ERROR;
656 ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
660 if (ret != LDAP_SUCCESS) {
661 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
662 talloc_free(*handle);
665 return lldb_ldap_to_ldb(ret);
668 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
670 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
671 struct ldb_async_handle *handle;
674 /* ignore ltdb specials */
675 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
679 ret = lldb_rename_async(module, olddn, newdn, NULL, NULL, lldb->timeout, &handle);
681 if (ret != LDB_SUCCESS)
684 return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
687 static int lldb_parse_result(struct ldb_async_handle *handle, LDAPMessage *result)
689 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
690 struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
691 struct ldb_async_result *ares = NULL;
694 char *matcheddnp = NULL;
695 char *errmsgp = NULL;
696 char **referralsp = NULL;
697 LDAPControl **serverctrlsp = NULL;
699 type = ldap_msgtype(result);
703 case LDAP_RES_SEARCH_ENTRY:
704 msg = ldap_first_entry(lldb->ldap, result);
706 BerElement *berptr = NULL;
709 ares = talloc_zero(ac, struct ldb_async_result);
711 handle->status = LDB_ERR_OPERATIONS_ERROR;
715 ares->message = ldb_msg_new(ares);
716 if (!ares->message) {
717 handle->status = LDB_ERR_OPERATIONS_ERROR;
721 dn = ldap_get_dn(lldb->ldap, msg);
723 handle->status = LDB_ERR_OPERATIONS_ERROR;
726 ares->message->dn = ldb_dn_explode_or_special(ares->message, dn);
727 if (ares->message->dn == NULL) {
728 handle->status = LDB_ERR_OPERATIONS_ERROR;
733 ares->message->num_elements = 0;
734 ares->message->elements = NULL;
735 ares->message->private_data = NULL;
737 /* loop over all attributes */
738 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
740 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
741 struct berval **bval;
742 bval = ldap_get_values_len(lldb->ldap, msg, attr);
745 lldb_add_msg_attr(ac->module->ldb, ares->message, attr, bval);
746 ldap_value_free_len(bval);
751 if (berptr) ber_free(berptr, 0);
754 ares->type = LDB_REPLY_ENTRY;
755 handle->state = LDB_ASYNC_PENDING;
756 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
758 ldap_msgfree(result);
762 case LDAP_RES_SEARCH_REFERENCE:
763 if (ldap_parse_result(lldb->ldap, result, &handle->status,
764 &matcheddnp, &errmsgp,
765 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
766 handle->status = LDB_ERR_OPERATIONS_ERROR;
769 if (referralsp == NULL) {
770 handle->status = LDB_ERR_PROTOCOL_ERROR;
774 ares = talloc_zero(ac, struct ldb_async_result);
776 handle->status = LDB_ERR_OPERATIONS_ERROR;
780 ares->referral = talloc_strdup(ares, *referralsp);
781 ares->type = LDB_REPLY_REFERRAL;
782 handle->state = LDB_ASYNC_PENDING;
783 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
787 case LDAP_RES_SEARCH_RESULT:
788 if (ldap_parse_result(lldb->ldap, result, &handle->status,
789 &matcheddnp, &errmsgp,
790 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
791 handle->status = LDB_ERR_OPERATIONS_ERROR;
795 ares = talloc_zero(ac, struct ldb_async_result);
797 handle->status = LDB_ERR_OPERATIONS_ERROR;
801 if (serverctrlsp != NULL) {
802 /* FIXME: transform the LDAPControl list into an ldb_control one */
803 ares->controls = NULL;
806 ares->type = LDB_REPLY_DONE;
807 handle->state = LDB_ASYNC_DONE;
808 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
812 case LDAP_RES_MODIFY:
814 case LDAP_RES_DELETE:
816 if (ldap_parse_result(lldb->ldap, result, &handle->status,
817 &matcheddnp, &errmsgp,
818 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
819 handle->status = LDB_ERR_OPERATIONS_ERROR;
822 if (ac->callback && handle->status == LDB_SUCCESS) {
823 ares = NULL; /* FIXME: build a corresponding ares to pass on */
824 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
826 handle->state = LDB_ASYNC_DONE;
830 handle->state = LDB_ERR_PROTOCOL_ERROR;
833 if (matcheddnp) ldap_memfree(matcheddnp);
835 ldb_set_errstring(ac->module->ldb, talloc_strdup(ac->module, errmsgp));
836 ldap_memfree(errmsgp);
838 if (referralsp) ldap_value_free(referralsp);
839 if (serverctrlsp) ldap_controls_free(serverctrlsp);
841 return handle->status;
844 handle->state = LDB_ASYNC_DONE;
845 return handle->status;
848 static int lldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
850 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
851 struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
852 struct timeval timeout;
857 return LDB_ERR_OPERATIONS_ERROR;
860 handle->status = LDB_SUCCESS;
861 handle->state = LDB_ASYNC_INIT;
867 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
869 handle->status = LDB_ERR_OPERATIONS_ERROR;
870 return handle->status;
873 handle->status = LDB_SUCCESS;
874 return handle->status;
876 ret = lldb_parse_result(handle, result);
879 timeout.tv_sec = ac->timeout;
881 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
882 if (ret == -1 || ret == 0) {
883 handle->status = LDB_ERR_OPERATIONS_ERROR;
884 return handle->status;
886 ret = lldb_parse_result(handle, result);
889 timeout.tv_sec = ac->timeout;
891 while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) {
892 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
893 if (ret == -1 || ret == 0) {
894 handle->status = LDB_ERR_OPERATIONS_ERROR;
895 return handle->status;
897 ret = lldb_parse_result(handle, result);
898 if (ret != LDB_SUCCESS) {
904 ret = LDB_ERR_OPERATIONS_ERROR;
910 static int lldb_start_trans(struct ldb_module *module)
912 /* TODO implement a local transaction mechanism here */
917 static int lldb_end_trans(struct ldb_module *module)
919 /* TODO implement a local transaction mechanism here */
924 static int lldb_del_trans(struct ldb_module *module)
926 /* TODO implement a local transaction mechanism here */
931 static int lldb_request(struct ldb_module *module, struct ldb_request *req)
933 switch (req->operation) {
936 return lldb_search_bytree(module,
938 req->op.search.scope,
940 req->op.search.attrs,
942 &req->op.search.res);
945 return lldb_add(module, req->op.add.message);
948 return lldb_modify(module, req->op.mod.message);
951 return lldb_delete(module, req->op.del.dn);
954 return lldb_rename(module,
955 req->op.rename.olddn,
956 req->op.rename.newdn);
958 case LDB_ASYNC_SEARCH:
959 return lldb_search_async(module,
961 req->op.search.scope,
963 req->op.search.attrs,
971 return lldb_add_async(module,
978 case LDB_ASYNC_MODIFY:
979 return lldb_modify_async(module,
986 case LDB_ASYNC_DELETE:
987 return lldb_delete_async(module,
994 case LDB_ASYNC_RENAME:
995 return lldb_rename_async(module,
996 req->op.rename.olddn,
997 req->op.rename.newdn,
1001 &req->async.handle);
1009 static const struct ldb_module_ops lldb_ops = {
1011 .request = lldb_request,
1012 .start_transaction = lldb_start_trans,
1013 .end_transaction = lldb_end_trans,
1014 .del_transaction = lldb_del_trans,
1018 static int lldb_destructor(void *p)
1020 struct lldb_private *lldb = p;
1021 ldap_unbind(lldb->ldap);
1026 connect to the database
1028 int lldb_connect(struct ldb_context *ldb,
1031 const char *options[])
1033 struct lldb_private *lldb = NULL;
1037 lldb = talloc(ldb, struct lldb_private);
1044 lldb->timeout = 120; /* TODO: get timeout from options ? */
1046 ret = ldap_initialize(&lldb->ldap, url);
1047 if (ret != LDAP_SUCCESS) {
1048 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
1049 url, ldap_err2string(ret));
1053 talloc_set_destructor(lldb, lldb_destructor);
1055 ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
1056 if (ret != LDAP_SUCCESS) {
1057 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
1058 ldap_err2string(ret));
1062 ldb->modules = talloc(ldb, struct ldb_module);
1063 if (!ldb->modules) {
1067 ldb->modules->ldb = ldb;
1068 ldb->modules->prev = ldb->modules->next = NULL;
1069 ldb->modules->private_data = lldb;
1070 ldb->modules->ops = &lldb_ops;
1072 ldb->async_wait = &lldb_async_wait;