2 ldb database mapping module
4 Copyright (C) Jelmer Vernooij 2005
5 Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
6 Copyright (C) Simo Sorce <idra@samba.org> 2008
8 ** NOTE! The following LGPL license applies to the ldb
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 #include "ldb_includes.h"
29 #include "ldb_map_private.h"
32 /* Mapping message elements
33 * ======================== */
35 /* Map a message element into the remote partition. */
36 static struct ldb_message_element
*ldb_msg_el_map_local(struct ldb_module
*module
, void *mem_ctx
, const struct ldb_map_attribute
*map
, const struct ldb_message_element
*old
)
38 struct ldb_message_element
*el
;
41 el
= talloc_zero(mem_ctx
, struct ldb_message_element
);
47 el
->num_values
= old
->num_values
;
48 el
->values
= talloc_array(el
, struct ldb_val
, el
->num_values
);
49 if (el
->values
== NULL
) {
55 el
->name
= map_attr_map_local(el
, map
, old
->name
);
57 for (i
= 0; i
< el
->num_values
; i
++) {
58 el
->values
[i
] = ldb_val_map_local(module
, el
->values
, map
, &old
->values
[i
]);
64 /* Add a message element either to a local or to a remote message,
65 * depending on whether it goes into the local or remote partition. */
66 static int ldb_msg_el_partition(struct ldb_module
*module
, struct ldb_message
*local
, struct ldb_message
*remote
, const struct ldb_message
*msg
, const char *attr_name
, /* const char * const names[], */ const struct ldb_message_element
*old
)
68 const struct ldb_map_context
*data
= map_get_context(module
);
69 const struct ldb_map_attribute
*map
= map_attr_find_local(data
, attr_name
);
70 struct ldb_message_element
*el
=NULL
;
71 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
73 /* Unknown attribute: ignore */
75 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
76 "Not mapping attribute '%s': no mapping found",
86 if (map
->u
.convert
.convert_local
== NULL
) {
87 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
88 "Not mapping attribute '%s': "
89 "'convert_local' not set",
96 el
= ldb_msg_el_map_local(module
, remote
, map
, old
);
99 case LDB_MAP_GENERATE
:
100 if (map
->u
.generate
.generate_remote
== NULL
) {
101 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
102 "Not mapping attribute '%s': "
103 "'generate_remote' not set",
108 /* TODO: if this attr requires context:
109 * make sure all context attrs are mappable (in 'names')
110 * make sure all context attrs have already been mapped?
111 * maybe postpone generation until they have been mapped?
114 map
->u
.generate
.generate_remote(module
, map
->local_name
, msg
, remote
, local
);
122 return ldb_msg_add(remote
, el
, old
->flags
);
125 el
= talloc(local
, struct ldb_message_element
);
131 *el
= *old
; /* copy the old element */
133 return ldb_msg_add(local
, el
, old
->flags
);
137 * ================ */
139 /* Check whether a message will be (partially) mapped into the remote partition. */
140 static bool ldb_msg_check_remote(struct ldb_module
*module
, const struct ldb_message
*msg
)
142 const struct ldb_map_context
*data
= map_get_context(module
);
146 for (i
= 0; i
< msg
->num_elements
; i
++) {
147 ret
= map_attr_check_remote(data
, msg
->elements
[i
].name
);
156 /* Split message elements that stay in the local partition from those
157 * that are mapped into the remote partition. */
158 static int ldb_msg_partition(struct ldb_module
*module
, struct ldb_message
*local
, struct ldb_message
*remote
, const struct ldb_message
*msg
)
160 /* const char * const names[]; */
161 struct ldb_context
*ldb
;
165 ldb
= ldb_module_get_ctx(module
);
167 for (i
= 0; i
< msg
->num_elements
; i
++) {
168 /* Skip 'IS_MAPPED' */
169 if (ldb_attr_cmp(msg
->elements
[i
].name
, IS_MAPPED
) == 0) {
170 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "ldb_map: "
171 "Skipping attribute '%s'",
172 msg
->elements
[i
].name
);
176 ret
= ldb_msg_el_partition(module
, local
, remote
, msg
, msg
->elements
[i
].name
, &msg
->elements
[i
]);
186 static int map_add_do_local(struct map_context
*ac
);
187 static int map_modify_do_local(struct map_context
*ac
);
188 static int map_delete_do_local(struct map_context
*ac
);
189 static int map_rename_do_local(struct map_context
*ac
);
190 static int map_rename_do_fixup(struct map_context
*ac
);
191 static int map_rename_local_callback(struct ldb_request
*req
,
192 struct ldb_reply
*ares
);
195 /*****************************************************************************
196 * COMMON INBOUND functions
197 *****************************************************************************/
199 /* Store the DN of a single search result in context. */
200 static int map_search_self_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
202 struct ldb_context
*ldb
;
203 struct map_context
*ac
;
206 ac
= talloc_get_type(req
->context
, struct map_context
);
207 ldb
= ldb_module_get_ctx(ac
->module
);
210 return ldb_module_done(ac
->req
, NULL
, NULL
,
211 LDB_ERR_OPERATIONS_ERROR
);
213 if (ares
->error
!= LDB_SUCCESS
) {
214 return ldb_module_done(ac
->req
, ares
->controls
,
215 ares
->response
, ares
->error
);
218 /* We are interested only in the single reply */
220 case LDB_REPLY_ENTRY
:
221 /* We have already found a remote DN */
223 ldb_set_errstring(ldb
,
224 "Too many results!");
225 return ldb_module_done(ac
->req
, NULL
, NULL
,
226 LDB_ERR_OPERATIONS_ERROR
);
230 ac
->local_dn
= talloc_steal(ac
, ares
->message
->dn
);
235 switch (ac
->req
->operation
) {
237 ret
= map_modify_do_local(ac
);
240 ret
= map_delete_do_local(ac
);
243 ret
= map_rename_do_local(ac
);
246 /* if we get here we have definitely a problem */
247 ret
= LDB_ERR_OPERATIONS_ERROR
;
249 if (ret
!= LDB_SUCCESS
) {
250 return ldb_module_done(ac
->req
, NULL
, NULL
,
251 LDB_ERR_OPERATIONS_ERROR
);
255 /* ignore referrals */
263 /* Build a request to search the local record by its DN. */
264 static int map_search_self_req(struct ldb_request
**req
,
265 struct map_context
*ac
,
268 /* attrs[] is returned from this function in
269 * ac->search_req->op.search.attrs, so it must be static, as
270 * otherwise the compiler can put it on the stack */
271 static const char * const attrs
[] = { IS_MAPPED
, NULL
};
272 struct ldb_parse_tree
*tree
;
274 /* Limit search to records with 'IS_MAPPED' present */
275 tree
= ldb_parse_tree(ac
, "(" IS_MAPPED
"=*)");
278 return LDB_ERR_OPERATIONS_ERROR
;
281 *req
= map_search_base_req(ac
, dn
, attrs
, tree
,
282 ac
, map_search_self_callback
);
284 return LDB_ERR_OPERATIONS_ERROR
;
290 static int map_op_local_callback(struct ldb_request
*req
,
291 struct ldb_reply
*ares
)
293 struct ldb_context
*ldb
;
294 struct map_context
*ac
;
297 ac
= talloc_get_type(req
->context
, struct map_context
);
298 ldb
= ldb_module_get_ctx(ac
->module
);
301 return ldb_module_done(ac
->req
, NULL
, NULL
,
302 LDB_ERR_OPERATIONS_ERROR
);
304 if (ares
->error
!= LDB_SUCCESS
) {
305 return ldb_module_done(ac
->req
, ares
->controls
,
306 ares
->response
, ares
->error
);
309 if (ares
->type
!= LDB_REPLY_DONE
) {
310 ldb_set_errstring(ldb
, "Invalid reply type!");
311 return ldb_module_done(ac
->req
, NULL
, NULL
,
312 LDB_ERR_OPERATIONS_ERROR
);
315 /* Do the remote request. */
316 ret
= ldb_next_remote_request(ac
->module
, ac
->remote_req
);
317 if (ret
!= LDB_SUCCESS
) {
318 return ldb_module_done(ac
->req
, NULL
, NULL
,
319 LDB_ERR_OPERATIONS_ERROR
);
325 static int map_op_remote_callback(struct ldb_request
*req
,
326 struct ldb_reply
*ares
)
328 struct ldb_context
*ldb
;
329 struct map_context
*ac
;
331 ac
= talloc_get_type(req
->context
, struct map_context
);
332 ldb
= ldb_module_get_ctx(ac
->module
);
335 return ldb_module_done(ac
->req
, NULL
, NULL
,
336 LDB_ERR_OPERATIONS_ERROR
);
338 if (ares
->error
!= LDB_SUCCESS
) {
339 return ldb_module_done(ac
->req
, ares
->controls
,
340 ares
->response
, ares
->error
);
343 if (ares
->type
!= LDB_REPLY_DONE
) {
344 ldb_set_errstring(ldb
, "Invalid reply type!");
345 return ldb_module_done(ac
->req
, NULL
, NULL
,
346 LDB_ERR_OPERATIONS_ERROR
);
349 return ldb_module_done(ac
->req
, ares
->controls
,
350 ares
->response
, ares
->error
);
354 /*****************************************************************************
356 *****************************************************************************/
360 int map_add(struct ldb_module
*module
, struct ldb_request
*req
)
362 const struct ldb_message
*msg
= req
->op
.add
.message
;
363 struct ldb_context
*ldb
;
364 struct map_context
*ac
;
365 struct ldb_message
*remote_msg
;
368 ldb
= ldb_module_get_ctx(module
);
370 /* Do not manipulate our control entries */
371 if (ldb_dn_is_special(msg
->dn
)) {
372 return ldb_next_request(module
, req
);
375 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
376 if (!ldb_dn_check_local(module
, msg
->dn
)) {
377 return ldb_next_request(module
, req
);
380 /* No mapping needed, fail */
381 if (!ldb_msg_check_remote(module
, msg
)) {
382 return LDB_ERR_OPERATIONS_ERROR
;
385 /* Prepare context and handle */
386 ac
= map_init_context(module
, req
);
388 return LDB_ERR_OPERATIONS_ERROR
;
392 /* Prepare the local message */
393 ac
->local_msg
= ldb_msg_new(ac
);
394 if (ac
->local_msg
== NULL
) {
396 return LDB_ERR_OPERATIONS_ERROR
;
398 ac
->local_msg
->dn
= msg
->dn
;
400 /* Prepare the remote message */
401 remote_msg
= ldb_msg_new(ac
);
402 if (remote_msg
== NULL
) {
404 return LDB_ERR_OPERATIONS_ERROR
;
406 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
408 /* Split local from remote message */
409 ldb_msg_partition(module
, ac
->local_msg
, remote_msg
, msg
);
411 /* Prepare the remote operation */
412 ret
= ldb_build_add_req(&ac
->remote_req
, ldb
,
415 ac
, map_op_remote_callback
,
417 if (ret
!= LDB_SUCCESS
) {
418 return LDB_ERR_OPERATIONS_ERROR
;
421 if ((ac
->local_msg
->num_elements
== 0) ||
422 ( ! map_check_local_db(ac
->module
))) {
423 /* No local data or db, just run the remote request */
424 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
427 /* Store remote DN in 'IS_MAPPED' */
428 /* TODO: use GUIDs here instead */
429 ret
= ldb_msg_add_linearized_dn(ac
->local_msg
, IS_MAPPED
,
431 if (ret
!= LDB_SUCCESS
) {
432 return LDB_ERR_OPERATIONS_ERROR
;
435 return map_add_do_local(ac
);
438 /* Add the local record. */
439 static int map_add_do_local(struct map_context
*ac
)
441 struct ldb_request
*local_req
;
442 struct ldb_context
*ldb
;
445 ldb
= ldb_module_get_ctx(ac
->module
);
447 /* Prepare the local operation */
448 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
452 map_op_local_callback
,
454 if (ret
!= LDB_SUCCESS
) {
455 return LDB_ERR_OPERATIONS_ERROR
;
457 return ldb_next_request(ac
->module
, local_req
);
460 /*****************************************************************************
462 *****************************************************************************/
464 /* Modify a record. */
465 int map_modify(struct ldb_module
*module
, struct ldb_request
*req
)
467 const struct ldb_message
*msg
= req
->op
.mod
.message
;
468 struct ldb_request
*search_req
;
469 struct ldb_message
*remote_msg
;
470 struct ldb_context
*ldb
;
471 struct map_context
*ac
;
474 ldb
= ldb_module_get_ctx(module
);
476 /* Do not manipulate our control entries */
477 if (ldb_dn_is_special(msg
->dn
)) {
478 return ldb_next_request(module
, req
);
481 /* No mapping requested (perhaps no DN mapping specified), skip to next module */
482 if (!ldb_dn_check_local(module
, msg
->dn
)) {
483 return ldb_next_request(module
, req
);
486 /* No mapping needed, skip to next module */
487 /* TODO: What if the remote part exists, the local doesn't,
488 * and this request wants to modify local data and thus
489 * add the local record? */
490 if (!ldb_msg_check_remote(module
, msg
)) {
491 return LDB_ERR_OPERATIONS_ERROR
;
494 /* Prepare context and handle */
495 ac
= map_init_context(module
, req
);
497 return LDB_ERR_OPERATIONS_ERROR
;
500 /* Prepare the local message */
501 ac
->local_msg
= ldb_msg_new(ac
);
502 if (ac
->local_msg
== NULL
) {
504 return LDB_ERR_OPERATIONS_ERROR
;
506 ac
->local_msg
->dn
= msg
->dn
;
508 /* Prepare the remote message */
509 remote_msg
= ldb_msg_new(ac
->remote_req
);
510 if (remote_msg
== NULL
) {
512 return LDB_ERR_OPERATIONS_ERROR
;
514 remote_msg
->dn
= ldb_dn_map_local(ac
->module
, remote_msg
, msg
->dn
);
516 /* Split local from remote message */
517 ldb_msg_partition(module
, ac
->local_msg
, remote_msg
, msg
);
519 /* Prepare the remote operation */
520 ret
= ldb_build_mod_req(&ac
->remote_req
, ldb
,
523 ac
, map_op_remote_callback
,
525 if (ret
!= LDB_SUCCESS
) {
526 return LDB_ERR_OPERATIONS_ERROR
;
529 if ((ac
->local_msg
->num_elements
== 0) ||
530 ( ! map_check_local_db(ac
->module
))) {
531 /* No local data or db, just run the remote request */
532 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
535 /* prepare the search operation */
536 ret
= map_search_self_req(&search_req
, ac
, msg
->dn
);
537 if (ret
!= LDB_SUCCESS
) {
538 return LDB_ERR_OPERATIONS_ERROR
;
541 return ldb_next_request(module
, search_req
);
544 /* Modify the local record. */
545 static int map_modify_do_local(struct map_context
*ac
)
547 struct ldb_request
*local_req
;
548 struct ldb_context
*ldb
;
551 ldb
= ldb_module_get_ctx(ac
->module
);
553 if (ac
->local_dn
== NULL
) {
554 /* No local record present, add it instead */
555 /* Add local 'IS_MAPPED' */
556 /* TODO: use GUIDs here instead */
557 if (ldb_msg_add_empty(ac
->local_msg
, IS_MAPPED
,
558 LDB_FLAG_MOD_ADD
, NULL
) != 0) {
559 return LDB_ERR_OPERATIONS_ERROR
;
561 ret
= ldb_msg_add_linearized_dn(ac
->local_msg
, IS_MAPPED
,
562 ac
->remote_req
->op
.mod
.message
->dn
);
564 return LDB_ERR_OPERATIONS_ERROR
;
567 /* Prepare the local operation */
568 ret
= ldb_build_add_req(&local_req
, ldb
, ac
,
572 map_op_local_callback
,
574 if (ret
!= LDB_SUCCESS
) {
575 return LDB_ERR_OPERATIONS_ERROR
;
578 /* Prepare the local operation */
579 ret
= ldb_build_mod_req(&local_req
, ldb
, ac
,
583 map_op_local_callback
,
585 if (ret
!= LDB_SUCCESS
) {
586 return LDB_ERR_OPERATIONS_ERROR
;
590 return ldb_next_request(ac
->module
, local_req
);
593 /*****************************************************************************
595 *****************************************************************************/
597 /* Delete a record. */
598 int map_delete(struct ldb_module
*module
, struct ldb_request
*req
)
600 struct ldb_request
*search_req
;
601 struct ldb_context
*ldb
;
602 struct map_context
*ac
;
605 ldb
= ldb_module_get_ctx(module
);
607 /* Do not manipulate our control entries */
608 if (ldb_dn_is_special(req
->op
.del
.dn
)) {
609 return ldb_next_request(module
, req
);
612 /* No mapping requested (perhaps no DN mapping specified).
613 * Skip to next module */
614 if (!ldb_dn_check_local(module
, req
->op
.del
.dn
)) {
615 return ldb_next_request(module
, req
);
618 /* Prepare context and handle */
619 ac
= map_init_context(module
, req
);
621 return LDB_ERR_OPERATIONS_ERROR
;
624 /* Prepare the remote operation */
625 ret
= ldb_build_del_req(&ac
->remote_req
, ldb
, ac
,
626 ldb_dn_map_local(module
, ac
, req
->op
.del
.dn
),
629 map_op_remote_callback
,
631 if (ret
!= LDB_SUCCESS
) {
632 return LDB_ERR_OPERATIONS_ERROR
;
635 /* No local db, just run the remote request */
636 if (!map_check_local_db(ac
->module
)) {
637 /* Do the remote request. */
638 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
641 /* Prepare the search operation */
642 ret
= map_search_self_req(&search_req
, ac
, req
->op
.del
.dn
);
643 if (ret
!= LDB_SUCCESS
) {
645 return LDB_ERR_OPERATIONS_ERROR
;
648 return ldb_next_request(module
, search_req
);
651 /* Delete the local record. */
652 static int map_delete_do_local(struct map_context
*ac
)
654 struct ldb_request
*local_req
;
655 struct ldb_context
*ldb
;
658 ldb
= ldb_module_get_ctx(ac
->module
);
660 /* No local record, continue remotely */
661 if (ac
->local_dn
== NULL
) {
662 /* Do the remote request. */
663 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
666 /* Prepare the local operation */
667 ret
= ldb_build_del_req(&local_req
, ldb
, ac
,
671 map_op_local_callback
,
673 if (ret
!= LDB_SUCCESS
) {
674 return LDB_ERR_OPERATIONS_ERROR
;
676 return ldb_next_request(ac
->module
, local_req
);
679 /*****************************************************************************
681 *****************************************************************************/
683 /* Rename a record. */
684 int map_rename(struct ldb_module
*module
, struct ldb_request
*req
)
686 struct ldb_request
*search_req
;
687 struct ldb_context
*ldb
;
688 struct map_context
*ac
;
691 ldb
= ldb_module_get_ctx(module
);
693 /* Do not manipulate our control entries */
694 if (ldb_dn_is_special(req
->op
.rename
.olddn
)) {
695 return ldb_next_request(module
, req
);
698 /* No mapping requested (perhaps no DN mapping specified).
699 * Skip to next module */
700 if ((!ldb_dn_check_local(module
, req
->op
.rename
.olddn
)) &&
701 (!ldb_dn_check_local(module
, req
->op
.rename
.newdn
))) {
702 return ldb_next_request(module
, req
);
705 /* Rename into/out of the mapped partition requested, bail out */
706 if (!ldb_dn_check_local(module
, req
->op
.rename
.olddn
) ||
707 !ldb_dn_check_local(module
, req
->op
.rename
.newdn
)) {
708 return LDB_ERR_AFFECTS_MULTIPLE_DSAS
;
711 /* Prepare context and handle */
712 ac
= map_init_context(module
, req
);
714 return LDB_ERR_OPERATIONS_ERROR
;
717 /* Prepare the remote operation */
718 ret
= ldb_build_rename_req(&ac
->remote_req
, ldb
, ac
,
719 ldb_dn_map_local(module
, ac
, req
->op
.rename
.olddn
),
720 ldb_dn_map_local(module
, ac
, req
->op
.rename
.newdn
),
722 ac
, map_op_remote_callback
,
724 if (ret
!= LDB_SUCCESS
) {
725 return LDB_ERR_OPERATIONS_ERROR
;
728 /* No local db, just run the remote request */
729 if (!map_check_local_db(ac
->module
)) {
730 /* Do the remote request. */
731 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
734 /* Prepare the search operation */
735 ret
= map_search_self_req(&search_req
, ac
, req
->op
.rename
.olddn
);
736 if (ret
!= LDB_SUCCESS
) {
738 return LDB_ERR_OPERATIONS_ERROR
;
741 return ldb_next_request(module
, search_req
);
744 /* Rename the local record. */
745 static int map_rename_do_local(struct map_context
*ac
)
747 struct ldb_request
*local_req
;
748 struct ldb_context
*ldb
;
751 ldb
= ldb_module_get_ctx(ac
->module
);
753 /* No local record, continue remotely */
754 if (ac
->local_dn
== NULL
) {
755 /* Do the remote request. */
756 return ldb_next_remote_request(ac
->module
, ac
->remote_req
);
759 /* Prepare the local operation */
760 ret
= ldb_build_rename_req(&local_req
, ldb
, ac
,
761 ac
->req
->op
.rename
.olddn
,
762 ac
->req
->op
.rename
.newdn
,
765 map_rename_local_callback
,
767 if (ret
!= LDB_SUCCESS
) {
768 return LDB_ERR_OPERATIONS_ERROR
;
771 return ldb_next_request(ac
->module
, local_req
);
774 static int map_rename_local_callback(struct ldb_request
*req
,
775 struct ldb_reply
*ares
)
777 struct ldb_context
*ldb
;
778 struct map_context
*ac
;
781 ac
= talloc_get_type(req
->context
, struct map_context
);
782 ldb
= ldb_module_get_ctx(ac
->module
);
785 return ldb_module_done(ac
->req
, NULL
, NULL
,
786 LDB_ERR_OPERATIONS_ERROR
);
788 if (ares
->error
!= LDB_SUCCESS
) {
789 return ldb_module_done(ac
->req
, ares
->controls
,
790 ares
->response
, ares
->error
);
793 if (ares
->type
!= LDB_REPLY_DONE
) {
794 ldb_set_errstring(ldb
, "Invalid reply type!");
795 return ldb_module_done(ac
->req
, NULL
, NULL
,
796 LDB_ERR_OPERATIONS_ERROR
);
799 /* proceed with next step */
800 ret
= map_rename_do_fixup(ac
);
801 if (ret
!= LDB_SUCCESS
) {
802 return ldb_module_done(ac
->req
, NULL
, NULL
,
803 LDB_ERR_OPERATIONS_ERROR
);
809 /* Update the local 'IS_MAPPED' attribute. */
810 static int map_rename_do_fixup(struct map_context
*ac
)
812 struct ldb_request
*local_req
;
814 /* Prepare the fixup operation */
815 /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
816 local_req
= map_build_fixup_req(ac
,
817 ac
->req
->op
.rename
.newdn
,
818 ac
->remote_req
->op
.rename
.newdn
,
820 map_op_local_callback
);
821 if (local_req
== NULL
) {
822 return LDB_ERR_OPERATIONS_ERROR
;
825 return ldb_next_request(ac
->module
, local_req
);