1 /* backover.c - backend overlay routines */
2 /* $OpenLDAP: pkg/ldap/servers/slapd/backover.c,v 1.71.2.10 2008/07/08 19:25:38 quanah Exp $ */
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
;
41 slap_overinfo
*oi
= be
->bd_info
->bi_private
;
42 slap_overinst
*on
= oi
->oi_list
;
43 BackendInfo
*bi_orig
= be
->bd_info
;
44 struct ConfigOCs
*be_cf_ocs
= be
->be_cf_ocs
;
48 if ( oi
->oi_orig
->bi_db_config
) {
49 be
->bd_info
= oi
->oi_orig
;
50 be
->be_cf_ocs
= oi
->oi_orig
->bi_cf_ocs
;
51 rc
= oi
->oi_orig
->bi_db_config( be
, fname
, lineno
,
54 if ( be
->bd_info
!= oi
->oi_orig
) {
56 slap_overinst
*on2
, **onp
;
60 /* a database added an overlay;
61 * work it around... */
62 assert( overlay_is_over( be
) );
64 oi2
= ( slap_overinfo
* )be
->bd_info
->bi_private
;
67 /* need to put a uniqueness check here as well;
68 * note that in principle there could be more than
69 * one overlay as a result of multiple calls to
71 be2
.bd_info
= (BackendInfo
*)oi
;
73 for ( i
= 0, onp
= &on2
; *onp
; i
++, onp
= &(*onp
)->on_next
) {
74 if ( overlay_is_inst( &be2
, (*onp
)->on_bi
.bi_type
) ) {
75 Debug( LDAP_DEBUG_ANY
, "over_db_config(): "
76 "warning, freshly added "
77 "overlay #%d \"%s\" is already in list\n",
78 i
, (*onp
)->on_bi
.bi_type
, 0 );
80 /* NOTE: if the overlay already exists,
81 * there is no way to merge the results
82 * of the configuration that may have
83 * occurred during bi_db_config(); we
84 * just issue a warning, and the
85 * administrator should deal with this */
92 ch_free( be
->bd_info
);
95 be
->bd_info
= (BackendInfo
*)oi
;
96 if ( rc
!= SLAP_CONF_UNKNOWN
) return rc
;
104 snprintf( ca
.log
, sizeof( ca
.log
), "%s: line %d",
105 ca
.fname
, ca
.lineno
);
107 for (; on
; on
=on
->on_next
) {
108 rc
= SLAP_CONF_UNKNOWN
;
109 if (on
->on_bi
.bi_cf_ocs
) {
112 ct
= config_find_keyword( on
->on_bi
.bi_cf_ocs
->co_table
, &ca
);
114 ca
.table
= on
->on_bi
.bi_cf_ocs
->co_type
;
115 rc
= config_add_vals( ct
, &ca
);
116 if ( rc
!= SLAP_CONF_UNKNOWN
)
120 if (on
->on_bi
.bi_db_config
&& rc
== SLAP_CONF_UNKNOWN
) {
121 be
->bd_info
= &on
->on_bi
;
122 rc
= on
->on_bi
.bi_db_config( be
, fname
, lineno
,
124 if ( rc
!= SLAP_CONF_UNKNOWN
) break;
127 be
->bd_info
= bi_orig
;
128 be
->be_cf_ocs
= be_cf_ocs
;
139 slap_overinfo
*oi
= be
->bd_info
->bi_private
;
140 slap_overinst
*on
= oi
->oi_list
;
144 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
145 db
.bd_info
= oi
->oi_orig
;
146 if ( db
.bd_info
->bi_db_open
) {
147 rc
= db
.bd_info
->bi_db_open( &db
, cr
);
150 for (; on
&& rc
== 0; on
=on
->on_next
) {
151 db
.bd_info
= &on
->on_bi
;
152 if ( db
.bd_info
->bi_db_open
) {
153 rc
= db
.bd_info
->bi_db_open( &db
, cr
);
166 slap_overinfo
*oi
= be
->bd_info
->bi_private
;
167 slap_overinst
*on
= oi
->oi_list
;
168 BackendInfo
*bi_orig
= be
->bd_info
;
171 for (; on
&& rc
== 0; on
=on
->on_next
) {
172 be
->bd_info
= &on
->on_bi
;
173 if ( be
->bd_info
->bi_db_close
) {
174 rc
= be
->bd_info
->bi_db_close( be
, cr
);
178 if ( oi
->oi_orig
->bi_db_close
) {
179 be
->bd_info
= oi
->oi_orig
;
180 rc
= be
->bd_info
->bi_db_close( be
, cr
);
183 be
->bd_info
= bi_orig
;
193 slap_overinfo
*oi
= be
->bd_info
->bi_private
;
194 slap_overinst
*on
= oi
->oi_list
, *next
;
195 BackendInfo
*bi_orig
= be
->bd_info
;
198 be
->bd_info
= oi
->oi_orig
;
199 if ( be
->bd_info
->bi_db_destroy
) {
200 rc
= be
->bd_info
->bi_db_destroy( be
, cr
);
203 for (; on
&& rc
== 0; on
=on
->on_next
) {
204 be
->bd_info
= &on
->on_bi
;
205 if ( be
->bd_info
->bi_db_destroy
) {
206 rc
= be
->bd_info
->bi_db_destroy( be
, cr
);
212 for (next
= on
->on_next
; on
; on
=next
) {
217 be
->bd_info
= bi_orig
;
223 over_back_response ( Operation
*op
, SlapReply
*rs
)
225 slap_overinfo
*oi
= op
->o_callback
->sc_private
;
226 slap_overinst
*on
= oi
->oi_list
;
227 int rc
= SLAP_CB_CONTINUE
;
228 BackendDB
*be
= op
->o_bd
, db
= *op
->o_bd
;
230 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
232 for (; on
; on
=on
->on_next
) {
233 if ( on
->on_response
) {
234 db
.bd_info
= (BackendInfo
*)on
;
235 rc
= on
->on_response( op
, rs
);
236 if ( rc
!= SLAP_CB_CONTINUE
) break;
239 /* Bypass the remaining on_response layers, but allow
240 * normal execution to continue.
242 if ( rc
== SLAP_CB_BYPASS
)
243 rc
= SLAP_CB_CONTINUE
;
252 AttributeDescription
*desc
,
254 slap_access_t access
,
255 AccessControlState
*state
,
261 BackendDB
*be
= op
->o_bd
, db
;
262 int rc
= SLAP_CB_CONTINUE
;
264 /* FIXME: used to happen for instance during abandon
265 * when global overlays are used... */
266 assert( op
->o_bd
!= NULL
);
268 bi
= op
->o_bd
->bd_info
;
269 /* Were we invoked on the frontend? */
270 if ( !bi
->bi_access_allowed
) {
271 oi
= frontendDB
->bd_info
->bi_private
;
273 oi
= op
->o_bd
->bd_info
->bi_private
;
277 for ( ; on
; on
= on
->on_next
) {
278 if ( on
->on_bi
.bi_access_allowed
) {
279 /* NOTE: do not copy the structure until required */
280 if ( !SLAP_ISOVERLAY( op
->o_bd
) ) {
282 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
286 op
->o_bd
->bd_info
= (BackendInfo
*)on
;
287 rc
= on
->on_bi
.bi_access_allowed( op
, e
,
288 desc
, val
, access
, state
, maskp
);
289 if ( rc
!= SLAP_CB_CONTINUE
) break;
293 if ( rc
== SLAP_CB_CONTINUE
) {
294 BI_access_allowed
*bi_access_allowed
;
296 /* if the database structure was changed, o_bd points to a
297 * copy of the structure; put the original bd_info in place */
298 if ( SLAP_ISOVERLAY( op
->o_bd
) ) {
299 op
->o_bd
->bd_info
= oi
->oi_orig
;
302 if ( oi
->oi_orig
->bi_access_allowed
) {
303 bi_access_allowed
= oi
->oi_orig
->bi_access_allowed
;
305 bi_access_allowed
= slap_access_allowed
;
308 rc
= bi_access_allowed( op
, e
,
309 desc
, val
, access
, state
, maskp
);
311 /* should not fall thru this far without anything happening... */
312 if ( rc
== SLAP_CB_CONTINUE
) {
313 /* access not allowed */
318 op
->o_bd
->bd_info
= bi
;
324 overlay_entry_get_ov(
328 AttributeDescription
*ad
,
333 slap_overinfo
*oi
= on
->on_info
;
334 BackendDB
*be
= op
->o_bd
, db
;
335 BackendInfo
*bi
= op
->o_bd
->bd_info
;
336 int rc
= SLAP_CB_CONTINUE
;
338 for ( ; on
; on
= on
->on_next
) {
339 if ( on
->on_bi
.bi_entry_get_rw
) {
340 /* NOTE: do not copy the structure until required */
341 if ( !SLAP_ISOVERLAY( op
->o_bd
) ) {
343 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
347 op
->o_bd
->bd_info
= (BackendInfo
*)on
;
348 rc
= on
->on_bi
.bi_entry_get_rw( op
, dn
,
350 if ( rc
!= SLAP_CB_CONTINUE
) break;
354 if ( rc
== SLAP_CB_CONTINUE
) {
355 /* if the database structure was changed, o_bd points to a
356 * copy of the structure; put the original bd_info in place */
357 if ( SLAP_ISOVERLAY( op
->o_bd
) ) {
358 op
->o_bd
->bd_info
= oi
->oi_orig
;
361 if ( oi
->oi_orig
->bi_entry_get_rw
) {
362 rc
= oi
->oi_orig
->bi_entry_get_rw( op
, dn
,
366 /* should not fall thru this far without anything happening... */
367 if ( rc
== SLAP_CB_CONTINUE
) {
368 rc
= LDAP_UNWILLING_TO_PERFORM
;
372 op
->o_bd
->bd_info
= bi
;
382 AttributeDescription
*ad
,
389 assert( op
->o_bd
!= NULL
);
391 oi
= op
->o_bd
->bd_info
->bi_private
;
394 return overlay_entry_get_ov( op
, dn
, oc
, ad
, rw
, e
, on
);
398 overlay_entry_release_ov(
404 slap_overinfo
*oi
= on
->on_info
;
405 BackendDB
*be
= op
->o_bd
, db
;
406 BackendInfo
*bi
= op
->o_bd
->bd_info
;
407 int rc
= SLAP_CB_CONTINUE
;
409 for ( ; on
; on
= on
->on_next
) {
410 if ( on
->on_bi
.bi_entry_release_rw
) {
411 /* NOTE: do not copy the structure until required */
412 if ( !SLAP_ISOVERLAY( op
->o_bd
) ) {
414 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
418 op
->o_bd
->bd_info
= (BackendInfo
*)on
;
419 rc
= on
->on_bi
.bi_entry_release_rw( op
, e
, rw
);
420 if ( rc
!= SLAP_CB_CONTINUE
) break;
424 if ( rc
== SLAP_CB_CONTINUE
) {
425 /* if the database structure was changed, o_bd points to a
426 * copy of the structure; put the original bd_info in place */
427 if ( SLAP_ISOVERLAY( op
->o_bd
) ) {
428 op
->o_bd
->bd_info
= oi
->oi_orig
;
431 if ( oi
->oi_orig
->bi_entry_release_rw
) {
432 rc
= oi
->oi_orig
->bi_entry_release_rw( op
, e
, rw
);
435 /* should not fall thru this far without anything happening... */
436 if ( rc
== SLAP_CB_CONTINUE
) {
442 op
->o_bd
->bd_info
= bi
;
448 over_entry_release_rw(
456 assert( op
->o_bd
!= NULL
);
458 oi
= op
->o_bd
->bd_info
->bi_private
;
461 return overlay_entry_release_ov( op
, e
, rw
, on
);
468 struct berval
*gr_ndn
,
469 struct berval
*op_ndn
,
470 ObjectClass
*group_oc
,
471 AttributeDescription
*group_at
)
475 BackendInfo
*bi
= op
->o_bd
->bd_info
;
476 BackendDB
*be
= op
->o_bd
, db
;
477 int rc
= SLAP_CB_CONTINUE
;
479 /* FIXME: used to happen for instance during abandon
480 * when global overlays are used... */
481 assert( op
->o_bd
!= NULL
);
483 oi
= op
->o_bd
->bd_info
->bi_private
;
486 for ( ; on
; on
= on
->on_next
) {
487 if ( on
->on_bi
.bi_acl_group
) {
488 /* NOTE: do not copy the structure until required */
489 if ( !SLAP_ISOVERLAY( op
->o_bd
) ) {
491 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
495 op
->o_bd
->bd_info
= (BackendInfo
*)on
;
496 rc
= on
->on_bi
.bi_acl_group( op
, e
,
497 gr_ndn
, op_ndn
, group_oc
, group_at
);
498 if ( rc
!= SLAP_CB_CONTINUE
) break;
502 if ( rc
== SLAP_CB_CONTINUE
) {
503 BI_acl_group
*bi_acl_group
;
505 /* if the database structure was changed, o_bd points to a
506 * copy of the structure; put the original bd_info in place */
507 if ( SLAP_ISOVERLAY( op
->o_bd
) ) {
508 op
->o_bd
->bd_info
= oi
->oi_orig
;
511 if ( oi
->oi_orig
->bi_acl_group
) {
512 bi_acl_group
= oi
->oi_orig
->bi_acl_group
;
514 bi_acl_group
= backend_group
;
517 rc
= bi_acl_group( op
, e
,
518 gr_ndn
, op_ndn
, group_oc
, group_at
);
520 /* should not fall thru this far without anything happening... */
521 if ( rc
== SLAP_CB_CONTINUE
) {
522 /* access not allowed */
527 op
->o_bd
->bd_info
= bi
;
536 struct berval
*entry_ndn
,
537 AttributeDescription
*entry_at
,
539 slap_access_t access
)
543 BackendInfo
*bi
= op
->o_bd
->bd_info
;
544 BackendDB
*be
= op
->o_bd
, db
;
545 int rc
= SLAP_CB_CONTINUE
;
547 /* FIXME: used to happen for instance during abandon
548 * when global overlays are used... */
549 assert( op
->o_bd
!= NULL
);
551 oi
= op
->o_bd
->bd_info
->bi_private
;
554 for ( ; on
; on
= on
->on_next
) {
555 if ( on
->on_bi
.bi_acl_attribute
) {
556 /* NOTE: do not copy the structure until required */
557 if ( !SLAP_ISOVERLAY( op
->o_bd
) ) {
559 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
563 op
->o_bd
->bd_info
= (BackendInfo
*)on
;
564 rc
= on
->on_bi
.bi_acl_attribute( op
, target
,
565 entry_ndn
, entry_at
, vals
, access
);
566 if ( rc
!= SLAP_CB_CONTINUE
) break;
570 if ( rc
== SLAP_CB_CONTINUE
) {
571 BI_acl_attribute
*bi_acl_attribute
;
573 /* if the database structure was changed, o_bd points to a
574 * copy of the structure; put the original bd_info in place */
575 if ( SLAP_ISOVERLAY( op
->o_bd
) ) {
576 op
->o_bd
->bd_info
= oi
->oi_orig
;
579 if ( oi
->oi_orig
->bi_acl_attribute
) {
580 bi_acl_attribute
= oi
->oi_orig
->bi_acl_attribute
;
582 bi_acl_attribute
= backend_attribute
;
585 rc
= bi_acl_attribute( op
, target
,
586 entry_ndn
, entry_at
, vals
, access
);
588 /* should not fall thru this far without anything happening... */
589 if ( rc
== SLAP_CB_CONTINUE
) {
590 /* access not allowed */
595 op
->o_bd
->bd_info
= bi
;
601 * default return code in case of missing backend function
602 * and overlay stack returning SLAP_CB_CONTINUE
604 static int op_rc
[ op_last
] = {
605 LDAP_UNWILLING_TO_PERFORM
, /* bind */
606 LDAP_UNWILLING_TO_PERFORM
, /* unbind */
607 LDAP_UNWILLING_TO_PERFORM
, /* search */
608 SLAP_CB_CONTINUE
, /* compare; pass to frontend */
609 LDAP_UNWILLING_TO_PERFORM
, /* modify */
610 LDAP_UNWILLING_TO_PERFORM
, /* modrdn */
611 LDAP_UNWILLING_TO_PERFORM
, /* add */
612 LDAP_UNWILLING_TO_PERFORM
, /* delete */
613 LDAP_UNWILLING_TO_PERFORM
, /* abandon */
614 LDAP_UNWILLING_TO_PERFORM
, /* cancel */
615 LDAP_UNWILLING_TO_PERFORM
, /* extended */
616 LDAP_SUCCESS
, /* aux_operational */
617 LDAP_SUCCESS
, /* aux_chk_referrals */
618 SLAP_CB_CONTINUE
/* aux_chk_controls; pass to frontend */
624 slap_operation_t which
,
630 int rc
= SLAP_CB_CONTINUE
;
632 for (; on
; on
=on
->on_next
) {
633 func
= &on
->on_bi
.bi_op_bind
;
635 op
->o_bd
->bd_info
= (BackendInfo
*)on
;
636 rc
= func
[which
]( op
, rs
);
637 if ( rc
!= SLAP_CB_CONTINUE
) break;
640 if ( rc
== SLAP_CB_BYPASS
)
641 rc
= SLAP_CB_CONTINUE
;
643 func
= &oi
->oi_orig
->bi_op_bind
;
644 if ( func
[which
] && rc
== SLAP_CB_CONTINUE
) {
645 op
->o_bd
->bd_info
= oi
->oi_orig
;
646 rc
= func
[which
]( op
, rs
);
648 /* should not fall thru this far without anything happening... */
649 if ( rc
== SLAP_CB_CONTINUE
) {
653 /* The underlying backend didn't handle the request, make sure
654 * overlay cleanup is processed.
656 if ( rc
== LDAP_UNWILLING_TO_PERFORM
) {
657 slap_callback
*sc_next
;
658 for ( ; op
->o_callback
&& op
->o_callback
->sc_response
!=
659 over_back_response
; op
->o_callback
= sc_next
) {
660 sc_next
= op
->o_callback
->sc_next
;
661 if ( op
->o_callback
->sc_cleanup
) {
662 op
->o_callback
->sc_cleanup( op
, rs
);
673 slap_operation_t which
678 BackendDB
*be
= op
->o_bd
, db
;
679 slap_callback cb
= {NULL
, over_back_response
, NULL
, NULL
};
680 int rc
= SLAP_CB_CONTINUE
;
682 /* FIXME: used to happen for instance during abandon
683 * when global overlays are used... */
684 assert( op
->o_bd
!= NULL
);
686 oi
= op
->o_bd
->bd_info
->bi_private
;
689 if ( !SLAP_ISOVERLAY( op
->o_bd
)) {
691 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
694 cb
.sc_next
= op
->o_callback
;
696 op
->o_callback
= &cb
;
698 rc
= overlay_op_walk( op
, rs
, which
, oi
, on
);
701 op
->o_callback
= cb
.sc_next
;
706 over_op_bind( Operation
*op
, SlapReply
*rs
)
708 return over_op_func( op
, rs
, op_bind
);
712 over_op_unbind( Operation
*op
, SlapReply
*rs
)
714 return over_op_func( op
, rs
, op_unbind
);
718 over_op_search( Operation
*op
, SlapReply
*rs
)
720 return over_op_func( op
, rs
, op_search
);
724 over_op_compare( Operation
*op
, SlapReply
*rs
)
726 return over_op_func( op
, rs
, op_compare
);
730 over_op_modify( Operation
*op
, SlapReply
*rs
)
732 return over_op_func( op
, rs
, op_modify
);
736 over_op_modrdn( Operation
*op
, SlapReply
*rs
)
738 return over_op_func( op
, rs
, op_modrdn
);
742 over_op_add( Operation
*op
, SlapReply
*rs
)
744 return over_op_func( op
, rs
, op_add
);
748 over_op_delete( Operation
*op
, SlapReply
*rs
)
750 return over_op_func( op
, rs
, op_delete
);
754 over_op_abandon( Operation
*op
, SlapReply
*rs
)
756 return over_op_func( op
, rs
, op_abandon
);
760 over_op_cancel( Operation
*op
, SlapReply
*rs
)
762 return over_op_func( op
, rs
, op_cancel
);
766 over_op_extended( Operation
*op
, SlapReply
*rs
)
768 return over_op_func( op
, rs
, op_extended
);
772 over_aux_operational( Operation
*op
, SlapReply
*rs
)
774 return over_op_func( op
, rs
, op_aux_operational
);
778 over_aux_chk_referrals( Operation
*op
, SlapReply
*rs
)
780 return over_op_func( op
, rs
, op_aux_chk_referrals
);
784 over_aux_chk_controls( Operation
*op
, SlapReply
*rs
)
786 return over_op_func( op
, rs
, op_aux_chk_controls
);
796 over_connection_func(
799 enum conn_which which
805 int rc
= SLAP_CB_CONTINUE
;
806 BI_connection_init
**func
;
808 /* FIXME: used to happen for instance during abandon
809 * when global overlays are used... */
810 assert( bd
!= NULL
);
812 oi
= bd
->bd_info
->bi_private
;
815 if ( !SLAP_ISOVERLAY( bd
) ) {
817 db
.be_flags
|= SLAP_DBFLAG_OVERLAY
;
821 for ( ; on
; on
= on
->on_next
) {
822 func
= &on
->on_bi
.bi_connection_init
;
823 if ( func
[ which
] ) {
824 bd
->bd_info
= (BackendInfo
*)on
;
825 rc
= func
[ which
]( bd
, conn
);
826 if ( rc
!= SLAP_CB_CONTINUE
) break;
830 func
= &oi
->oi_orig
->bi_connection_init
;
831 if ( func
[ which
] && rc
== SLAP_CB_CONTINUE
) {
832 bd
->bd_info
= oi
->oi_orig
;
833 rc
= func
[ which
]( bd
, conn
);
835 /* should not fall thru this far without anything happening... */
836 if ( rc
== SLAP_CB_CONTINUE
) {
837 rc
= LDAP_UNWILLING_TO_PERFORM
;
844 over_connection_init(
849 return over_connection_func( bd
, conn
, conn_init
);
853 over_connection_destroy(
858 return over_connection_func( bd
, conn
, conn_destroy
);
868 /* FIXME: check for duplicates? */
869 for ( tmp
= overlays
; tmp
!= NULL
; tmp
= tmp
->on_next
) {
870 if ( strcmp( on
->on_bi
.bi_type
, tmp
->on_bi
.bi_type
) == 0 ) {
871 Debug( LDAP_DEBUG_ANY
,
872 "overlay_register(\"%s\"): "
873 "name already in use.\n",
874 on
->on_bi
.bi_type
, 0, 0 );
878 if ( on
->on_bi
.bi_obsolete_names
!= NULL
) {
881 for ( i
= 0; on
->on_bi
.bi_obsolete_names
[ i
] != NULL
; i
++ ) {
882 if ( strcmp( on
->on_bi
.bi_obsolete_names
[ i
], tmp
->on_bi
.bi_type
) == 0 ) {
883 Debug( LDAP_DEBUG_ANY
,
884 "overlay_register(\"%s\"): "
885 "obsolete name \"%s\" already in use "
886 "by overlay \"%s\".\n",
888 on
->on_bi
.bi_obsolete_names
[ i
],
889 tmp
->on_bi
.bi_type
);
895 if ( tmp
->on_bi
.bi_obsolete_names
!= NULL
) {
898 for ( i
= 0; tmp
->on_bi
.bi_obsolete_names
[ i
] != NULL
; i
++ ) {
901 if ( strcmp( on
->on_bi
.bi_type
, tmp
->on_bi
.bi_obsolete_names
[ i
] ) == 0 ) {
902 Debug( LDAP_DEBUG_ANY
,
903 "overlay_register(\"%s\"): "
904 "name already in use "
905 "as obsolete by overlay \"%s\".\n",
907 tmp
->on_bi
.bi_obsolete_names
[ i
], 0 );
911 if ( on
->on_bi
.bi_obsolete_names
!= NULL
) {
912 for ( j
= 0; on
->on_bi
.bi_obsolete_names
[ j
] != NULL
; j
++ ) {
913 if ( strcmp( on
->on_bi
.bi_obsolete_names
[ j
], tmp
->on_bi
.bi_obsolete_names
[ i
] ) == 0 ) {
914 Debug( LDAP_DEBUG_ANY
,
915 "overlay_register(\"%s\"): "
916 "obsolete name \"%s\" already in use "
917 "as obsolete by overlay \"%s\".\n",
919 on
->on_bi
.bi_obsolete_names
[ j
],
920 tmp
->on_bi
.bi_type
);
929 on
->on_next
= overlays
;
935 * iterator on registered overlays; overlay_next( NULL ) returns the first
936 * overlay; subsequent calls with the previously returned value allow to
937 * iterate over the entire list; returns NULL when no more overlays are
954 * returns a specific registered overlay based on the type; NULL if not
959 overlay_find( const char *over_type
)
961 slap_overinst
*on
= overlays
;
963 assert( over_type
!= NULL
);
965 for ( ; on
; on
= on
->on_next
) {
966 if ( strcmp( on
->on_bi
.bi_type
, over_type
) == 0 ) {
970 if ( on
->on_bi
.bi_obsolete_names
!= NULL
) {
973 for ( i
= 0; on
->on_bi
.bi_obsolete_names
[ i
] != NULL
; i
++ ) {
974 if ( strcmp( on
->on_bi
.bi_obsolete_names
[ i
], over_type
) == 0 ) {
975 Debug( LDAP_DEBUG_ANY
,
976 "overlay_find(\"%s\"): "
977 "obsolete name for \"%s\".\n",
978 on
->on_bi
.bi_obsolete_names
[ i
],
979 on
->on_bi
.bi_type
, 0 );
990 static const char overtype
[] = "over";
993 * returns TRUE (1) if the database is actually an overlay instance;
994 * FALSE (0) otherwise.
998 overlay_is_over( BackendDB
*be
)
1000 return be
->bd_info
->bi_type
== overtype
;
1004 * returns TRUE (1) if the given database is actually an overlay
1005 * instance and, somewhere in the list, contains the requested overlay;
1006 * FALSE (0) otherwise.
1010 overlay_is_inst( BackendDB
*be
, const char *over_type
)
1014 assert( be
!= NULL
);
1016 if ( !overlay_is_over( be
) ) {
1020 on
= ((slap_overinfo
*)be
->bd_info
->bi_private
)->oi_list
;
1021 for ( ; on
; on
= on
->on_next
) {
1022 if ( strcmp( on
->on_bi
.bi_type
, over_type
) == 0 ) {
1031 overlay_register_control( BackendDB
*be
, const char *oid
)
1036 if ( slap_find_control_id( oid
, &cid
) == LDAP_CONTROL_NOT_FOUND
) {
1040 if ( SLAP_ISGLOBALOVERLAY( be
) ) {
1043 /* add to all backends... */
1044 LDAP_STAILQ_FOREACH( bd
, &backendDB
, be_next
) {
1049 bd
->be_ctrls
[ cid
] = 1;
1050 bd
->be_ctrls
[ SLAP_MAX_CIDS
] = 1;
1056 be
->be_ctrls
[ cid
] = 1;
1057 be
->be_ctrls
[ SLAP_MAX_CIDS
] = 1;
1064 overlay_destroy_one( BackendDB
*be
, slap_overinst
*on
)
1066 slap_overinfo
*oi
= on
->on_info
;
1067 slap_overinst
**oidx
;
1069 for ( oidx
= &oi
->oi_list
; *oidx
; oidx
= &(*oidx
)->on_next
) {
1070 if ( *oidx
== on
) {
1071 *oidx
= on
->on_next
;
1072 if ( on
->on_bi
.bi_db_destroy
) {
1073 BackendInfo
*bi_orig
= be
->bd_info
;
1074 be
->bd_info
= (BackendInfo
*)on
;
1075 on
->on_bi
.bi_db_destroy( be
, NULL
);
1076 be
->bd_info
= bi_orig
;
1084 #ifdef SLAP_CONFIG_DELETE
1086 overlay_remove( BackendDB
*be
, slap_overinst
*on
)
1088 slap_overinfo
*oi
= on
->on_info
;
1089 slap_overinst
**oidx
, *on2
;
1091 /* remove overlay from oi_list an call db_close and db_destroy
1093 for ( oidx
= &oi
->oi_list
; *oidx
; oidx
= &(*oidx
)->on_next
) {
1094 if ( *oidx
== on
) {
1095 *oidx
= on
->on_next
;
1096 BackendInfo
*bi_orig
= be
->bd_info
;
1097 be
->bd_info
= (BackendInfo
*)on
;
1098 if ( on
->on_bi
.bi_db_close
) {
1099 on
->on_bi
.bi_db_close( be
, NULL
);
1101 if ( on
->on_bi
.bi_db_destroy
) {
1102 on
->on_bi
.bi_db_destroy( be
, NULL
);
1104 be
->bd_info
= bi_orig
;
1110 /* clean up after removing last overlay */
1111 if ( ! oi
->oi_list
)
1113 /* reset db flags and bd_info to orig */
1114 SLAP_DBFLAGS( be
) &= ~SLAP_DBFLAG_GLOBAL_OVERLAY
;
1115 be
->bd_info
= oi
->oi_orig
;
1119 #endif /* SLAP_CONFIG_DELETE */
1122 overlay_insert( BackendDB
*be
, slap_overinst
*on2
, slap_overinst
***prev
,
1125 slap_overinfo
*oi
= (slap_overinfo
*)be
->bd_info
;
1128 on2
->on_next
= oi
->oi_list
;
1132 slap_overinst
*on
, *otmp1
= NULL
, *otmp2
;
1134 /* Since the list is in reverse order and is singly linked,
1135 * we reverse it to find the idx insertion point. Adding
1136 * on overlay at a specific point should be a pretty
1137 * infrequent occurrence.
1139 for ( on
= oi
->oi_list
; on
; on
=otmp2
) {
1140 otmp2
= on
->on_next
;
1141 on
->on_next
= otmp1
;
1145 /* advance to insertion point */
1146 for ( i
=0, on
= otmp1
; i
<idx
; i
++ ) {
1147 otmp1
= on
->on_next
;
1148 on
->on_next
= oi
->oi_list
;
1152 on2
->on_next
= oi
->oi_list
;
1155 *prev
= &otmp1
->on_next
;
1156 /* replace remainder of list */
1157 for ( on
=otmp1
; on
; on
=otmp1
) {
1158 otmp1
= on
->on_next
;
1159 on
->on_next
= oi
->oi_list
;
1167 overlay_move( BackendDB
*be
, slap_overinst
*on
, int idx
)
1169 slap_overinfo
*oi
= (slap_overinfo
*)be
->bd_info
;
1170 slap_overinst
**onp
;
1172 for (onp
= &oi
->oi_list
; *onp
; onp
= &(*onp
)->on_next
) {
1178 overlay_insert( be
, on
, &onp
, idx
);
1181 /* add an overlay to a particular backend. */
1183 overlay_config( BackendDB
*be
, const char *ov
, int idx
, BackendInfo
**res
, ConfigReply
*cr
)
1185 slap_overinst
*on
= NULL
, *on2
= NULL
, **prev
;
1186 slap_overinfo
*oi
= NULL
;
1187 BackendInfo
*bi
= NULL
;
1192 on
= overlay_find( ov
);
1194 Debug( LDAP_DEBUG_ANY
, "overlay \"%s\" not found\n", ov
, 0, 0 );
1198 /* If this is the first overlay on this backend, set up the
1199 * overlay info structure
1201 if ( !overlay_is_over( be
) ) {
1204 /* NOTE: the first time a global overlay is configured,
1205 * frontendDB gets this flag; it is used later by overlays
1206 * to determine if they're stacked on top of the frontendDB */
1207 if ( be
->bd_info
== frontendDB
->bd_info
|| SLAP_ISGLOBALOVERLAY( be
) ) {
1209 if ( on
->on_bi
.bi_flags
& SLAPO_BFLAG_DBONLY
) {
1210 Debug( LDAP_DEBUG_ANY
, "overlay_config(): "
1211 "overlay \"%s\" cannot be global.\n",
1216 } else if ( on
->on_bi
.bi_flags
& SLAPO_BFLAG_GLOBONLY
) {
1217 Debug( LDAP_DEBUG_ANY
, "overlay_config(): "
1218 "overlay \"%s\" can only be global.\n",
1223 oi
= ch_malloc( sizeof( slap_overinfo
) );
1224 oi
->oi_orig
= be
->bd_info
;
1225 oi
->oi_bi
= *be
->bd_info
;
1229 SLAP_DBFLAGS( be
) |= SLAP_DBFLAG_GLOBAL_OVERLAY
;
1232 /* Save a pointer to ourself in bi_private.
1234 oi
->oi_bi
.bi_private
= oi
;
1236 bi
= (BackendInfo
*)oi
;
1238 bi
->bi_type
= (char *)overtype
;
1240 bi
->bi_db_config
= over_db_config
;
1241 bi
->bi_db_open
= over_db_open
;
1242 bi
->bi_db_close
= over_db_close
;
1243 bi
->bi_db_destroy
= over_db_destroy
;
1245 bi
->bi_op_bind
= over_op_bind
;
1246 bi
->bi_op_unbind
= over_op_unbind
;
1247 bi
->bi_op_search
= over_op_search
;
1248 bi
->bi_op_compare
= over_op_compare
;
1249 bi
->bi_op_modify
= over_op_modify
;
1250 bi
->bi_op_modrdn
= over_op_modrdn
;
1251 bi
->bi_op_add
= over_op_add
;
1252 bi
->bi_op_delete
= over_op_delete
;
1253 bi
->bi_op_abandon
= over_op_abandon
;
1254 bi
->bi_op_cancel
= over_op_cancel
;
1256 bi
->bi_extended
= over_op_extended
;
1259 * this is fine because it has the same
1260 * args of the operations; we need to rework
1261 * all the hooks to share the same args
1262 * of the operations...
1264 bi
->bi_operational
= over_aux_operational
;
1265 bi
->bi_chk_referrals
= over_aux_chk_referrals
;
1266 bi
->bi_chk_controls
= over_aux_chk_controls
;
1268 /* these have specific arglists */
1269 bi
->bi_entry_get_rw
= over_entry_get_rw
;
1270 bi
->bi_entry_release_rw
= over_entry_release_rw
;
1271 bi
->bi_access_allowed
= over_access_allowed
;
1272 bi
->bi_acl_group
= over_acl_group
;
1273 bi
->bi_acl_attribute
= over_acl_attribute
;
1275 bi
->bi_connection_init
= over_connection_init
;
1276 bi
->bi_connection_destroy
= over_connection_destroy
;
1281 if ( overlay_is_inst( be
, ov
) ) {
1282 if ( SLAPO_SINGLE( be
) ) {
1283 Debug( LDAP_DEBUG_ANY
, "overlay_config(): "
1284 "overlay \"%s\" already in list\n",
1290 oi
= be
->bd_info
->bi_private
;
1293 /* Insert new overlay into list. By default overlays are
1294 * added to head of list and executed in LIFO order.
1296 on2
= ch_calloc( 1, sizeof(slap_overinst
) );
1300 prev
= &oi
->oi_list
;
1301 /* Do we need to find the insertion point? */
1305 /* count current overlays */
1306 for ( i
=0, on
=oi
->oi_list
; on
; on
=on
->on_next
, i
++ );
1308 /* are we just appending a new one? */
1312 overlay_insert( be
, on2
, &prev
, idx
);
1314 /* Any initialization needed? */
1315 if ( on2
->on_bi
.bi_db_init
) {
1317 be
->bd_info
= (BackendInfo
*)on2
;
1318 rc
= on2
->on_bi
.bi_db_init( be
, cr
);
1319 be
->bd_info
= (BackendInfo
*)oi
;
1321 *prev
= on2
->on_next
;