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"));
81 ac = talloc(h, struct lldb_async_context);
83 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
88 h->private_data = (void *)ac;
91 ac->context = context;
92 ac->callback = callback;
93 ac->timeout = timeout;
99 convert a ldb_message structure to a list of LDAPMod structures
100 ready for ldap_add() or ldap_modify()
102 static LDAPMod **lldb_msg_to_mods(void *mem_ctx, const struct ldb_message *msg, int use_flags)
108 /* allocate maximum number of elements needed */
109 mods = talloc_array(mem_ctx, LDAPMod *, msg->num_elements+1);
116 for (i=0;i<msg->num_elements;i++) {
117 const struct ldb_message_element *el = &msg->elements[i];
119 mods[num_mods] = talloc(mods, LDAPMod);
120 if (!mods[num_mods]) {
123 mods[num_mods+1] = NULL;
124 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
126 switch (el->flags & LDB_FLAG_MOD_MASK) {
127 case LDB_FLAG_MOD_ADD:
128 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
130 case LDB_FLAG_MOD_DELETE:
131 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
133 case LDB_FLAG_MOD_REPLACE:
134 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
138 mods[num_mods]->mod_type = discard_const_p(char, el->name);
139 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods],
142 if (!mods[num_mods]->mod_vals.modv_bvals) {
146 for (j=0;j<el->num_values;j++) {
147 mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
149 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
152 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
153 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
155 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
167 add a single set of ldap message values to a ldb_message
169 static int lldb_add_msg_attr(struct ldb_context *ldb,
170 struct ldb_message *msg,
171 const char *attr, struct berval **bval)
174 struct ldb_message_element *el;
176 count = ldap_count_values_len(bval);
182 el = talloc_realloc(msg, msg->elements, struct ldb_message_element,
183 msg->num_elements + 1);
191 el = &msg->elements[msg->num_elements];
193 el->name = talloc_strdup(msg->elements, attr);
201 el->values = talloc_array(msg->elements, struct ldb_val, count);
207 for (i=0;i<count;i++) {
208 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
209 if (!el->values[i].data) {
212 el->values[i].length = bval[i]->bv_len;
222 search for matching records
224 static int lldb_search_async(struct ldb_module *module, const struct ldb_dn *base,
225 enum ldb_scope scope, struct ldb_parse_tree *tree,
226 const char * const *attrs,
227 struct ldb_control **control_req,
229 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
231 struct ldb_async_handle **handle)
233 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
234 struct lldb_async_context *lldb_ac;
241 if (!callback || !context) {
242 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Async interface called with NULL callback function or NULL context"));
243 return LDB_ERR_OPERATIONS_ERROR;
247 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Invalid expression parse tree"));
248 return LDB_ERR_OPERATIONS_ERROR;
251 if (control_req != NULL) {
252 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");
255 *handle = init_handle(lldb, module, context, callback, timeout);
256 if (*handle == NULL) {
257 talloc_free(*handle);
258 return LDB_ERR_OPERATIONS_ERROR;
261 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
263 search_base = ldb_dn_linearize(lldb_ac, base);
265 search_base = talloc_strdup(lldb_ac, "");
267 if (search_base == NULL) {
268 talloc_free(*handle);
269 return LDB_ERR_OPERATIONS_ERROR;
272 expression = ldb_filter_from_tree(lldb_ac, tree);
273 if (expression == NULL) {
274 talloc_free(*handle);
275 return LDB_ERR_OPERATIONS_ERROR;
280 ldap_scope = LDAP_SCOPE_BASE;
282 case LDB_SCOPE_ONELEVEL:
283 ldap_scope = LDAP_SCOPE_ONELEVEL;
286 ldap_scope = LDAP_SCOPE_SUBTREE;
293 ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope,
295 discard_const_p(char *, attrs),
303 if (ret != LDAP_SUCCESS) {
304 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
305 talloc_free(*handle);
309 return lldb_ldap_to_ldb(ret);
312 static int lldb_search_sync_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
314 struct ldb_result *res;
318 ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context in callback"));
319 return LDB_ERR_OPERATIONS_ERROR;
322 res = *((struct ldb_result **)context);
328 if (ares->type == LDB_REPLY_ENTRY) {
329 res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
334 res->msgs[res->count + 1] = NULL;
336 res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
337 if (! res->msgs[res->count]) {
344 if (ares->type == LDB_REPLY_REFERRAL) {
346 for (n = 0; res->refs[n]; n++) /*noop*/ ;
351 res->refs = talloc_realloc(res, res->refs, char *, n + 2);
356 res->refs[n] = talloc_steal(res->refs, ares->referral);
357 res->refs[n + 1] = NULL;
360 if (ares->type == LDB_REPLY_DONE) {
361 if (ares->controls) {
362 res->controls = talloc_steal(res, ares->controls);
363 if (! res->controls) {
375 *((struct ldb_result **)context) = NULL;
376 return LDB_ERR_OPERATIONS_ERROR;
380 search for matching records using a synchronous function
382 static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
383 enum ldb_scope scope, struct ldb_parse_tree *tree,
384 const char * const *attrs,
385 struct ldb_control **control_req,
386 struct ldb_result **res)
388 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
389 struct ldb_async_handle *handle;
392 *res = talloc_zero(lldb, struct ldb_result);
394 return LDB_ERR_OPERATIONS_ERROR;
397 ret = lldb_search_async(module, base, scope, tree, attrs, control_req,
398 res, &lldb_search_sync_callback, lldb->timeout, &handle);
400 if (ret == LDB_SUCCESS) {
401 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
405 if (ret != LDB_SUCCESS) {
415 static int lldb_add_async(struct ldb_module *module, const struct ldb_message *msg,
417 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
419 struct ldb_async_handle **handle)
421 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
422 struct lldb_async_context *lldb_ac;
427 /* ltdb specials should not reach this point */
428 if (ldb_dn_is_special(msg->dn)) {
429 return LDB_ERR_INVALID_DN_SYNTAX;
432 *handle = init_handle(lldb, module, context, callback, timeout);
433 if (*handle == NULL) {
434 return LDB_ERR_OPERATIONS_ERROR;
437 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
439 mods = lldb_msg_to_mods(lldb_ac, msg, 0);
441 talloc_free(*handle);
442 return LDB_ERR_OPERATIONS_ERROR;
445 dn = ldb_dn_linearize(lldb_ac, msg->dn);
447 talloc_free(*handle);
448 return LDB_ERR_OPERATIONS_ERROR;
451 ret = ldap_add_ext(lldb->ldap, dn, mods,
456 if (ret != LDAP_SUCCESS) {
457 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
458 talloc_free(*handle);
461 return lldb_ldap_to_ldb(ret);
464 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
466 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
467 struct ldb_async_handle *handle;
470 /* ldap does not understand ltdb specials */
471 if (ldb_dn_is_special(msg->dn)) {
475 ret = lldb_add_async(module, msg, NULL, NULL, lldb->timeout, &handle);
477 if (ret != LDB_SUCCESS)
480 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
490 static int lldb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
492 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
494 struct ldb_async_handle **handle)
496 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
497 struct lldb_async_context *lldb_ac;
502 /* ltdb specials should not reach this point */
503 if (ldb_dn_is_special(msg->dn)) {
504 return LDB_ERR_INVALID_DN_SYNTAX;
507 *handle = init_handle(lldb, module, context, callback, timeout);
508 if (*handle == NULL) {
509 return LDB_ERR_OPERATIONS_ERROR;
512 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
514 mods = lldb_msg_to_mods(lldb_ac, msg, 1);
516 talloc_free(*handle);
517 return LDB_ERR_OPERATIONS_ERROR;
520 dn = ldb_dn_linearize(lldb_ac, msg->dn);
522 talloc_free(*handle);
523 return LDB_ERR_OPERATIONS_ERROR;
526 ret = ldap_modify_ext(lldb->ldap, dn, mods,
531 if (ret != LDAP_SUCCESS) {
532 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
533 talloc_free(*handle);
536 return lldb_ldap_to_ldb(ret);
539 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
541 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
542 struct ldb_async_handle *handle;
545 /* ldap does not understand ltdb specials */
546 if (ldb_dn_is_special(msg->dn)) {
550 ret = lldb_modify_async(module, msg, NULL, NULL, lldb->timeout, &handle);
552 if (ret != LDB_SUCCESS)
555 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
564 static int lldb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
566 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
568 struct ldb_async_handle **handle)
570 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
571 struct lldb_async_context *lldb_ac;
575 /* ltdb specials should not reach this point */
576 if (ldb_dn_is_special(dn)) {
577 return LDB_ERR_INVALID_DN_SYNTAX;
580 *handle = init_handle(lldb, module, context, callback, timeout);
581 if (*handle == NULL) {
582 return LDB_ERR_OPERATIONS_ERROR;
585 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
587 dnstr = ldb_dn_linearize(lldb_ac, dn);
589 ret = ldap_delete_ext(lldb->ldap, dnstr,
594 if (ret != LDAP_SUCCESS) {
595 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
596 talloc_free(*handle);
599 return lldb_ldap_to_ldb(ret);
602 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *dn)
604 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
605 struct ldb_async_handle *handle;
608 /* ignore ltdb specials */
609 if (ldb_dn_is_special(dn)) {
613 ret = lldb_delete_async(module, dn, NULL, NULL, lldb->timeout, &handle);
615 if (ret != LDB_SUCCESS)
618 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
627 static int lldb_rename_async(struct ldb_module *module,
628 const struct ldb_dn *olddn, const struct ldb_dn *newdn,
630 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
632 struct ldb_async_handle **handle)
634 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
635 struct lldb_async_context *lldb_ac;
641 /* ltdb specials should not reach this point */
642 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
643 return LDB_ERR_INVALID_DN_SYNTAX;
646 *handle = init_handle(lldb, module, context, callback, timeout);
647 if (*handle == NULL) {
648 return LDB_ERR_OPERATIONS_ERROR;
651 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
653 old_dn = ldb_dn_linearize(lldb_ac, olddn);
654 if (old_dn == NULL) {
655 talloc_free(*handle);
656 return LDB_ERR_OPERATIONS_ERROR;
659 newrdn = talloc_asprintf(lldb_ac, "%s=%s",
660 newdn->components[0].name,
661 ldb_dn_escape_value(lldb, newdn->components[0].value));
663 talloc_free(*handle);
664 return LDB_ERR_OPERATIONS_ERROR;
667 parentdn = ldb_dn_linearize(lldb_ac, ldb_dn_get_parent(lldb_ac, newdn));
669 talloc_free(*handle);
670 return LDB_ERR_OPERATIONS_ERROR;
673 ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
677 if (ret != LDAP_SUCCESS) {
678 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
679 talloc_free(*handle);
682 return lldb_ldap_to_ldb(ret);
685 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
687 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
688 struct ldb_async_handle *handle;
691 /* ignore ltdb specials */
692 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
696 ret = lldb_rename_async(module, olddn, newdn, NULL, NULL, lldb->timeout, &handle);
698 if (ret != LDB_SUCCESS)
701 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
707 static int lldb_parse_result(struct ldb_async_handle *handle, LDAPMessage *result)
709 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
710 struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
711 struct ldb_async_result *ares = NULL;
714 char *matcheddnp = NULL;
715 char *errmsgp = NULL;
716 char **referralsp = NULL;
717 LDAPControl **serverctrlsp = NULL;
720 type = ldap_msgtype(result);
724 case LDAP_RES_SEARCH_ENTRY:
725 msg = ldap_first_entry(lldb->ldap, result);
727 BerElement *berptr = NULL;
730 ares = talloc_zero(ac, struct ldb_async_result);
732 handle->status = LDB_ERR_OPERATIONS_ERROR;
736 ares->message = ldb_msg_new(ares);
737 if (!ares->message) {
738 handle->status = LDB_ERR_OPERATIONS_ERROR;
742 dn = ldap_get_dn(lldb->ldap, msg);
744 handle->status = LDB_ERR_OPERATIONS_ERROR;
747 ares->message->dn = ldb_dn_explode_or_special(ares->message, dn);
748 if (ares->message->dn == NULL) {
749 handle->status = LDB_ERR_OPERATIONS_ERROR;
754 ares->message->num_elements = 0;
755 ares->message->elements = NULL;
756 ares->message->private_data = NULL;
758 /* loop over all attributes */
759 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
761 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
762 struct berval **bval;
763 bval = ldap_get_values_len(lldb->ldap, msg, attr);
766 lldb_add_msg_attr(ac->module->ldb, ares->message, attr, bval);
767 ldap_value_free_len(bval);
770 if (berptr) ber_free(berptr, 0);
773 ares->type = LDB_REPLY_ENTRY;
774 handle->state = LDB_ASYNC_PENDING;
775 ret = ac->callback(ac->module->ldb, ac->context, ares);
776 if (ret != LDB_SUCCESS) {
777 handle->status = ret;
780 handle->status = LDB_ERR_PROTOCOL_ERROR;
781 handle->state = LDB_ASYNC_DONE;
785 case LDAP_RES_SEARCH_REFERENCE:
786 if (ldap_parse_result(lldb->ldap, result, &handle->status,
787 &matcheddnp, &errmsgp,
788 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
789 handle->status = LDB_ERR_OPERATIONS_ERROR;
792 if (referralsp == NULL) {
793 handle->status = LDB_ERR_PROTOCOL_ERROR;
797 ares = talloc_zero(ac, struct ldb_async_result);
799 handle->status = LDB_ERR_OPERATIONS_ERROR;
803 ares->referral = talloc_strdup(ares, *referralsp);
804 ares->type = LDB_REPLY_REFERRAL;
805 handle->state = LDB_ASYNC_PENDING;
806 ret = ac->callback(ac->module->ldb, ac->context, ares);
807 if (ret != LDB_SUCCESS) {
808 handle->status = ret;
813 case LDAP_RES_SEARCH_RESULT:
814 if (ldap_parse_result(lldb->ldap, result, &handle->status,
815 &matcheddnp, &errmsgp,
816 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
817 handle->status = LDB_ERR_OPERATIONS_ERROR;
821 ares = talloc_zero(ac, struct ldb_async_result);
823 handle->status = LDB_ERR_OPERATIONS_ERROR;
827 if (serverctrlsp != NULL) {
828 /* FIXME: transform the LDAPControl list into an ldb_control one */
829 ares->controls = NULL;
832 ares->type = LDB_REPLY_DONE;
833 handle->state = LDB_ASYNC_DONE;
834 ret = ac->callback(ac->module->ldb, ac->context, ares);
835 if (ret != LDB_SUCCESS) {
836 handle->status = ret;
841 case LDAP_RES_MODIFY:
843 case LDAP_RES_DELETE:
845 if (ldap_parse_result(lldb->ldap, result, &handle->status,
846 &matcheddnp, &errmsgp,
847 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
848 handle->status = LDB_ERR_OPERATIONS_ERROR;
851 if (ac->callback && handle->status == LDB_SUCCESS) {
852 ares = NULL; /* FIXME: build a corresponding ares to pass on */
853 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
855 handle->state = LDB_ASYNC_DONE;
859 handle->status = LDB_ERR_PROTOCOL_ERROR;
863 if (matcheddnp) ldap_memfree(matcheddnp);
865 ldb_set_errstring(ac->module->ldb, talloc_strdup(ac->module, errmsgp));
866 ldap_memfree(errmsgp);
868 if (referralsp) ldap_value_free(referralsp);
869 if (serverctrlsp) ldap_controls_free(serverctrlsp);
871 ldap_msgfree(result);
872 return handle->status;
875 handle->state = LDB_ASYNC_DONE;
876 ldap_msgfree(result);
877 return handle->status;
880 static int lldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
882 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
883 struct lldb_private *lldb = talloc_get_type(handle->module->private_data, struct lldb_private);
884 struct timeval timeout;
886 int ret = LDB_ERR_OPERATIONS_ERROR;
889 return LDB_ERR_OPERATIONS_ERROR;
892 handle->status = LDB_SUCCESS;
893 handle->state = LDB_ASYNC_INIT;
899 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
901 handle->status = LDB_ERR_OPERATIONS_ERROR;
902 return handle->status;
905 handle->status = LDB_SUCCESS;
906 return handle->status;
908 ret = lldb_parse_result(handle, result);
911 timeout.tv_sec = ac->timeout;
913 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
914 if (ret == -1 || ret == 0) {
915 handle->status = LDB_ERR_OPERATIONS_ERROR;
916 return handle->status;
918 ret = lldb_parse_result(handle, result);
921 timeout.tv_sec = ac->timeout;
923 while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) {
924 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
925 if (ret == -1 || ret == 0) {
926 handle->status = LDB_ERR_OPERATIONS_ERROR;
927 return handle->status;
929 ret = lldb_parse_result(handle, result);
930 if (ret != LDB_SUCCESS) {
940 static int lldb_start_trans(struct ldb_module *module)
942 /* TODO implement a local transaction mechanism here */
947 static int lldb_end_trans(struct ldb_module *module)
949 /* TODO implement a local transaction mechanism here */
954 static int lldb_del_trans(struct ldb_module *module)
956 /* TODO implement a local transaction mechanism here */
961 static int lldb_request(struct ldb_module *module, struct ldb_request *req)
963 switch (req->operation) {
966 return lldb_search_bytree(module,
968 req->op.search.scope,
970 req->op.search.attrs,
972 &req->op.search.res);
975 return lldb_add(module, req->op.add.message);
978 return lldb_modify(module, req->op.mod.message);
981 return lldb_delete(module, req->op.del.dn);
984 return lldb_rename(module,
985 req->op.rename.olddn,
986 req->op.rename.newdn);
988 case LDB_ASYNC_SEARCH:
989 return lldb_search_async(module,
991 req->op.search.scope,
993 req->op.search.attrs,
1001 return lldb_add_async(module,
1002 req->op.add.message,
1004 req->async.callback,
1006 &req->async.handle);
1008 case LDB_ASYNC_MODIFY:
1009 return lldb_modify_async(module,
1010 req->op.mod.message,
1012 req->async.callback,
1014 &req->async.handle);
1016 case LDB_ASYNC_DELETE:
1017 return lldb_delete_async(module,
1020 req->async.callback,
1022 &req->async.handle);
1024 case LDB_ASYNC_RENAME:
1025 return lldb_rename_async(module,
1026 req->op.rename.olddn,
1027 req->op.rename.newdn,
1029 req->async.callback,
1031 &req->async.handle);
1039 static const struct ldb_module_ops lldb_ops = {
1041 .request = lldb_request,
1042 .start_transaction = lldb_start_trans,
1043 .end_transaction = lldb_end_trans,
1044 .del_transaction = lldb_del_trans,
1045 .async_wait = lldb_async_wait
1049 static int lldb_destructor(void *p)
1051 struct lldb_private *lldb = p;
1052 ldap_unbind(lldb->ldap);
1057 connect to the database
1059 static int lldb_connect(struct ldb_context *ldb,
1062 const char *options[])
1064 struct lldb_private *lldb = NULL;
1068 lldb = talloc(ldb, struct lldb_private);
1075 lldb->timeout = 120; /* TODO: get timeout from options ? */
1077 ret = ldap_initialize(&lldb->ldap, url);
1078 if (ret != LDAP_SUCCESS) {
1079 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
1080 url, ldap_err2string(ret));
1084 talloc_set_destructor(lldb, lldb_destructor);
1086 ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
1087 if (ret != LDAP_SUCCESS) {
1088 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
1089 ldap_err2string(ret));
1093 ldb->modules = talloc(ldb, struct ldb_module);
1094 if (!ldb->modules) {
1098 ldb->modules->ldb = ldb;
1099 ldb->modules->prev = ldb->modules->next = NULL;
1100 ldb->modules->private_data = lldb;
1101 ldb->modules->ops = &lldb_ops;
1110 int ldb_ldap_init(void)
1112 return ldb_register_backend("ldap", lldb_connect);