1 /* op.c - relay backend operations */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2004-2007 The OpenLDAP Foundation.
5 * Portions Copyright 2004 Pierangelo Masarati.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
17 * This work was initially developed by Pierangelo Masarati for inclusion
18 * in OpenLDAP Software.
26 #include "back-relay.h"
29 relay_back_swap_bd( Operation *op, SlapReply *rs )
31 slap_callback *cb = op->o_callback;
32 BackendDB *be = op->o_bd;
34 op->o_bd = cb->sc_private;
37 return SLAP_CB_CONTINUE;
41 relay_back_add_cb( slap_callback *cb, Operation *op )
43 cb->sc_next = op->o_callback;
44 cb->sc_response = relay_back_swap_bd;
45 cb->sc_cleanup = relay_back_swap_bd;
46 cb->sc_private = op->o_bd;
51 * selects the backend if not enforced at config;
52 * in case of failure, behaves based on err:
53 * -1 don't send result
54 * LDAP_SUCCESS don't send result; may send referral
55 * any valid error send as error result
58 relay_back_select_backend( Operation *op, SlapReply *rs, int err, int dosend )
60 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
61 BackendDB *bd = ri->ri_bd;
63 if ( bd == NULL && !BER_BVISNULL( &op->o_req_ndn ) ) {
64 bd = select_backend( &op->o_req_ndn, 0, 1 );
65 if ( bd == op->o_bd ) {
66 if ( err > LDAP_SUCCESS && dosend ) {
67 send_ldap_error( op, rs,
68 LDAP_UNWILLING_TO_PERFORM,
69 "back-relay would call self" );
75 if ( bd == NULL && err > -1 ) {
76 if ( default_referral ) {
77 rs->sr_err = LDAP_REFERRAL;
79 rs->sr_ref = referral_rewrite(
84 rs->sr_ref = default_referral;
87 send_ldap_result( op, rs );
89 if ( rs->sr_ref != default_referral ) {
90 ber_bvarray_free( rs->sr_ref );
95 /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind,
96 * LDAP_NO_SUCH_OBJECT for other operations.
97 * noSuchObject cannot be returned by bind */
100 send_ldap_result( op, rs );
109 relay_back_op_bind( Operation *op, SlapReply *rs )
114 bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS, 1 );
120 BackendDB *be = op->o_bd;
123 relay_back_add_cb( &cb, op );
126 rc = bd->be_bind( op, rs );
129 if ( op->o_callback == &cb ) {
130 op->o_callback = op->o_callback->sc_next;
134 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
135 "operation not supported "
136 "within naming context" );
143 relay_back_op_unbind( Operation *op, SlapReply *rs )
148 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
153 if ( bd && bd->be_unbind ) {
154 BackendDB *be = op->o_bd;
157 relay_back_add_cb( &cb, op );
160 rc = bd->be_unbind( op, rs );
163 if ( op->o_callback == &cb ) {
164 op->o_callback = op->o_callback->sc_next;
173 relay_back_op_search( Operation *op, SlapReply *rs )
178 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
183 if ( bd->be_search ) {
184 BackendDB *be = op->o_bd;
187 relay_back_add_cb( &cb, op );
190 rc = bd->be_search( op, rs );
193 if ( op->o_callback == &cb ) {
194 op->o_callback = op->o_callback->sc_next;
198 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
199 "operation not supported "
200 "within naming context" );
208 relay_back_op_compare( Operation *op, SlapReply *rs )
213 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
218 if ( bd->be_compare ) {
219 BackendDB *be = op->o_bd;
222 relay_back_add_cb( &cb, op );
225 rc = bd->be_compare( op, rs );
228 if ( op->o_callback == &cb ) {
229 op->o_callback = op->o_callback->sc_next;
233 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
234 "operation not supported "
235 "within naming context" );
243 relay_back_op_modify( Operation *op, SlapReply *rs )
248 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
253 if ( bd->be_modify ) {
254 BackendDB *be = op->o_bd;
257 relay_back_add_cb( &cb, op );
260 rc = bd->be_modify( op, rs );
263 if ( op->o_callback == &cb ) {
264 op->o_callback = op->o_callback->sc_next;
268 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
269 "operation not supported "
270 "within naming context" );
278 relay_back_op_modrdn( Operation *op, SlapReply *rs )
283 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
288 if ( bd->be_modrdn ) {
289 BackendDB *be = op->o_bd;
292 relay_back_add_cb( &cb, op );
295 rc = bd->be_modrdn( op, rs );
298 if ( op->o_callback == &cb ) {
299 op->o_callback = op->o_callback->sc_next;
303 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
304 "operation not supported "
305 "within naming context" );
313 relay_back_op_add( Operation *op, SlapReply *rs )
318 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
324 BackendDB *be = op->o_bd;
327 relay_back_add_cb( &cb, op );
330 rc = bd->be_add( op, rs );
333 if ( op->o_callback == &cb ) {
334 op->o_callback = op->o_callback->sc_next;
338 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
339 "operation not supported "
340 "within naming context" );
348 relay_back_op_delete( Operation *op, SlapReply *rs )
353 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 1 );
358 if ( bd->be_delete ) {
359 BackendDB *be = op->o_bd;
362 relay_back_add_cb( &cb, op );
365 rc = bd->be_delete( op, rs );
368 if ( op->o_callback == &cb ) {
369 op->o_callback = op->o_callback->sc_next;
378 relay_back_op_abandon( Operation *op, SlapReply *rs )
383 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
388 if ( bd->be_abandon ) {
389 BackendDB *be = op->o_bd;
392 relay_back_add_cb( &cb, op );
395 rc = bd->be_abandon( op, rs );
398 if ( op->o_callback == &cb ) {
399 op->o_callback = op->o_callback->sc_next;
408 relay_back_op_cancel( Operation *op, SlapReply *rs )
413 bd = relay_back_select_backend( op, rs, LDAP_CANNOT_CANCEL, 0 );
418 if ( bd->be_cancel ) {
419 BackendDB *be = op->o_bd;
422 relay_back_add_cb( &cb, op );
425 rc = bd->be_cancel( op, rs );
428 if ( op->o_callback == &cb ) {
429 op->o_callback = op->o_callback->sc_next;
433 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
434 "operation not supported "
435 "within naming context" );
443 relay_back_op_extended( Operation *op, SlapReply *rs )
448 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT, 0 );
453 if ( bd->be_extended ) {
454 BackendDB *be = op->o_bd;
457 relay_back_add_cb( &cb, op );
460 rc = bd->be_extended( op, rs );
463 if ( op->o_callback == &cb ) {
464 op->o_callback = op->o_callback->sc_next;
468 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
469 "operation not supported "
470 "within naming context" );
478 relay_back_entry_release_rw( Operation *op, Entry *e, int rw )
480 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
486 bd = select_backend( &op->o_req_ndn, 0, 1 );
492 if ( bd->be_release ) {
493 BackendDB *be = op->o_bd;
496 rc = bd->be_release( op, e, rw );
505 relay_back_entry_get_rw( Operation *op, struct berval *ndn,
506 ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
508 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
514 bd = select_backend( &op->o_req_ndn, 0, 1 );
520 if ( bd->be_fetch ) {
521 BackendDB *be = op->o_bd;
524 rc = bd->be_fetch( op, ndn, oc, at, rw, e );
533 * NOTE: even the existence of this function is questionable: we cannot
534 * pass the bi_chk_referrals() call thru the rwm overlay because there
535 * is no way to rewrite the req_dn back; but then relay_back_chk_referrals()
536 * is passing the target database a DN that likely does not belong to its
537 * naming context... mmmh.
540 relay_back_chk_referrals( Operation *op, SlapReply *rs )
545 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 1 );
546 /* FIXME: this test only works if there are no overlays, so
547 * it is nearly useless; if made stricter, no nested back-relays
548 * can be instantiated... too bad. */
549 if ( bd == NULL || bd == op->o_bd ) {
553 /* no nested back-relays... */
554 if ( overlay_is_over( bd ) ) {
555 slap_overinfo *oi = (slap_overinfo *)bd->bd_info->bi_private;
557 if ( oi->oi_orig == op->o_bd->bd_info ) {
562 if ( bd->be_chk_referrals ) {
563 BackendDB *be = op->o_bd;
566 relay_back_add_cb( &cb, op );
569 rc = bd->be_chk_referrals( op, rs );
572 if ( op->o_callback == &cb ) {
573 op->o_callback = op->o_callback->sc_next;
582 relay_back_operational( Operation *op, SlapReply *rs )
587 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS, 0 );
588 /* FIXME: this test only works if there are no overlays, so
589 * it is nearly useless; if made stricter, no nested back-relays
590 * can be instantiated... too bad. */
591 if ( bd == NULL || bd == op->o_bd ) {
595 if ( bd->be_operational ) {
596 BackendDB *be = op->o_bd;
599 relay_back_add_cb( &cb, op );
602 rc = bd->be_operational( op, rs );
605 if ( op->o_callback == &cb ) {
606 op->o_callback = op->o_callback->sc_next;
615 relay_back_has_subordinates( Operation *op, Entry *e, int *hasSubs )
617 SlapReply rs = { 0 };
621 bd = relay_back_select_backend( op, &rs, LDAP_SUCCESS, 0 );
622 /* FIXME: this test only works if there are no overlays, so
623 * it is nearly useless; if made stricter, no nested back-relays
624 * can be instantiated... too bad. */
625 if ( bd == NULL || bd == op->o_bd ) {
629 if ( bd->be_has_subordinates ) {
630 BackendDB *be = op->o_bd;
633 rc = bd->be_has_subordinates( op, e, hasSubs );
642 relay_back_connection_init( BackendDB *bd, Connection *c )
644 relay_back_info *ri = (relay_back_info *)bd->be_private;
651 if ( bd->be_connection_init ) {
652 return bd->be_connection_init( bd, c );
659 relay_back_connection_destroy( BackendDB *bd, Connection *c )
661 relay_back_info *ri = (relay_back_info *)bd->be_private;
668 if ( bd->be_connection_destroy ) {
669 return bd->be_connection_destroy( bd, c );
677 * FIXME: must implement tools as well