1 /* backover.c - backend overlay routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2008 The OpenLDAP Foundation.
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 /* Functions to overlay other modules over a backend. */
23 #include <ac/string.h>
24 #include <ac/socket.h>
30 static slap_overinst *overlays;
46 slap_overinfo *oi = be->bd_info->bi_private;
47 slap_overinst *on = oi->oi_list;
48 BackendInfo *bi_orig = be->bd_info;
52 func = &oi->oi_orig->bi_db_open;
54 be->bd_info = oi->oi_orig;
55 rc = func[which]( be, cr );
58 for (; on && rc == 0; on=on->on_next) {
59 be->bd_info = &on->on_bi;
60 func = &on->on_bi.bi_db_open;
62 rc = func[which]( be, cr );
65 be->bd_info = bi_orig;
78 slap_overinfo *oi = be->bd_info->bi_private;
79 slap_overinst *on = oi->oi_list;
80 BackendInfo *bi_orig = be->bd_info;
81 struct ConfigOCs *be_cf_ocs = be->be_cf_ocs;
85 if ( oi->oi_orig->bi_db_config ) {
86 be->bd_info = oi->oi_orig;
87 be->be_cf_ocs = oi->oi_orig->bi_cf_ocs;
88 rc = oi->oi_orig->bi_db_config( be, fname, lineno,
91 if ( be->bd_info != oi->oi_orig ) {
93 slap_overinst *on2, **onp;
97 /* a database added an overlay;
98 * work it around... */
99 assert( overlay_is_over( be ) );
101 oi2 = ( slap_overinfo * )be->bd_info->bi_private;
104 /* need to put a uniqueness check here as well;
105 * note that in principle there could be more than
106 * one overlay as a result of multiple calls to
107 * overlay_config() */
108 be2.bd_info = (BackendInfo *)oi;
110 for ( i = 0, onp = &on2; *onp; i++, onp = &(*onp)->on_next ) {
111 if ( overlay_is_inst( &be2, (*onp)->on_bi.bi_type ) ) {
112 Debug( LDAP_DEBUG_ANY, "over_db_config(): "
113 "warning, freshly added "
114 "overlay #%d \"%s\" is already in list\n",
115 i, (*onp)->on_bi.bi_type, 0 );
117 /* NOTE: if the overlay already exists,
118 * there is no way to merge the results
119 * of the configuration that may have
120 * occurred during bi_db_config(); we
121 * just issue a warning, and the
122 * administrator should deal with this */
129 ch_free( be->bd_info );
132 be->bd_info = (BackendInfo *)oi;
133 if ( rc != SLAP_CONF_UNKNOWN ) return rc;
141 snprintf( ca.log, sizeof( ca.log ), "%s: line %d",
142 ca.fname, ca.lineno );
144 for (; on; on=on->on_next) {
145 rc = SLAP_CONF_UNKNOWN;
146 if (on->on_bi.bi_cf_ocs) {
149 ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
151 ca.table = on->on_bi.bi_cf_ocs->co_type;
152 rc = config_add_vals( ct, &ca );
153 if ( rc != SLAP_CONF_UNKNOWN )
157 if (on->on_bi.bi_db_config && rc == SLAP_CONF_UNKNOWN) {
158 be->bd_info = &on->on_bi;
159 rc = on->on_bi.bi_db_config( be, fname, lineno,
161 if ( rc != SLAP_CONF_UNKNOWN ) break;
164 be->bd_info = bi_orig;
165 be->be_cf_ocs = be_cf_ocs;
176 return over_db_func( be, cr, db_open );
185 slap_overinfo *oi = be->bd_info->bi_private;
186 slap_overinst *on = oi->oi_list;
187 BackendInfo *bi_orig = be->bd_info;
190 for (; on && rc == 0; on=on->on_next) {
191 be->bd_info = &on->on_bi;
192 if ( be->bd_info->bi_db_close ) {
193 rc = be->bd_info->bi_db_close( be, cr );
197 if ( oi->oi_orig->bi_db_close ) {
198 be->bd_info = oi->oi_orig;
199 rc = be->bd_info->bi_db_close( be, cr );
202 be->bd_info = bi_orig;
212 slap_overinfo *oi = be->bd_info->bi_private;
213 slap_overinst *on = oi->oi_list, *next;
216 rc = over_db_func( be, cr, db_destroy );
219 for (next = on->on_next; on; on=next) {
230 over_back_response ( Operation *op, SlapReply *rs )
232 slap_overinfo *oi = op->o_callback->sc_private;
233 slap_overinst *on = oi->oi_list;
234 int rc = SLAP_CB_CONTINUE;
235 BackendDB *be = op->o_bd, db = *op->o_bd;
237 db.be_flags |= SLAP_DBFLAG_OVERLAY;
239 for (; on; on=on->on_next ) {
240 if ( on->on_response ) {
241 db.bd_info = (BackendInfo *)on;
242 rc = on->on_response( op, rs );
243 if ( rc != SLAP_CB_CONTINUE ) break;
246 /* Bypass the remaining on_response layers, but allow
247 * normal execution to continue.
249 if ( rc == SLAP_CB_BYPASS )
250 rc = SLAP_CB_CONTINUE;
259 AttributeDescription *desc,
261 slap_access_t access,
262 AccessControlState *state,
268 BackendDB *be = op->o_bd, db;
269 int rc = SLAP_CB_CONTINUE;
271 /* FIXME: used to happen for instance during abandon
272 * when global overlays are used... */
273 assert( op->o_bd != NULL );
275 bi = op->o_bd->bd_info;
276 /* Were we invoked on the frontend? */
277 if ( !bi->bi_access_allowed ) {
278 oi = frontendDB->bd_info->bi_private;
280 oi = op->o_bd->bd_info->bi_private;
284 for ( ; on; on = on->on_next ) {
285 if ( on->on_bi.bi_access_allowed ) {
286 /* NOTE: do not copy the structure until required */
287 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
289 db.be_flags |= SLAP_DBFLAG_OVERLAY;
293 op->o_bd->bd_info = (BackendInfo *)on;
294 rc = on->on_bi.bi_access_allowed( op, e,
295 desc, val, access, state, maskp );
296 if ( rc != SLAP_CB_CONTINUE ) break;
300 if ( rc == SLAP_CB_CONTINUE ) {
301 BI_access_allowed *bi_access_allowed;
303 /* if the database structure was changed, o_bd points to a
304 * copy of the structure; put the original bd_info in place */
305 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
306 op->o_bd->bd_info = oi->oi_orig;
309 if ( oi->oi_orig->bi_access_allowed ) {
310 bi_access_allowed = oi->oi_orig->bi_access_allowed;
312 bi_access_allowed = slap_access_allowed;
315 rc = bi_access_allowed( op, e,
316 desc, val, access, state, maskp );
318 /* should not fall thru this far without anything happening... */
319 if ( rc == SLAP_CB_CONTINUE ) {
320 /* access not allowed */
325 op->o_bd->bd_info = bi;
331 overlay_entry_get_ov(
335 AttributeDescription *ad,
340 slap_overinfo *oi = on->on_info;
341 BackendDB *be = op->o_bd, db;
342 BackendInfo *bi = op->o_bd->bd_info;
343 int rc = SLAP_CB_CONTINUE;
345 for ( ; on; on = on->on_next ) {
346 if ( on->on_bi.bi_entry_get_rw ) {
347 /* NOTE: do not copy the structure until required */
348 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
350 db.be_flags |= SLAP_DBFLAG_OVERLAY;
354 op->o_bd->bd_info = (BackendInfo *)on;
355 rc = on->on_bi.bi_entry_get_rw( op, dn,
357 if ( rc != SLAP_CB_CONTINUE ) break;
361 if ( rc == SLAP_CB_CONTINUE ) {
362 /* if the database structure was changed, o_bd points to a
363 * copy of the structure; put the original bd_info in place */
364 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
365 op->o_bd->bd_info = oi->oi_orig;
368 if ( oi->oi_orig->bi_entry_get_rw ) {
369 rc = oi->oi_orig->bi_entry_get_rw( op, dn,
373 /* should not fall thru this far without anything happening... */
374 if ( rc == SLAP_CB_CONTINUE ) {
375 rc = LDAP_UNWILLING_TO_PERFORM;
379 op->o_bd->bd_info = bi;
389 AttributeDescription *ad,
396 assert( op->o_bd != NULL );
398 oi = op->o_bd->bd_info->bi_private;
401 return overlay_entry_get_ov( op, dn, oc, ad, rw, e, on );
405 overlay_entry_release_ov(
411 slap_overinfo *oi = on->on_info;
412 BackendDB *be = op->o_bd, db;
413 BackendInfo *bi = op->o_bd->bd_info;
414 int rc = SLAP_CB_CONTINUE;
416 for ( ; on; on = on->on_next ) {
417 if ( on->on_bi.bi_entry_release_rw ) {
418 /* NOTE: do not copy the structure until required */
419 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
421 db.be_flags |= SLAP_DBFLAG_OVERLAY;
425 op->o_bd->bd_info = (BackendInfo *)on;
426 rc = on->on_bi.bi_entry_release_rw( op, e, rw );
427 if ( rc != SLAP_CB_CONTINUE ) break;
431 if ( rc == SLAP_CB_CONTINUE ) {
432 /* if the database structure was changed, o_bd points to a
433 * copy of the structure; put the original bd_info in place */
434 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
435 op->o_bd->bd_info = oi->oi_orig;
438 if ( oi->oi_orig->bi_entry_release_rw ) {
439 rc = oi->oi_orig->bi_entry_release_rw( op, e, rw );
442 /* should not fall thru this far without anything happening... */
443 if ( rc == SLAP_CB_CONTINUE ) {
449 op->o_bd->bd_info = bi;
455 over_entry_release_rw(
463 assert( op->o_bd != NULL );
465 oi = op->o_bd->bd_info->bi_private;
468 return overlay_entry_release_ov( op, e, rw, on );
475 struct berval *gr_ndn,
476 struct berval *op_ndn,
477 ObjectClass *group_oc,
478 AttributeDescription *group_at )
482 BackendInfo *bi = op->o_bd->bd_info;
483 BackendDB *be = op->o_bd, db;
484 int rc = SLAP_CB_CONTINUE;
486 /* FIXME: used to happen for instance during abandon
487 * when global overlays are used... */
488 assert( op->o_bd != NULL );
490 oi = op->o_bd->bd_info->bi_private;
493 for ( ; on; on = on->on_next ) {
494 if ( on->on_bi.bi_acl_group ) {
495 /* NOTE: do not copy the structure until required */
496 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
498 db.be_flags |= SLAP_DBFLAG_OVERLAY;
502 op->o_bd->bd_info = (BackendInfo *)on;
503 rc = on->on_bi.bi_acl_group( op, e,
504 gr_ndn, op_ndn, group_oc, group_at );
505 if ( rc != SLAP_CB_CONTINUE ) break;
509 if ( rc == SLAP_CB_CONTINUE ) {
510 BI_acl_group *bi_acl_group;
512 /* if the database structure was changed, o_bd points to a
513 * copy of the structure; put the original bd_info in place */
514 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
515 op->o_bd->bd_info = oi->oi_orig;
518 if ( oi->oi_orig->bi_acl_group ) {
519 bi_acl_group = oi->oi_orig->bi_acl_group;
521 bi_acl_group = backend_group;
524 rc = bi_acl_group( op, e,
525 gr_ndn, op_ndn, group_oc, group_at );
527 /* should not fall thru this far without anything happening... */
528 if ( rc == SLAP_CB_CONTINUE ) {
529 /* access not allowed */
534 op->o_bd->bd_info = bi;
543 struct berval *entry_ndn,
544 AttributeDescription *entry_at,
546 slap_access_t access )
550 BackendInfo *bi = op->o_bd->bd_info;
551 BackendDB *be = op->o_bd, db;
552 int rc = SLAP_CB_CONTINUE;
554 /* FIXME: used to happen for instance during abandon
555 * when global overlays are used... */
556 assert( op->o_bd != NULL );
558 oi = op->o_bd->bd_info->bi_private;
561 for ( ; on; on = on->on_next ) {
562 if ( on->on_bi.bi_acl_attribute ) {
563 /* NOTE: do not copy the structure until required */
564 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
566 db.be_flags |= SLAP_DBFLAG_OVERLAY;
570 op->o_bd->bd_info = (BackendInfo *)on;
571 rc = on->on_bi.bi_acl_attribute( op, target,
572 entry_ndn, entry_at, vals, access );
573 if ( rc != SLAP_CB_CONTINUE ) break;
577 if ( rc == SLAP_CB_CONTINUE ) {
578 BI_acl_attribute *bi_acl_attribute;
580 /* if the database structure was changed, o_bd points to a
581 * copy of the structure; put the original bd_info in place */
582 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
583 op->o_bd->bd_info = oi->oi_orig;
586 if ( oi->oi_orig->bi_acl_attribute ) {
587 bi_acl_attribute = oi->oi_orig->bi_acl_attribute;
589 bi_acl_attribute = backend_attribute;
592 rc = bi_acl_attribute( op, target,
593 entry_ndn, entry_at, vals, access );
595 /* should not fall thru this far without anything happening... */
596 if ( rc == SLAP_CB_CONTINUE ) {
597 /* access not allowed */
602 op->o_bd->bd_info = bi;
608 * default return code in case of missing backend function
609 * and overlay stack returning SLAP_CB_CONTINUE
611 static int op_rc[ op_last ] = {
612 LDAP_UNWILLING_TO_PERFORM, /* bind */
613 LDAP_UNWILLING_TO_PERFORM, /* unbind */
614 LDAP_UNWILLING_TO_PERFORM, /* search */
615 SLAP_CB_CONTINUE, /* compare; pass to frontend */
616 LDAP_UNWILLING_TO_PERFORM, /* modify */
617 LDAP_UNWILLING_TO_PERFORM, /* modrdn */
618 LDAP_UNWILLING_TO_PERFORM, /* add */
619 LDAP_UNWILLING_TO_PERFORM, /* delete */
620 LDAP_UNWILLING_TO_PERFORM, /* abandon */
621 LDAP_UNWILLING_TO_PERFORM, /* cancel */
622 LDAP_UNWILLING_TO_PERFORM, /* extended */
623 LDAP_SUCCESS, /* aux_operational */
624 LDAP_SUCCESS, /* aux_chk_referrals */
625 SLAP_CB_CONTINUE /* aux_chk_controls; pass to frontend */
631 slap_operation_t which,
637 int rc = SLAP_CB_CONTINUE;
639 for (; on; on=on->on_next ) {
640 func = &on->on_bi.bi_op_bind;
642 op->o_bd->bd_info = (BackendInfo *)on;
643 rc = func[which]( op, rs );
644 if ( rc != SLAP_CB_CONTINUE ) break;
647 if ( rc == SLAP_CB_BYPASS )
648 rc = SLAP_CB_CONTINUE;
650 func = &oi->oi_orig->bi_op_bind;
651 if ( func[which] && rc == SLAP_CB_CONTINUE ) {
652 op->o_bd->bd_info = oi->oi_orig;
653 rc = func[which]( op, rs );
655 /* should not fall thru this far without anything happening... */
656 if ( rc == SLAP_CB_CONTINUE ) {
660 /* The underlying backend didn't handle the request, make sure
661 * overlay cleanup is processed.
663 if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
664 slap_callback *sc_next;
665 for ( ; op->o_callback && op->o_callback->sc_response !=
666 over_back_response; op->o_callback = sc_next ) {
667 sc_next = op->o_callback->sc_next;
668 if ( op->o_callback->sc_cleanup ) {
669 op->o_callback->sc_cleanup( op, rs );
680 slap_operation_t which
685 BackendDB *be = op->o_bd, db;
686 slap_callback cb = {NULL, over_back_response, NULL, NULL};
687 int rc = SLAP_CB_CONTINUE;
689 /* FIXME: used to happen for instance during abandon
690 * when global overlays are used... */
691 assert( op->o_bd != NULL );
693 oi = op->o_bd->bd_info->bi_private;
696 if ( !SLAP_ISOVERLAY( op->o_bd )) {
698 db.be_flags |= SLAP_DBFLAG_OVERLAY;
701 cb.sc_next = op->o_callback;
703 op->o_callback = &cb;
705 rc = overlay_op_walk( op, rs, which, oi, on );
708 op->o_callback = cb.sc_next;
713 over_op_bind( Operation *op, SlapReply *rs )
715 return over_op_func( op, rs, op_bind );
719 over_op_unbind( Operation *op, SlapReply *rs )
721 return over_op_func( op, rs, op_unbind );
725 over_op_search( Operation *op, SlapReply *rs )
727 return over_op_func( op, rs, op_search );
731 over_op_compare( Operation *op, SlapReply *rs )
733 return over_op_func( op, rs, op_compare );
737 over_op_modify( Operation *op, SlapReply *rs )
739 return over_op_func( op, rs, op_modify );
743 over_op_modrdn( Operation *op, SlapReply *rs )
745 return over_op_func( op, rs, op_modrdn );
749 over_op_add( Operation *op, SlapReply *rs )
751 return over_op_func( op, rs, op_add );
755 over_op_delete( Operation *op, SlapReply *rs )
757 return over_op_func( op, rs, op_delete );
761 over_op_abandon( Operation *op, SlapReply *rs )
763 return over_op_func( op, rs, op_abandon );
767 over_op_cancel( Operation *op, SlapReply *rs )
769 return over_op_func( op, rs, op_cancel );
773 over_op_extended( Operation *op, SlapReply *rs )
775 return over_op_func( op, rs, op_extended );
779 over_aux_operational( Operation *op, SlapReply *rs )
781 return over_op_func( op, rs, op_aux_operational );
785 over_aux_chk_referrals( Operation *op, SlapReply *rs )
787 return over_op_func( op, rs, op_aux_chk_referrals );
791 over_aux_chk_controls( Operation *op, SlapReply *rs )
793 return over_op_func( op, rs, op_aux_chk_controls );
803 over_connection_func(
806 enum conn_which which
812 int rc = SLAP_CB_CONTINUE;
813 BI_connection_init **func;
815 /* FIXME: used to happen for instance during abandon
816 * when global overlays are used... */
817 assert( bd != NULL );
819 oi = bd->bd_info->bi_private;
822 if ( !SLAP_ISOVERLAY( bd ) ) {
824 db.be_flags |= SLAP_DBFLAG_OVERLAY;
828 for ( ; on; on = on->on_next ) {
829 func = &on->on_bi.bi_connection_init;
830 if ( func[ which ] ) {
831 bd->bd_info = (BackendInfo *)on;
832 rc = func[ which ]( bd, conn );
833 if ( rc != SLAP_CB_CONTINUE ) break;
837 func = &oi->oi_orig->bi_connection_init;
838 if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
839 bd->bd_info = oi->oi_orig;
840 rc = func[ which ]( bd, conn );
842 /* should not fall thru this far without anything happening... */
843 if ( rc == SLAP_CB_CONTINUE ) {
844 rc = LDAP_UNWILLING_TO_PERFORM;
851 over_connection_init(
856 return over_connection_func( bd, conn, conn_init );
860 over_connection_destroy(
865 return over_connection_func( bd, conn, conn_destroy );
875 /* FIXME: check for duplicates? */
876 for ( tmp = overlays; tmp != NULL; tmp = tmp->on_next ) {
877 if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_type ) == 0 ) {
878 Debug( LDAP_DEBUG_ANY,
879 "overlay_register(\"%s\"): "
880 "name already in use.\n",
881 on->on_bi.bi_type, 0, 0 );
885 if ( on->on_bi.bi_obsolete_names != NULL ) {
888 for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
889 if ( strcmp( on->on_bi.bi_obsolete_names[ i ], tmp->on_bi.bi_type ) == 0 ) {
890 Debug( LDAP_DEBUG_ANY,
891 "overlay_register(\"%s\"): "
892 "obsolete name \"%s\" already in use "
893 "by overlay \"%s\".\n",
895 on->on_bi.bi_obsolete_names[ i ],
896 tmp->on_bi.bi_type );
902 if ( tmp->on_bi.bi_obsolete_names != NULL ) {
905 for ( i = 0; tmp->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
908 if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
909 Debug( LDAP_DEBUG_ANY,
910 "overlay_register(\"%s\"): "
911 "name already in use "
912 "as obsolete by overlay \"%s\".\n",
914 tmp->on_bi.bi_obsolete_names[ i ], 0 );
918 if ( on->on_bi.bi_obsolete_names != NULL ) {
919 for ( j = 0; on->on_bi.bi_obsolete_names[ j ] != NULL; j++ ) {
920 if ( strcmp( on->on_bi.bi_obsolete_names[ j ], tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
921 Debug( LDAP_DEBUG_ANY,
922 "overlay_register(\"%s\"): "
923 "obsolete name \"%s\" already in use "
924 "as obsolete by overlay \"%s\".\n",
926 on->on_bi.bi_obsolete_names[ j ],
927 tmp->on_bi.bi_type );
936 on->on_next = overlays;
942 * iterator on registered overlays; overlay_next( NULL ) returns the first
943 * overlay; subsequent calls with the previously returned value allow to
944 * iterate over the entire list; returns NULL when no more overlays are
961 * returns a specific registered overlay based on the type; NULL if not
966 overlay_find( const char *over_type )
968 slap_overinst *on = overlays;
970 assert( over_type != NULL );
972 for ( ; on; on = on->on_next ) {
973 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
977 if ( on->on_bi.bi_obsolete_names != NULL ) {
980 for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
981 if ( strcmp( on->on_bi.bi_obsolete_names[ i ], over_type ) == 0 ) {
982 Debug( LDAP_DEBUG_ANY,
983 "overlay_find(\"%s\"): "
984 "obsolete name for \"%s\".\n",
985 on->on_bi.bi_obsolete_names[ i ],
986 on->on_bi.bi_type, 0 );
997 static const char overtype[] = "over";
1000 * returns TRUE (1) if the database is actually an overlay instance;
1001 * FALSE (0) otherwise.
1005 overlay_is_over( BackendDB *be )
1007 return be->bd_info->bi_type == overtype;
1011 * returns TRUE (1) if the given database is actually an overlay
1012 * instance and, somewhere in the list, contains the requested overlay;
1013 * FALSE (0) otherwise.
1017 overlay_is_inst( BackendDB *be, const char *over_type )
1021 assert( be != NULL );
1023 if ( !overlay_is_over( be ) ) {
1027 on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
1028 for ( ; on; on = on->on_next ) {
1029 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
1038 overlay_register_control( BackendDB *be, const char *oid )
1043 if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
1047 if ( SLAP_ISGLOBALOVERLAY( be ) ) {
1050 /* add to all backends... */
1051 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
1056 bd->be_ctrls[ cid ] = 1;
1057 bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
1063 be->be_ctrls[ cid ] = 1;
1064 be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
1071 overlay_destroy_one( BackendDB *be, slap_overinst *on )
1073 slap_overinfo *oi = on->on_info;
1074 slap_overinst **oidx;
1076 for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
1077 if ( *oidx == on ) {
1078 *oidx = on->on_next;
1079 if ( on->on_bi.bi_db_destroy ) {
1080 BackendInfo *bi_orig = be->bd_info;
1081 be->bd_info = (BackendInfo *)on;
1082 on->on_bi.bi_db_destroy( be, NULL );
1083 be->bd_info = bi_orig;
1092 overlay_insert( BackendDB *be, slap_overinst *on2, slap_overinst ***prev,
1095 slap_overinfo *oi = (slap_overinfo *)be->bd_info;
1098 on2->on_next = oi->oi_list;
1102 slap_overinst *on, *otmp1 = NULL, *otmp2;
1104 /* Since the list is in reverse order and is singly linked,
1105 * we reverse it to find the idx insertion point. Adding
1106 * on overlay at a specific point should be a pretty
1107 * infrequent occurrence.
1109 for ( on = oi->oi_list; on; on=otmp2 ) {
1110 otmp2 = on->on_next;
1111 on->on_next = otmp1;
1115 /* advance to insertion point */
1116 for ( i=0, on = otmp1; i<idx; i++ ) {
1117 otmp1 = on->on_next;
1118 on->on_next = oi->oi_list;
1122 on2->on_next = oi->oi_list;
1125 *prev = &otmp1->on_next;
1126 /* replace remainder of list */
1127 for ( on=otmp1; on; on=otmp1 ) {
1128 otmp1 = on->on_next;
1129 on->on_next = oi->oi_list;
1137 overlay_move( BackendDB *be, slap_overinst *on, int idx )
1139 slap_overinfo *oi = (slap_overinfo *)be->bd_info;
1140 slap_overinst **onp;
1142 for (onp = &oi->oi_list; *onp; onp= &(*onp)->on_next) {
1148 overlay_insert( be, on, &onp, idx );
1151 /* add an overlay to a particular backend. */
1153 overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res )
1155 slap_overinst *on = NULL, *on2 = NULL, **prev;
1156 slap_overinfo *oi = NULL;
1157 BackendInfo *bi = NULL;
1162 on = overlay_find( ov );
1164 Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
1168 /* If this is the first overlay on this backend, set up the
1169 * overlay info structure
1171 if ( !overlay_is_over( be ) ) {
1174 /* NOTE: the first time a global overlay is configured,
1175 * frontendDB gets this flag; it is used later by overlays
1176 * to determine if they're stacked on top of the frontendDB */
1177 if ( be->bd_info == frontendDB->bd_info || SLAP_ISGLOBALOVERLAY( be ) ) {
1179 if ( on->on_bi.bi_flags & SLAPO_BFLAG_DBONLY ) {
1180 Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1181 "overlay \"%s\" cannot be global.\n",
1186 } else if ( on->on_bi.bi_flags & SLAPO_BFLAG_GLOBONLY ) {
1187 Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1188 "overlay \"%s\" can only be global.\n",
1193 oi = ch_malloc( sizeof( slap_overinfo ) );
1194 oi->oi_orig = be->bd_info;
1195 oi->oi_bi = *be->bd_info;
1199 SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
1202 /* Save a pointer to ourself in bi_private.
1204 oi->oi_bi.bi_private = oi;
1206 bi = (BackendInfo *)oi;
1208 bi->bi_type = (char *)overtype;
1210 bi->bi_db_config = over_db_config;
1211 bi->bi_db_open = over_db_open;
1212 bi->bi_db_close = over_db_close;
1213 bi->bi_db_destroy = over_db_destroy;
1215 bi->bi_op_bind = over_op_bind;
1216 bi->bi_op_unbind = over_op_unbind;
1217 bi->bi_op_search = over_op_search;
1218 bi->bi_op_compare = over_op_compare;
1219 bi->bi_op_modify = over_op_modify;
1220 bi->bi_op_modrdn = over_op_modrdn;
1221 bi->bi_op_add = over_op_add;
1222 bi->bi_op_delete = over_op_delete;
1223 bi->bi_op_abandon = over_op_abandon;
1224 bi->bi_op_cancel = over_op_cancel;
1226 bi->bi_extended = over_op_extended;
1229 * this is fine because it has the same
1230 * args of the operations; we need to rework
1231 * all the hooks to share the same args
1232 * of the operations...
1234 bi->bi_operational = over_aux_operational;
1235 bi->bi_chk_referrals = over_aux_chk_referrals;
1236 bi->bi_chk_controls = over_aux_chk_controls;
1238 /* these have specific arglists */
1239 bi->bi_entry_get_rw = over_entry_get_rw;
1240 bi->bi_entry_release_rw = over_entry_release_rw;
1241 bi->bi_access_allowed = over_access_allowed;
1242 bi->bi_acl_group = over_acl_group;
1243 bi->bi_acl_attribute = over_acl_attribute;
1245 bi->bi_connection_init = over_connection_init;
1246 bi->bi_connection_destroy = over_connection_destroy;
1251 if ( overlay_is_inst( be, ov ) ) {
1252 if ( SLAPO_SINGLE( be ) ) {
1253 Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1254 "overlay \"%s\" already in list\n",
1260 oi = be->bd_info->bi_private;
1263 /* Insert new overlay into list. By default overlays are
1264 * added to head of list and executed in LIFO order.
1266 on2 = ch_calloc( 1, sizeof(slap_overinst) );
1270 prev = &oi->oi_list;
1271 /* Do we need to find the insertion point? */
1275 /* count current overlays */
1276 for ( i=0, on=oi->oi_list; on; on=on->on_next, i++ );
1278 /* are we just appending a new one? */
1282 overlay_insert( be, on2, &prev, idx );
1284 /* Any initialization needed? */
1285 if ( on2->on_bi.bi_db_init ) {
1287 be->bd_info = (BackendInfo *)on2;
1288 rc = on2->on_bi.bi_db_init( be, NULL );
1289 be->bd_info = (BackendInfo *)oi;
1291 *prev = on2->on_next;