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) {
399 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
403 if (ret != LDB_SUCCESS) {
413 static int lldb_add_async(struct ldb_module *module, const struct ldb_message *msg,
415 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
417 struct ldb_async_handle **handle)
419 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
420 struct lldb_async_context *lldb_ac;
425 /* ltdb specials should not reach this point */
426 if (ldb_dn_is_special(msg->dn)) {
427 return LDB_ERR_INVALID_DN_SYNTAX;
430 *handle = init_handle(lldb, module, context, callback, timeout);
431 if (*handle == NULL) {
432 return LDB_ERR_OPERATIONS_ERROR;
435 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
437 mods = lldb_msg_to_mods(lldb_ac, msg, 0);
439 talloc_free(*handle);
440 return LDB_ERR_OPERATIONS_ERROR;
443 dn = ldb_dn_linearize(lldb_ac, msg->dn);
445 talloc_free(*handle);
446 return LDB_ERR_OPERATIONS_ERROR;
449 ret = ldap_add_ext(lldb->ldap, dn, mods,
454 if (ret != LDAP_SUCCESS) {
455 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
456 talloc_free(*handle);
459 return lldb_ldap_to_ldb(ret);
462 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
464 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
465 struct ldb_async_handle *handle;
468 /* ldap does not understand ltdb specials */
469 if (ldb_dn_is_special(msg->dn)) {
473 ret = lldb_add_async(module, msg, NULL, NULL, lldb->timeout, &handle);
475 if (ret != LDB_SUCCESS)
478 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
488 static int lldb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
490 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
492 struct ldb_async_handle **handle)
494 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
495 struct lldb_async_context *lldb_ac;
500 /* ltdb specials should not reach this point */
501 if (ldb_dn_is_special(msg->dn)) {
502 return LDB_ERR_INVALID_DN_SYNTAX;
505 *handle = init_handle(lldb, module, context, callback, timeout);
506 if (*handle == NULL) {
507 return LDB_ERR_OPERATIONS_ERROR;
510 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
512 mods = lldb_msg_to_mods(lldb_ac, msg, 1);
514 talloc_free(*handle);
515 return LDB_ERR_OPERATIONS_ERROR;
518 dn = ldb_dn_linearize(lldb_ac, msg->dn);
520 talloc_free(*handle);
521 return LDB_ERR_OPERATIONS_ERROR;
524 ret = ldap_modify_ext(lldb->ldap, dn, mods,
529 if (ret != LDAP_SUCCESS) {
530 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
531 talloc_free(*handle);
534 return lldb_ldap_to_ldb(ret);
537 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
539 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
540 struct ldb_async_handle *handle;
543 /* ldap does not understand ltdb specials */
544 if (ldb_dn_is_special(msg->dn)) {
548 ret = lldb_modify_async(module, msg, NULL, NULL, lldb->timeout, &handle);
550 if (ret != LDB_SUCCESS)
553 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
562 static int lldb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
564 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
566 struct ldb_async_handle **handle)
568 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
569 struct lldb_async_context *lldb_ac;
573 /* ltdb specials should not reach this point */
574 if (ldb_dn_is_special(dn)) {
575 return LDB_ERR_INVALID_DN_SYNTAX;
578 *handle = init_handle(lldb, module, context, callback, timeout);
579 if (*handle == NULL) {
580 return LDB_ERR_OPERATIONS_ERROR;
583 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
585 dnstr = ldb_dn_linearize(lldb_ac, dn);
587 ret = ldap_delete_ext(lldb->ldap, dnstr,
592 if (ret != LDAP_SUCCESS) {
593 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
594 talloc_free(*handle);
597 return lldb_ldap_to_ldb(ret);
600 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *dn)
602 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
603 struct ldb_async_handle *handle;
606 /* ignore ltdb specials */
607 if (ldb_dn_is_special(dn)) {
611 ret = lldb_delete_async(module, dn, NULL, NULL, lldb->timeout, &handle);
613 if (ret != LDB_SUCCESS)
616 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
625 static int lldb_rename_async(struct ldb_module *module,
626 const struct ldb_dn *olddn, const struct ldb_dn *newdn,
628 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
630 struct ldb_async_handle **handle)
632 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
633 struct lldb_async_context *lldb_ac;
639 /* ltdb specials should not reach this point */
640 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
641 return LDB_ERR_INVALID_DN_SYNTAX;
644 *handle = init_handle(lldb, module, context, callback, timeout);
645 if (*handle == NULL) {
646 return LDB_ERR_OPERATIONS_ERROR;
649 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
651 old_dn = ldb_dn_linearize(lldb_ac, olddn);
652 if (old_dn == NULL) {
653 talloc_free(*handle);
654 return LDB_ERR_OPERATIONS_ERROR;
657 newrdn = talloc_asprintf(lldb_ac, "%s=%s",
658 newdn->components[0].name,
659 ldb_dn_escape_value(lldb, newdn->components[0].value));
661 talloc_free(*handle);
662 return LDB_ERR_OPERATIONS_ERROR;
665 parentdn = ldb_dn_linearize(lldb_ac, ldb_dn_get_parent(lldb_ac, newdn));
667 talloc_free(*handle);
668 return LDB_ERR_OPERATIONS_ERROR;
671 ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
675 if (ret != LDAP_SUCCESS) {
676 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
677 talloc_free(*handle);
680 return lldb_ldap_to_ldb(ret);
683 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
685 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
686 struct ldb_async_handle *handle;
689 /* ignore ltdb specials */
690 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
694 ret = lldb_rename_async(module, olddn, newdn, NULL, NULL, lldb->timeout, &handle);
696 if (ret != LDB_SUCCESS)
699 ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
705 static int lldb_parse_result(struct ldb_async_handle *handle, LDAPMessage *result)
707 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
708 struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
709 struct ldb_async_result *ares = NULL;
712 char *matcheddnp = NULL;
713 char *errmsgp = NULL;
714 char **referralsp = NULL;
715 LDAPControl **serverctrlsp = NULL;
718 type = ldap_msgtype(result);
722 case LDAP_RES_SEARCH_ENTRY:
723 msg = ldap_first_entry(lldb->ldap, result);
725 BerElement *berptr = NULL;
728 ares = talloc_zero(ac, struct ldb_async_result);
730 handle->status = LDB_ERR_OPERATIONS_ERROR;
734 ares->message = ldb_msg_new(ares);
735 if (!ares->message) {
736 handle->status = LDB_ERR_OPERATIONS_ERROR;
740 dn = ldap_get_dn(lldb->ldap, msg);
742 handle->status = LDB_ERR_OPERATIONS_ERROR;
745 ares->message->dn = ldb_dn_explode_or_special(ares->message, dn);
746 if (ares->message->dn == NULL) {
747 handle->status = LDB_ERR_OPERATIONS_ERROR;
752 ares->message->num_elements = 0;
753 ares->message->elements = NULL;
754 ares->message->private_data = NULL;
756 /* loop over all attributes */
757 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
759 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
760 struct berval **bval;
761 bval = ldap_get_values_len(lldb->ldap, msg, attr);
764 lldb_add_msg_attr(ac->module->ldb, ares->message, attr, bval);
765 ldap_value_free_len(bval);
768 if (berptr) ber_free(berptr, 0);
771 ares->type = LDB_REPLY_ENTRY;
772 handle->state = LDB_ASYNC_PENDING;
773 ret = ac->callback(ac->module->ldb, ac->context, ares);
774 if (ret != LDB_SUCCESS) {
775 handle->status = ret;
778 handle->status = LDB_ERR_PROTOCOL_ERROR;
779 handle->state = LDB_ASYNC_DONE;
783 case LDAP_RES_SEARCH_REFERENCE:
784 if (ldap_parse_result(lldb->ldap, result, &handle->status,
785 &matcheddnp, &errmsgp,
786 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
787 handle->status = LDB_ERR_OPERATIONS_ERROR;
790 if (referralsp == NULL) {
791 handle->status = LDB_ERR_PROTOCOL_ERROR;
795 ares = talloc_zero(ac, struct ldb_async_result);
797 handle->status = LDB_ERR_OPERATIONS_ERROR;
801 ares->referral = talloc_strdup(ares, *referralsp);
802 ares->type = LDB_REPLY_REFERRAL;
803 handle->state = LDB_ASYNC_PENDING;
804 ret = ac->callback(ac->module->ldb, ac->context, ares);
805 if (ret != LDB_SUCCESS) {
806 handle->status = ret;
811 case LDAP_RES_SEARCH_RESULT:
812 if (ldap_parse_result(lldb->ldap, result, &handle->status,
813 &matcheddnp, &errmsgp,
814 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
815 handle->status = LDB_ERR_OPERATIONS_ERROR;
819 ares = talloc_zero(ac, struct ldb_async_result);
821 handle->status = LDB_ERR_OPERATIONS_ERROR;
825 if (serverctrlsp != NULL) {
826 /* FIXME: transform the LDAPControl list into an ldb_control one */
827 ares->controls = NULL;
830 ares->type = LDB_REPLY_DONE;
831 handle->state = LDB_ASYNC_DONE;
832 ret = ac->callback(ac->module->ldb, ac->context, ares);
833 if (ret != LDB_SUCCESS) {
834 handle->status = ret;
839 case LDAP_RES_MODIFY:
841 case LDAP_RES_DELETE:
843 if (ldap_parse_result(lldb->ldap, result, &handle->status,
844 &matcheddnp, &errmsgp,
845 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
846 handle->status = LDB_ERR_OPERATIONS_ERROR;
849 if (ac->callback && handle->status == LDB_SUCCESS) {
850 ares = NULL; /* FIXME: build a corresponding ares to pass on */
851 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
853 handle->state = LDB_ASYNC_DONE;
857 handle->status = LDB_ERR_PROTOCOL_ERROR;
861 if (matcheddnp) ldap_memfree(matcheddnp);
863 ldb_set_errstring(ac->module->ldb, talloc_strdup(ac->module, errmsgp));
864 ldap_memfree(errmsgp);
866 if (referralsp) ldap_value_free(referralsp);
867 if (serverctrlsp) ldap_controls_free(serverctrlsp);
869 ldap_msgfree(result);
870 return handle->status;
873 handle->state = LDB_ASYNC_DONE;
874 ldap_msgfree(result);
875 return handle->status;
878 static int lldb_async_wait(struct ldb_module *module, struct ldb_async_handle *handle, enum ldb_async_wait_type type)
880 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
881 struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
882 struct timeval timeout;
884 int ret = LDB_ERR_OPERATIONS_ERROR;
887 return LDB_ERR_OPERATIONS_ERROR;
890 handle->status = LDB_SUCCESS;
891 handle->state = LDB_ASYNC_INIT;
897 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
899 handle->status = LDB_ERR_OPERATIONS_ERROR;
900 return handle->status;
903 handle->status = LDB_SUCCESS;
904 return handle->status;
906 ret = lldb_parse_result(handle, result);
909 timeout.tv_sec = ac->timeout;
911 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
912 if (ret == -1 || ret == 0) {
913 handle->status = LDB_ERR_OPERATIONS_ERROR;
914 return handle->status;
916 ret = lldb_parse_result(handle, result);
919 timeout.tv_sec = ac->timeout;
921 while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) {
922 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
923 if (ret == -1 || ret == 0) {
924 handle->status = LDB_ERR_OPERATIONS_ERROR;
925 return handle->status;
927 ret = lldb_parse_result(handle, result);
928 if (ret != LDB_SUCCESS) {
938 static int lldb_start_trans(struct ldb_module *module)
940 /* TODO implement a local transaction mechanism here */
945 static int lldb_end_trans(struct ldb_module *module)
947 /* TODO implement a local transaction mechanism here */
952 static int lldb_del_trans(struct ldb_module *module)
954 /* TODO implement a local transaction mechanism here */
959 static int lldb_request(struct ldb_module *module, struct ldb_request *req)
961 switch (req->operation) {
964 return lldb_search_bytree(module,
966 req->op.search.scope,
968 req->op.search.attrs,
970 &req->op.search.res);
973 return lldb_add(module, req->op.add.message);
976 return lldb_modify(module, req->op.mod.message);
979 return lldb_delete(module, req->op.del.dn);
982 return lldb_rename(module,
983 req->op.rename.olddn,
984 req->op.rename.newdn);
986 case LDB_ASYNC_SEARCH:
987 return lldb_search_async(module,
989 req->op.search.scope,
991 req->op.search.attrs,
999 return lldb_add_async(module,
1000 req->op.add.message,
1002 req->async.callback,
1004 &req->async.handle);
1006 case LDB_ASYNC_MODIFY:
1007 return lldb_modify_async(module,
1008 req->op.mod.message,
1010 req->async.callback,
1012 &req->async.handle);
1014 case LDB_ASYNC_DELETE:
1015 return lldb_delete_async(module,
1018 req->async.callback,
1020 &req->async.handle);
1022 case LDB_ASYNC_RENAME:
1023 return lldb_rename_async(module,
1024 req->op.rename.olddn,
1025 req->op.rename.newdn,
1027 req->async.callback,
1029 &req->async.handle);
1037 static const struct ldb_module_ops lldb_ops = {
1039 .request = lldb_request,
1040 .start_transaction = lldb_start_trans,
1041 .end_transaction = lldb_end_trans,
1042 .del_transaction = lldb_del_trans,
1043 .async_wait = lldb_async_wait
1047 static int lldb_destructor(void *p)
1049 struct lldb_private *lldb = p;
1050 ldap_unbind(lldb->ldap);
1055 connect to the database
1057 static int lldb_connect(struct ldb_context *ldb,
1060 const char *options[])
1062 struct lldb_private *lldb = NULL;
1066 lldb = talloc(ldb, struct lldb_private);
1073 lldb->timeout = 120; /* TODO: get timeout from options ? */
1075 ret = ldap_initialize(&lldb->ldap, url);
1076 if (ret != LDAP_SUCCESS) {
1077 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
1078 url, ldap_err2string(ret));
1082 talloc_set_destructor(lldb, lldb_destructor);
1084 ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
1085 if (ret != LDAP_SUCCESS) {
1086 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
1087 ldap_err2string(ret));
1091 ldb->modules = talloc(ldb, struct ldb_module);
1092 if (!ldb->modules) {
1096 ldb->modules->ldb = ldb;
1097 ldb->modules->prev = ldb->modules->next = NULL;
1098 ldb->modules->private_data = lldb;
1099 ldb->modules->ops = &lldb_ops;
1108 int ldb_ldap_init(void)
1110 return ldb_register_backend("ldap", lldb_connect);