1 /* op.c - relay backend operations */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2004-2005 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( struct slap_op *op, struct slap_rep *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, struct slap_op *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( struct slap_op *op, struct slap_rep *rs, int err )
60 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
61 BackendDB *bd = ri->ri_bd;
64 bd = select_backend( &op->o_req_ndn, 0, 1 );
65 if ( bd == op->o_bd ) {
66 if ( err > LDAP_SUCCESS ) {
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_ref = referral_rewrite( default_referral,
78 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
80 rs->sr_ref = default_referral;
83 rs->sr_err = LDAP_REFERRAL;
84 send_ldap_result( op, rs );
86 if ( rs->sr_ref != default_referral ) {
87 ber_bvarray_free( rs->sr_ref );
91 /* NOTE: err is LDAP_INVALID_CREDENTIALS for bind,
92 * LDAP_NO_SUCH_OBJECT for other operations.
93 * noSuchObject cannot be returned by bind */
95 send_ldap_result( op, rs );
103 relay_back_op_bind( struct slap_op *op, struct slap_rep *rs )
108 bd = relay_back_select_backend( op, rs, LDAP_INVALID_CREDENTIALS );
114 BackendDB *be = op->o_bd;
117 relay_back_add_cb( &cb, op );
120 rc = ( bd->be_bind )( op, rs );
123 if ( op->o_callback == &cb ) {
124 op->o_callback = op->o_callback->sc_next;
128 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
129 "operation not supported "
130 "within naming context" );
137 relay_back_op_unbind( struct slap_op *op, struct slap_rep *rs )
139 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
145 bd = select_backend( &op->o_req_ndn, 0, 1 );
148 if ( bd && bd->be_unbind ) {
149 BackendDB *be = op->o_bd;
152 relay_back_add_cb( &cb, op );
155 rc = ( bd->be_unbind )( op, rs );
158 if ( op->o_callback == &cb ) {
159 op->o_callback = op->o_callback->sc_next;
168 relay_back_op_search( struct slap_op *op, struct slap_rep *rs )
173 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
178 if ( bd->be_search ) {
179 BackendDB *be = op->o_bd;
182 relay_back_add_cb( &cb, op );
185 rc = ( bd->be_search )( op, rs );
188 if ( op->o_callback == &cb ) {
189 op->o_callback = op->o_callback->sc_next;
193 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
194 "operation not supported "
195 "within naming context" );
203 relay_back_op_compare( struct slap_op *op, struct slap_rep *rs )
208 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
213 if ( bd->be_compare ) {
214 BackendDB *be = op->o_bd;
217 relay_back_add_cb( &cb, op );
220 rc = ( bd->be_compare )( op, rs );
223 if ( op->o_callback == &cb ) {
224 op->o_callback = op->o_callback->sc_next;
228 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
229 "operation not supported "
230 "within naming context" );
238 relay_back_op_modify( struct slap_op *op, struct slap_rep *rs )
243 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
248 if ( bd->be_modify ) {
249 BackendDB *be = op->o_bd;
252 relay_back_add_cb( &cb, op );
255 rc = ( bd->be_modify )( op, rs );
258 if ( op->o_callback == &cb ) {
259 op->o_callback = op->o_callback->sc_next;
263 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
264 "operation not supported "
265 "within naming context" );
273 relay_back_op_modrdn( struct slap_op *op, struct slap_rep *rs )
278 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
283 if ( bd->be_modrdn ) {
284 BackendDB *be = op->o_bd;
287 relay_back_add_cb( &cb, op );
290 rc = ( bd->be_modrdn )( op, rs );
293 if ( op->o_callback == &cb ) {
294 op->o_callback = op->o_callback->sc_next;
298 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
299 "operation not supported "
300 "within naming context" );
308 relay_back_op_add( struct slap_op *op, struct slap_rep *rs )
313 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
319 BackendDB *be = op->o_bd;
322 relay_back_add_cb( &cb, op );
325 rc = ( bd->be_add )( op, rs );
328 if ( op->o_callback == &cb ) {
329 op->o_callback = op->o_callback->sc_next;
333 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
334 "operation not supported "
335 "within naming context" );
343 relay_back_op_delete( struct slap_op *op, struct slap_rep *rs )
348 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
353 if ( bd->be_delete ) {
354 BackendDB *be = op->o_bd;
357 relay_back_add_cb( &cb, op );
360 rc = ( bd->be_delete )( op, rs );
363 if ( op->o_callback == &cb ) {
364 op->o_callback = op->o_callback->sc_next;
373 relay_back_op_abandon( struct slap_op *op, struct slap_rep *rs )
378 bd = relay_back_select_backend( op, rs, -1 );
383 if ( bd->be_abandon ) {
384 BackendDB *be = op->o_bd;
387 relay_back_add_cb( &cb, op );
390 rc = ( bd->be_abandon )( op, rs );
393 if ( op->o_callback == &cb ) {
394 op->o_callback = op->o_callback->sc_next;
403 relay_back_op_cancel( struct slap_op *op, struct slap_rep *rs )
408 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
413 if ( bd->be_cancel ) {
414 BackendDB *be = op->o_bd;
417 relay_back_add_cb( &cb, op );
420 rc = ( bd->be_cancel )( op, rs );
423 if ( op->o_callback == &cb ) {
424 op->o_callback = op->o_callback->sc_next;
428 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
429 "operation not supported "
430 "within naming context" );
438 relay_back_op_extended( struct slap_op *op, struct slap_rep *rs )
443 bd = relay_back_select_backend( op, rs, LDAP_NO_SUCH_OBJECT );
448 if ( bd->be_extended ) {
449 BackendDB *be = op->o_bd;
452 relay_back_add_cb( &cb, op );
455 rc = ( bd->be_extended )( op, rs );
458 if ( op->o_callback == &cb ) {
459 op->o_callback = op->o_callback->sc_next;
463 send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
464 "operation not supported "
465 "within naming context" );
473 relay_back_entry_release_rw( struct slap_op *op, Entry *e, int rw )
475 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
481 bd = select_backend( &op->o_req_ndn, 0, 1 );
487 if ( bd->be_release ) {
488 BackendDB *be = op->o_bd;
491 rc = ( bd->be_release )( op, e, rw );
500 relay_back_entry_get_rw( struct slap_op *op, struct berval *ndn,
501 ObjectClass *oc, AttributeDescription *at, int rw, Entry **e )
503 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
509 bd = select_backend( &op->o_req_ndn, 0, 1 );
515 if ( bd->be_fetch ) {
516 BackendDB *be = op->o_bd;
519 rc = ( bd->be_fetch )( op, ndn, oc, at, rw, e );
528 * NOTE: even the existence of this function is questionable: we cannot
529 * pass the bi_chk_referrals() call thru the rwm overlay because there
530 * is no way to rewrite the req_dn back; but then relay_back_chk_referrals()
531 * is passing the target database a DN that likely does not belong to its
532 * naming context... mmmh.
535 relay_back_chk_referrals( struct slap_op *op, struct slap_rep *rs )
540 bd = relay_back_select_backend( op, rs, LDAP_SUCCESS );
541 /* FIXME: this test only works if there are no overlays, so
542 * it is nearly useless; if made stricter, no nested back-relays
543 * can be instantiated... too bad. */
544 if ( bd == NULL || bd == op->o_bd ) {
548 /* no nested back-relays... */
549 if ( overlay_is_over( bd ) ) {
550 slap_overinfo *oi = (slap_overinfo *)bd->bd_info->bi_private;
552 if ( oi->oi_orig == op->o_bd->bd_info ) {
557 if ( bd->be_chk_referrals ) {
558 BackendDB *be = op->o_bd;
561 relay_back_add_cb( &cb, op );
564 rc = ( bd->be_chk_referrals )( op, rs );
567 if ( op->o_callback == &cb ) {
568 op->o_callback = op->o_callback->sc_next;
577 relay_back_operational( struct slap_op *op, struct slap_rep *rs )
579 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
585 bd = select_backend( &op->o_req_ndn, 0, 1 );
591 if ( bd->be_operational ) {
592 BackendDB *be = op->o_bd;
595 relay_back_add_cb( &cb, op );
598 rc = ( bd->be_operational )( op, rs );
601 if ( op->o_callback == &cb ) {
602 op->o_callback = op->o_callback->sc_next;
611 relay_back_has_subordinates( struct slap_op *op, Entry *e, int *hasSubs )
613 relay_back_info *ri = (relay_back_info *)op->o_bd->be_private;
619 bd = select_backend( &op->o_req_ndn, 0, 1 );
625 if ( bd->be_has_subordinates ) {
626 BackendDB *be = op->o_bd;
629 rc = ( bd->be_has_subordinates )( op, e, hasSubs );
638 relay_back_connection_init( BackendDB *bd, struct slap_conn *c )
640 relay_back_info *ri = (relay_back_info *)bd->be_private;
647 if ( bd->be_connection_init ) {
648 return ( bd->be_connection_init )( bd, c );
655 relay_back_connection_destroy( BackendDB *bd, struct slap_conn *c )
657 relay_back_info *ri = (relay_back_info *)bd->be_private;
664 if ( bd->be_connection_destroy ) {
665 return ( bd->be_connection_destroy )( bd, c );
673 * FIXME: must implement tools as well