1 /* backover.c - backend overlay routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2007 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;
45 slap_overinfo *oi = be->bd_info->bi_private;
46 slap_overinst *on = oi->oi_list;
47 BackendInfo *bi_orig = be->bd_info;
51 func = &oi->oi_orig->bi_db_open;
53 be->bd_info = oi->oi_orig;
54 rc = func[which]( be, NULL );
57 for (; on && rc == 0; on=on->on_next) {
58 be->bd_info = &on->on_bi;
59 func = &on->on_bi.bi_db_open;
61 rc = func[which]( be, NULL );
64 be->bd_info = bi_orig;
77 slap_overinfo *oi = be->bd_info->bi_private;
78 slap_overinst *on = oi->oi_list;
79 BackendInfo *bi_orig = be->bd_info;
80 struct ConfigOCs *be_cf_ocs = be->be_cf_ocs;
84 if ( oi->oi_orig->bi_db_config ) {
85 be->bd_info = oi->oi_orig;
86 be->be_cf_ocs = oi->oi_orig->bi_cf_ocs;
87 rc = oi->oi_orig->bi_db_config( be, fname, lineno,
90 if ( be->bd_info != oi->oi_orig ) {
92 slap_overinst *on2, **onp;
96 /* a database added an overlay;
97 * work it around... */
98 assert( overlay_is_over( be ) );
100 oi2 = ( slap_overinfo * )be->bd_info->bi_private;
103 /* need to put a uniqueness check here as well;
104 * note that in principle there could be more than
105 * one overlay as a result of multiple calls to
106 * overlay_config() */
107 be2.bd_info = (BackendInfo *)oi;
109 for ( i = 0, onp = &on2; *onp; i++, onp = &(*onp)->on_next ) {
110 if ( overlay_is_inst( &be2, (*onp)->on_bi.bi_type ) ) {
111 Debug( LDAP_DEBUG_ANY, "over_db_config(): "
112 "warning, freshly added "
113 "overlay #%d \"%s\" is already in list\n",
114 i, (*onp)->on_bi.bi_type, 0 );
116 /* NOTE: if the overlay already exists,
117 * there is no way to merge the results
118 * of the configuration that may have
119 * occurred during bi_db_config(); we
120 * just issue a warning, and the
121 * administrator should deal with this */
128 ch_free( be->bd_info );
131 be->bd_info = (BackendInfo *)oi;
132 if ( rc != SLAP_CONF_UNKNOWN ) return rc;
140 snprintf( ca.log, sizeof( ca.log ), "%s: line %d",
141 ca.fname, ca.lineno );
143 for (; on; on=on->on_next) {
144 rc = SLAP_CONF_UNKNOWN;
145 if (on->on_bi.bi_cf_ocs) {
148 ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
150 ca.table = on->on_bi.bi_cf_ocs->co_type;
151 rc = config_add_vals( ct, &ca );
152 if ( rc != SLAP_CONF_UNKNOWN )
156 if (on->on_bi.bi_db_config && rc == SLAP_CONF_UNKNOWN) {
157 be->bd_info = &on->on_bi;
158 rc = on->on_bi.bi_db_config( be, fname, lineno,
160 if ( rc != SLAP_CONF_UNKNOWN ) break;
163 be->bd_info = bi_orig;
164 be->be_cf_ocs = be_cf_ocs;
175 return over_db_func( be, db_open );
184 slap_overinfo *oi = be->bd_info->bi_private;
185 slap_overinst *on = oi->oi_list;
186 BackendInfo *bi_orig = be->bd_info;
189 for (; on && rc == 0; on=on->on_next) {
190 be->bd_info = &on->on_bi;
191 if ( be->bd_info->bi_db_close ) {
192 rc = be->bd_info->bi_db_close( be, NULL );
196 if ( oi->oi_orig->bi_db_close ) {
197 be->bd_info = oi->oi_orig;
198 rc = be->bd_info->bi_db_close( be, NULL );
201 be->bd_info = bi_orig;
211 slap_overinfo *oi = be->bd_info->bi_private;
212 slap_overinst *on = oi->oi_list, *next;
215 rc = over_db_func( be, db_destroy );
218 for (next = on->on_next; on; on=next) {
229 over_back_response ( Operation *op, SlapReply *rs )
231 slap_overinfo *oi = op->o_callback->sc_private;
232 slap_overinst *on = oi->oi_list;
233 int rc = SLAP_CB_CONTINUE;
234 BackendDB *be = op->o_bd, db = *op->o_bd;
236 db.be_flags |= SLAP_DBFLAG_OVERLAY;
238 for (; on; on=on->on_next ) {
239 if ( on->on_response ) {
240 db.bd_info = (BackendInfo *)on;
241 rc = on->on_response( op, rs );
242 if ( rc != SLAP_CB_CONTINUE ) break;
245 /* Bypass the remaining on_response layers, but allow
246 * normal execution to continue.
248 if ( rc == SLAP_CB_BYPASS )
249 rc = SLAP_CB_CONTINUE;
258 AttributeDescription *desc,
260 slap_access_t access,
261 AccessControlState *state,
267 BackendDB *be = op->o_bd, db;
268 int rc = SLAP_CB_CONTINUE;
270 /* FIXME: used to happen for instance during abandon
271 * when global overlays are used... */
272 assert( op->o_bd != NULL );
274 bi = op->o_bd->bd_info;
275 /* Were we invoked on the frontend? */
276 if ( !bi->bi_access_allowed ) {
277 oi = frontendDB->bd_info->bi_private;
279 oi = op->o_bd->bd_info->bi_private;
283 for ( ; on; on = on->on_next ) {
284 if ( on->on_bi.bi_access_allowed ) {
285 /* NOTE: do not copy the structure until required */
286 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
288 db.be_flags |= SLAP_DBFLAG_OVERLAY;
292 op->o_bd->bd_info = (BackendInfo *)on;
293 rc = on->on_bi.bi_access_allowed( op, e,
294 desc, val, access, state, maskp );
295 if ( rc != SLAP_CB_CONTINUE ) break;
299 if ( rc == SLAP_CB_CONTINUE ) {
300 BI_access_allowed *bi_access_allowed;
302 /* if the database structure was changed, o_bd points to a
303 * copy of the structure; put the original bd_info in place */
304 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
305 op->o_bd->bd_info = oi->oi_orig;
308 if ( oi->oi_orig->bi_access_allowed ) {
309 bi_access_allowed = oi->oi_orig->bi_access_allowed;
311 bi_access_allowed = slap_access_allowed;
314 rc = bi_access_allowed( op, e,
315 desc, val, access, state, maskp );
317 /* should not fall thru this far without anything happening... */
318 if ( rc == SLAP_CB_CONTINUE ) {
319 /* access not allowed */
324 op->o_bd->bd_info = bi;
330 overlay_entry_get_ov(
334 AttributeDescription *ad,
339 slap_overinfo *oi = on->on_info;
340 BackendDB *be = op->o_bd, db;
341 BackendInfo *bi = op->o_bd->bd_info;
342 int rc = SLAP_CB_CONTINUE;
344 for ( ; on; on = on->on_next ) {
345 if ( on->on_bi.bi_entry_get_rw ) {
346 /* NOTE: do not copy the structure until required */
347 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
349 db.be_flags |= SLAP_DBFLAG_OVERLAY;
353 op->o_bd->bd_info = (BackendInfo *)on;
354 rc = on->on_bi.bi_entry_get_rw( op, dn,
356 if ( rc != SLAP_CB_CONTINUE ) break;
360 if ( rc == SLAP_CB_CONTINUE ) {
361 /* if the database structure was changed, o_bd points to a
362 * copy of the structure; put the original bd_info in place */
363 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
364 op->o_bd->bd_info = oi->oi_orig;
367 if ( oi->oi_orig->bi_entry_get_rw ) {
368 rc = oi->oi_orig->bi_entry_get_rw( op, dn,
372 /* should not fall thru this far without anything happening... */
373 if ( rc == SLAP_CB_CONTINUE ) {
374 rc = LDAP_UNWILLING_TO_PERFORM;
378 op->o_bd->bd_info = bi;
388 AttributeDescription *ad,
395 assert( op->o_bd != NULL );
397 oi = op->o_bd->bd_info->bi_private;
400 return overlay_entry_get_ov( op, dn, oc, ad, rw, e, on );
404 overlay_entry_release_ov(
410 slap_overinfo *oi = on->on_info;
411 BackendDB *be = op->o_bd, db;
412 BackendInfo *bi = op->o_bd->bd_info;
413 int rc = SLAP_CB_CONTINUE;
415 for ( ; on; on = on->on_next ) {
416 if ( on->on_bi.bi_entry_release_rw ) {
417 /* NOTE: do not copy the structure until required */
418 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
420 db.be_flags |= SLAP_DBFLAG_OVERLAY;
424 op->o_bd->bd_info = (BackendInfo *)on;
425 rc = on->on_bi.bi_entry_release_rw( op, e, rw );
426 if ( rc != SLAP_CB_CONTINUE ) break;
430 if ( rc == SLAP_CB_CONTINUE ) {
431 /* if the database structure was changed, o_bd points to a
432 * copy of the structure; put the original bd_info in place */
433 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
434 op->o_bd->bd_info = oi->oi_orig;
437 if ( oi->oi_orig->bi_entry_release_rw ) {
438 rc = oi->oi_orig->bi_entry_release_rw( op, e, rw );
441 /* should not fall thru this far without anything happening... */
442 if ( rc == SLAP_CB_CONTINUE ) {
448 op->o_bd->bd_info = bi;
454 over_entry_release_rw(
462 assert( op->o_bd != NULL );
464 oi = op->o_bd->bd_info->bi_private;
467 return overlay_entry_release_ov( op, e, rw, on );
474 struct berval *gr_ndn,
475 struct berval *op_ndn,
476 ObjectClass *group_oc,
477 AttributeDescription *group_at )
481 BackendInfo *bi = op->o_bd->bd_info;
482 BackendDB *be = op->o_bd, db;
483 int rc = SLAP_CB_CONTINUE;
485 /* FIXME: used to happen for instance during abandon
486 * when global overlays are used... */
487 assert( op->o_bd != NULL );
489 oi = op->o_bd->bd_info->bi_private;
492 for ( ; on; on = on->on_next ) {
493 if ( on->on_bi.bi_acl_group ) {
494 /* NOTE: do not copy the structure until required */
495 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
497 db.be_flags |= SLAP_DBFLAG_OVERLAY;
501 op->o_bd->bd_info = (BackendInfo *)on;
502 rc = on->on_bi.bi_acl_group( op, e,
503 gr_ndn, op_ndn, group_oc, group_at );
504 if ( rc != SLAP_CB_CONTINUE ) break;
508 if ( rc == SLAP_CB_CONTINUE ) {
509 BI_acl_group *bi_acl_group;
511 /* if the database structure was changed, o_bd points to a
512 * copy of the structure; put the original bd_info in place */
513 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
514 op->o_bd->bd_info = oi->oi_orig;
517 if ( oi->oi_orig->bi_acl_group ) {
518 bi_acl_group = oi->oi_orig->bi_acl_group;
520 bi_acl_group = backend_group;
523 rc = bi_acl_group( op, e,
524 gr_ndn, op_ndn, group_oc, group_at );
526 /* should not fall thru this far without anything happening... */
527 if ( rc == SLAP_CB_CONTINUE ) {
528 /* access not allowed */
533 op->o_bd->bd_info = bi;
542 struct berval *entry_ndn,
543 AttributeDescription *entry_at,
545 slap_access_t access )
549 BackendInfo *bi = op->o_bd->bd_info;
550 BackendDB *be = op->o_bd, db;
551 int rc = SLAP_CB_CONTINUE;
553 /* FIXME: used to happen for instance during abandon
554 * when global overlays are used... */
555 assert( op->o_bd != NULL );
557 oi = op->o_bd->bd_info->bi_private;
560 for ( ; on; on = on->on_next ) {
561 if ( on->on_bi.bi_acl_attribute ) {
562 /* NOTE: do not copy the structure until required */
563 if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
565 db.be_flags |= SLAP_DBFLAG_OVERLAY;
569 op->o_bd->bd_info = (BackendInfo *)on;
570 rc = on->on_bi.bi_acl_attribute( op, target,
571 entry_ndn, entry_at, vals, access );
572 if ( rc != SLAP_CB_CONTINUE ) break;
576 if ( rc == SLAP_CB_CONTINUE ) {
577 BI_acl_attribute *bi_acl_attribute;
579 /* if the database structure was changed, o_bd points to a
580 * copy of the structure; put the original bd_info in place */
581 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
582 op->o_bd->bd_info = oi->oi_orig;
585 if ( oi->oi_orig->bi_acl_attribute ) {
586 bi_acl_attribute = oi->oi_orig->bi_acl_attribute;
588 bi_acl_attribute = backend_attribute;
591 rc = bi_acl_attribute( op, target,
592 entry_ndn, entry_at, vals, access );
594 /* should not fall thru this far without anything happening... */
595 if ( rc == SLAP_CB_CONTINUE ) {
596 /* access not allowed */
601 op->o_bd->bd_info = bi;
607 * default return code in case of missing backend function
608 * and overlay stack returning SLAP_CB_CONTINUE
610 static int op_rc[ op_last ] = {
611 LDAP_UNWILLING_TO_PERFORM, /* bind */
612 LDAP_UNWILLING_TO_PERFORM, /* unbind */
613 LDAP_UNWILLING_TO_PERFORM, /* search */
614 SLAP_CB_CONTINUE, /* compare; pass to frontend */
615 LDAP_UNWILLING_TO_PERFORM, /* modify */
616 LDAP_UNWILLING_TO_PERFORM, /* modrdn */
617 LDAP_UNWILLING_TO_PERFORM, /* add */
618 LDAP_UNWILLING_TO_PERFORM, /* delete */
619 LDAP_UNWILLING_TO_PERFORM, /* abandon */
620 LDAP_UNWILLING_TO_PERFORM, /* cancel */
621 LDAP_UNWILLING_TO_PERFORM, /* extended */
622 LDAP_SUCCESS, /* aux_operational */
623 LDAP_SUCCESS, /* aux_chk_referrals */
624 SLAP_CB_CONTINUE /* aux_chk_controls; pass to frontend */
630 slap_operation_t which,
636 int rc = SLAP_CB_CONTINUE;
638 for (; on; on=on->on_next ) {
639 func = &on->on_bi.bi_op_bind;
641 op->o_bd->bd_info = (BackendInfo *)on;
642 rc = func[which]( op, rs );
643 if ( rc != SLAP_CB_CONTINUE ) break;
646 if ( rc == SLAP_CB_BYPASS )
647 rc = SLAP_CB_CONTINUE;
649 func = &oi->oi_orig->bi_op_bind;
650 if ( func[which] && rc == SLAP_CB_CONTINUE ) {
651 op->o_bd->bd_info = oi->oi_orig;
652 rc = func[which]( op, rs );
654 /* should not fall thru this far without anything happening... */
655 if ( rc == SLAP_CB_CONTINUE ) {
659 /* The underlying backend didn't handle the request, make sure
660 * overlay cleanup is processed.
662 if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
663 slap_callback *sc_next;
664 for ( ; op->o_callback && op->o_callback->sc_response !=
665 over_back_response; op->o_callback = sc_next ) {
666 sc_next = op->o_callback->sc_next;
667 if ( op->o_callback->sc_cleanup ) {
668 op->o_callback->sc_cleanup( op, rs );
679 slap_operation_t which
684 BackendDB *be = op->o_bd, db;
685 slap_callback cb = {NULL, over_back_response, NULL, NULL};
686 int rc = SLAP_CB_CONTINUE;
688 /* FIXME: used to happen for instance during abandon
689 * when global overlays are used... */
690 assert( op->o_bd != NULL );
692 oi = op->o_bd->bd_info->bi_private;
695 if ( !SLAP_ISOVERLAY( op->o_bd )) {
697 db.be_flags |= SLAP_DBFLAG_OVERLAY;
700 cb.sc_next = op->o_callback;
702 op->o_callback = &cb;
704 rc = overlay_op_walk( op, rs, which, oi, on );
707 op->o_callback = cb.sc_next;
712 over_op_bind( Operation *op, SlapReply *rs )
714 return over_op_func( op, rs, op_bind );
718 over_op_unbind( Operation *op, SlapReply *rs )
720 return over_op_func( op, rs, op_unbind );
724 over_op_search( Operation *op, SlapReply *rs )
726 return over_op_func( op, rs, op_search );
730 over_op_compare( Operation *op, SlapReply *rs )
732 return over_op_func( op, rs, op_compare );
736 over_op_modify( Operation *op, SlapReply *rs )
738 return over_op_func( op, rs, op_modify );
742 over_op_modrdn( Operation *op, SlapReply *rs )
744 return over_op_func( op, rs, op_modrdn );
748 over_op_add( Operation *op, SlapReply *rs )
750 return over_op_func( op, rs, op_add );
754 over_op_delete( Operation *op, SlapReply *rs )
756 return over_op_func( op, rs, op_delete );
760 over_op_abandon( Operation *op, SlapReply *rs )
762 return over_op_func( op, rs, op_abandon );
766 over_op_cancel( Operation *op, SlapReply *rs )
768 return over_op_func( op, rs, op_cancel );
772 over_op_extended( Operation *op, SlapReply *rs )
774 return over_op_func( op, rs, op_extended );
778 over_aux_operational( Operation *op, SlapReply *rs )
780 return over_op_func( op, rs, op_aux_operational );
784 over_aux_chk_referrals( Operation *op, SlapReply *rs )
786 return over_op_func( op, rs, op_aux_chk_referrals );
790 over_aux_chk_controls( Operation *op, SlapReply *rs )
792 return over_op_func( op, rs, op_aux_chk_controls );
802 over_connection_func(
805 enum conn_which which
811 int rc = SLAP_CB_CONTINUE;
812 BI_connection_init **func;
814 /* FIXME: used to happen for instance during abandon
815 * when global overlays are used... */
816 assert( bd != NULL );
818 oi = bd->bd_info->bi_private;
821 if ( !SLAP_ISOVERLAY( bd ) ) {
823 db.be_flags |= SLAP_DBFLAG_OVERLAY;
827 for ( ; on; on = on->on_next ) {
828 func = &on->on_bi.bi_connection_init;
829 if ( func[ which ] ) {
830 bd->bd_info = (BackendInfo *)on;
831 rc = func[ which ]( bd, conn );
832 if ( rc != SLAP_CB_CONTINUE ) break;
836 func = &oi->oi_orig->bi_connection_init;
837 if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
838 bd->bd_info = oi->oi_orig;
839 rc = func[ which ]( bd, conn );
841 /* should not fall thru this far without anything happening... */
842 if ( rc == SLAP_CB_CONTINUE ) {
843 rc = LDAP_UNWILLING_TO_PERFORM;
850 over_connection_init(
855 return over_connection_func( bd, conn, conn_init );
859 over_connection_destroy(
864 return over_connection_func( bd, conn, conn_destroy );
874 /* FIXME: check for duplicates? */
875 for ( tmp = overlays; tmp != NULL; tmp = tmp->on_next ) {
876 if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_type ) == 0 ) {
877 Debug( LDAP_DEBUG_ANY,
878 "overlay_register(\"%s\"): "
879 "name already in use.\n",
880 on->on_bi.bi_type, 0, 0 );
884 if ( on->on_bi.bi_obsolete_names != NULL ) {
887 for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
888 if ( strcmp( on->on_bi.bi_obsolete_names[ i ], tmp->on_bi.bi_type ) == 0 ) {
889 Debug( LDAP_DEBUG_ANY,
890 "overlay_register(\"%s\"): "
891 "obsolete name \"%s\" already in use "
892 "by overlay \"%s\".\n",
894 on->on_bi.bi_obsolete_names[ i ],
895 tmp->on_bi.bi_type );
901 if ( tmp->on_bi.bi_obsolete_names != NULL ) {
904 for ( i = 0; tmp->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
907 if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
908 Debug( LDAP_DEBUG_ANY,
909 "overlay_register(\"%s\"): "
910 "name already in use "
911 "as obsolete by overlay \"%s\".\n",
913 tmp->on_bi.bi_obsolete_names[ i ], 0 );
917 if ( on->on_bi.bi_obsolete_names != NULL ) {
918 for ( j = 0; on->on_bi.bi_obsolete_names[ j ] != NULL; j++ ) {
919 if ( strcmp( on->on_bi.bi_obsolete_names[ j ], tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
920 Debug( LDAP_DEBUG_ANY,
921 "overlay_register(\"%s\"): "
922 "obsolete name \"%s\" already in use "
923 "as obsolete by overlay \"%s\".\n",
925 on->on_bi.bi_obsolete_names[ j ],
926 tmp->on_bi.bi_type );
935 on->on_next = overlays;
941 * iterator on registered overlays; overlay_next( NULL ) returns the first
942 * overlay; subsequent calls with the previously returned value allow to
943 * iterate over the entire list; returns NULL when no more overlays are
960 * returns a specific registered overlay based on the type; NULL if not
965 overlay_find( const char *over_type )
967 slap_overinst *on = overlays;
969 assert( over_type != NULL );
971 for ( ; on; on = on->on_next ) {
972 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
976 if ( on->on_bi.bi_obsolete_names != NULL ) {
979 for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
980 if ( strcmp( on->on_bi.bi_obsolete_names[ i ], over_type ) == 0 ) {
981 Debug( LDAP_DEBUG_ANY,
982 "overlay_find(\"%s\"): "
983 "obsolete name for \"%s\".\n",
984 on->on_bi.bi_obsolete_names[ i ],
985 on->on_bi.bi_type, 0 );
996 static const char overtype[] = "over";
999 * returns TRUE (1) if the database is actually an overlay instance;
1000 * FALSE (0) otherwise.
1004 overlay_is_over( BackendDB *be )
1006 return be->bd_info->bi_type == overtype;
1010 * returns TRUE (1) if the given database is actually an overlay
1011 * instance and, somewhere in the list, contains the requested overlay;
1012 * FALSE (0) otherwise.
1016 overlay_is_inst( BackendDB *be, const char *over_type )
1020 assert( be != NULL );
1022 if ( !overlay_is_over( be ) ) {
1026 on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
1027 for ( ; on; on = on->on_next ) {
1028 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
1037 overlay_register_control( BackendDB *be, const char *oid )
1042 if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
1046 if ( SLAP_ISGLOBALOVERLAY( be ) ) {
1049 /* add to all backends... */
1050 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
1055 bd->be_ctrls[ cid ] = 1;
1056 bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
1062 be->be_ctrls[ cid ] = 1;
1063 be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
1070 overlay_destroy_one( BackendDB *be, slap_overinst *on )
1072 slap_overinfo *oi = on->on_info;
1073 slap_overinst **oidx;
1075 for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
1076 if ( *oidx == on ) {
1077 *oidx = on->on_next;
1078 if ( on->on_bi.bi_db_destroy ) {
1079 BackendInfo *bi_orig = be->bd_info;
1080 be->bd_info = (BackendInfo *)on;
1081 on->on_bi.bi_db_destroy( be, NULL );
1082 be->bd_info = bi_orig;
1091 overlay_insert( BackendDB *be, slap_overinst *on2, slap_overinst ***prev,
1094 slap_overinfo *oi = (slap_overinfo *)be->bd_info;
1097 on2->on_next = oi->oi_list;
1101 slap_overinst *on, *otmp1 = NULL, *otmp2;
1103 /* Since the list is in reverse order and is singly linked,
1104 * we reverse it to find the idx insertion point. Adding
1105 * on overlay at a specific point should be a pretty
1106 * infrequent occurrence.
1108 for ( on = oi->oi_list; on; on=otmp2 ) {
1109 otmp2 = on->on_next;
1110 on->on_next = otmp1;
1114 /* advance to insertion point */
1115 for ( i=0, on = otmp1; i<idx; i++ ) {
1116 otmp1 = on->on_next;
1117 on->on_next = oi->oi_list;
1121 on2->on_next = oi->oi_list;
1124 *prev = &otmp1->on_next;
1125 /* replace remainder of list */
1126 for ( on=otmp1; on; on=otmp1 ) {
1127 otmp1 = on->on_next;
1128 on->on_next = oi->oi_list;
1136 overlay_move( BackendDB *be, slap_overinst *on, int idx )
1138 slap_overinfo *oi = (slap_overinfo *)be->bd_info;
1139 slap_overinst **onp;
1141 for (onp = &oi->oi_list; *onp; onp= &(*onp)->on_next) {
1147 overlay_insert( be, on, &onp, idx );
1150 /* add an overlay to a particular backend. */
1152 overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res )
1154 slap_overinst *on = NULL, *on2 = NULL, **prev;
1155 slap_overinfo *oi = NULL;
1156 BackendInfo *bi = NULL;
1161 on = overlay_find( ov );
1163 Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
1167 /* If this is the first overlay on this backend, set up the
1168 * overlay info structure
1170 if ( !overlay_is_over( be ) ) {
1173 /* NOTE: the first time a global overlay is configured,
1174 * frontendDB gets this flag; it is used later by overlays
1175 * to determine if they're stacked on top of the frontendDB */
1176 if ( be->bd_info == frontendDB->bd_info || SLAP_ISGLOBALOVERLAY( be ) ) {
1178 if ( on->on_bi.bi_flags & SLAPO_BFLAG_DBONLY ) {
1179 Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1180 "overlay \"%s\" cannot be global.\n",
1185 } else if ( on->on_bi.bi_flags & SLAPO_BFLAG_GLOBONLY ) {
1186 Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1187 "overlay \"%s\" can only be global.\n",
1192 oi = ch_malloc( sizeof( slap_overinfo ) );
1193 oi->oi_orig = be->bd_info;
1194 oi->oi_bi = *be->bd_info;
1198 SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
1201 /* Save a pointer to ourself in bi_private.
1203 oi->oi_bi.bi_private = oi;
1205 bi = (BackendInfo *)oi;
1207 bi->bi_type = (char *)overtype;
1209 bi->bi_db_config = over_db_config;
1210 bi->bi_db_open = over_db_open;
1211 bi->bi_db_close = over_db_close;
1212 bi->bi_db_destroy = over_db_destroy;
1214 bi->bi_op_bind = over_op_bind;
1215 bi->bi_op_unbind = over_op_unbind;
1216 bi->bi_op_search = over_op_search;
1217 bi->bi_op_compare = over_op_compare;
1218 bi->bi_op_modify = over_op_modify;
1219 bi->bi_op_modrdn = over_op_modrdn;
1220 bi->bi_op_add = over_op_add;
1221 bi->bi_op_delete = over_op_delete;
1222 bi->bi_op_abandon = over_op_abandon;
1223 bi->bi_op_cancel = over_op_cancel;
1225 bi->bi_extended = over_op_extended;
1228 * this is fine because it has the same
1229 * args of the operations; we need to rework
1230 * all the hooks to share the same args
1231 * of the operations...
1233 bi->bi_operational = over_aux_operational;
1234 bi->bi_chk_referrals = over_aux_chk_referrals;
1235 bi->bi_chk_controls = over_aux_chk_controls;
1237 /* these have specific arglists */
1238 bi->bi_entry_get_rw = over_entry_get_rw;
1239 bi->bi_entry_release_rw = over_entry_release_rw;
1240 bi->bi_access_allowed = over_access_allowed;
1241 bi->bi_acl_group = over_acl_group;
1242 bi->bi_acl_attribute = over_acl_attribute;
1244 bi->bi_connection_init = over_connection_init;
1245 bi->bi_connection_destroy = over_connection_destroy;
1250 if ( overlay_is_inst( be, ov ) ) {
1251 Debug( LDAP_DEBUG_ANY, "overlay_config(): "
1252 "overlay \"%s\" already in list\n",
1254 if ( SLAPO_SINGLE( be ) ) {
1259 oi = be->bd_info->bi_private;
1262 /* Insert new overlay into list. By default overlays are
1263 * added to head of list and executed in LIFO order.
1265 on2 = ch_calloc( 1, sizeof(slap_overinst) );
1269 prev = &oi->oi_list;
1270 /* Do we need to find the insertion point? */
1274 /* count current overlays */
1275 for ( i=0, on=oi->oi_list; on; on=on->on_next, i++ );
1277 /* are we just appending a new one? */
1281 overlay_insert( be, on2, &prev, idx );
1283 /* Any initialization needed? */
1284 if ( on2->on_bi.bi_db_init ) {
1286 be->bd_info = (BackendInfo *)on2;
1287 rc = on2->on_bi.bi_db_init( be, NULL );
1288 be->bd_info = (BackendInfo *)oi;
1290 *prev = on2->on_next;