]> git.sur5r.net Git - openldap/blob - servers/slapd/backover.c
b3c06b04f4dd080228a7eaa090a7026acf7b82e5
[openldap] / servers / slapd / backover.c
1 /* backover.c - backend overlay routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
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>.
15  */
16
17 /* Functions to overlay other modules over a backend. */
18
19 #include "portable.h"
20
21 #include <stdio.h>
22
23 #include <ac/string.h>
24 #include <ac/socket.h>
25
26 #define SLAPD_TOOLS
27 #include "slap.h"
28 #include "config.h"
29
30 static slap_overinst *overlays;
31
32 enum db_which {
33         db_open = 0,
34         db_close,
35         db_destroy,
36         db_last
37 };
38
39 static int
40 over_db_func(
41         BackendDB *be,
42         enum db_which which
43 )
44 {
45         slap_overinfo *oi = be->bd_info->bi_private;
46         slap_overinst *on = oi->oi_list;
47         BackendInfo *bi_orig = be->bd_info;
48         BI_db_open **func;
49         int rc = 0;
50
51         func = &oi->oi_orig->bi_db_open;
52         if ( func[which] ) {
53                 be->bd_info = oi->oi_orig;
54                 rc = func[which]( be );
55         }
56
57         for (; on && rc == 0; on=on->on_next) {
58                 be->bd_info = &on->on_bi;
59                 func = &on->on_bi.bi_db_open;
60                 if (func[which]) {
61                         rc = func[which]( be );
62                 }
63         }
64         be->bd_info = bi_orig;
65         return rc;
66 }
67
68 static int
69 over_db_config(
70         BackendDB *be,
71         const char *fname,
72         int lineno,
73         int argc,
74         char **argv
75 )
76 {
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;
81         ConfigArgs ca = {0};
82         int rc = 0;
83
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,
88                         argc, argv );
89
90                 if ( be->bd_info != oi->oi_orig ) {
91                         slap_overinfo   *oi2;
92                         slap_overinst   *on2, **onp;
93                         BackendDB       be2 = *be;
94                         int             i;
95
96                         /* a database added an overlay;
97                          * work it around... */
98                         assert( overlay_is_over( be ) );
99                         
100                         oi2 = ( slap_overinfo * )be->bd_info->bi_private;
101                         on2 = oi2->oi_list;
102
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;
108
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 );
115
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 */
122                                 }
123                         }
124                         *onp = oi->oi_list;
125
126                         oi->oi_list = on2;
127
128                         ch_free( be->bd_info );
129                 }
130
131                 be->bd_info = (BackendInfo *)oi;
132                 if ( rc != SLAP_CONF_UNKNOWN ) return rc;
133         }
134
135         ca.argv = argv;
136         ca.argc = argc;
137         ca.fname = fname;
138         ca.lineno = lineno;
139         ca.be = be;
140         for (; on; on=on->on_next) {
141                 rc = SLAP_CONF_UNKNOWN;
142                 if (on->on_bi.bi_cf_ocs) {
143                         ConfigTable *ct;
144                         ca.bi = &on->on_bi;
145                         ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
146                         if ( ct ) {
147                                 rc = config_add_vals( ct, &ca );
148                         }
149                 }
150                 if (on->on_bi.bi_db_config && rc == SLAP_CONF_UNKNOWN) {
151                         be->bd_info = &on->on_bi;
152                         rc = on->on_bi.bi_db_config( be, fname, lineno,
153                                 argc, argv );
154                         if ( rc != SLAP_CONF_UNKNOWN ) break;
155                 }
156         }
157         be->bd_info = bi_orig;
158         be->be_cf_ocs = be_cf_ocs;
159         
160         return rc;
161 }
162
163 static int
164 over_db_open(
165         BackendDB *be
166 )
167 {
168         return over_db_func( be, db_open );
169 }
170
171 static int
172 over_db_close(
173         BackendDB *be
174 )
175 {
176         slap_overinfo *oi = be->bd_info->bi_private;
177         slap_overinst *on = oi->oi_list;
178         BackendInfo *bi_orig = be->bd_info;
179         int rc = 0;
180
181         for (; on && rc == 0; on=on->on_next) {
182                 be->bd_info = &on->on_bi;
183                 if ( be->bd_info->bi_db_close ) {
184                         rc = be->bd_info->bi_db_close( be );
185                 }
186         }
187
188         if ( oi->oi_orig->bi_db_close ) {
189                 be->bd_info = oi->oi_orig;
190                 rc = be->bd_info->bi_db_close( be );
191         }
192
193         be->bd_info = bi_orig;
194         return rc;
195 }
196
197 static int
198 over_db_destroy(
199         BackendDB *be
200 )
201 {
202         slap_overinfo *oi = be->bd_info->bi_private;
203         slap_overinst *on = oi->oi_list, *next;
204         int rc;
205
206         rc = over_db_func( be, db_destroy );
207
208         for (next = on->on_next; on; on=next) {
209                 next = on->on_next;
210                 free( on );
211         }
212         free( oi );
213         return rc;
214 }
215
216 static int
217 over_back_response ( Operation *op, SlapReply *rs )
218 {
219         slap_overinfo *oi = op->o_callback->sc_private;
220         slap_overinst *on = oi->oi_list;
221         int rc = SLAP_CB_CONTINUE;
222         BackendDB *be = op->o_bd, db = *op->o_bd;
223
224         db.be_flags |= SLAP_DBFLAG_OVERLAY;
225         op->o_bd = &db;
226         for (; on; on=on->on_next ) {
227                 if ( on->on_response ) {
228                         db.bd_info = (BackendInfo *)on;
229                         rc = on->on_response( op, rs );
230                         if ( rc != SLAP_CB_CONTINUE ) break;
231                 }
232         }
233         op->o_bd = be;
234         return rc;
235 }
236
237 #ifdef SLAP_OVERLAY_ACCESS
238 static int
239 over_access_allowed(
240         Operation               *op,
241         Entry                   *e,
242         AttributeDescription    *desc,
243         struct berval           *val,
244         slap_access_t           access,
245         AccessControlState      *state,
246         slap_mask_t             *maskp )
247 {
248         slap_overinfo *oi;
249         slap_overinst *on;
250         BackendInfo *bi = op->o_bd->bd_info;
251         BackendDB *be = op->o_bd, db;
252         int rc = SLAP_CB_CONTINUE;
253
254         /* FIXME: used to happen for instance during abandon
255          * when global overlays are used... */
256         assert( op->o_bd != NULL );
257
258         oi = op->o_bd->bd_info->bi_private;
259         on = oi->oi_list;
260
261         for ( ; on; on = on->on_next ) {
262                 if ( on->on_bi.bi_access_allowed ) {
263                         /* NOTE: do not copy the structure until required */
264                         if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
265                                 db = *op->o_bd;
266                                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
267                                 op->o_bd = &db;
268                         }
269
270                         op->o_bd->bd_info = (BackendInfo *)on;
271                         rc = on->on_bi.bi_access_allowed( op, e,
272                                 desc, val, access, state, maskp );
273                         if ( rc != SLAP_CB_CONTINUE ) break;
274                 }
275         }
276
277         if ( rc == SLAP_CB_CONTINUE ) {
278                 BI_access_allowed       *bi_access_allowed;
279
280                 /* if the database structure was changed, o_bd points to a
281                  * copy of the structure; put the original bd_info in place */
282                 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
283                         op->o_bd->bd_info = oi->oi_orig;
284                 }
285
286                 if ( oi->oi_orig->bi_access_allowed ) {
287                         bi_access_allowed = oi->oi_orig->bi_access_allowed;
288                 } else {
289                         bi_access_allowed = slap_access_allowed;
290                 }
291
292                 rc = bi_access_allowed( op, e,
293                         desc, val, access, state, maskp );
294         }
295         /* should not fall thru this far without anything happening... */
296         if ( rc == SLAP_CB_CONTINUE ) {
297                 /* access not allowed */
298                 rc = 0;
299         }
300
301         op->o_bd = be;
302         op->o_bd->bd_info = bi;
303
304         return rc;
305 }
306
307 static int
308 over_acl_group(
309         Operation               *op,
310         Entry                   *e,
311         struct berval           *gr_ndn,
312         struct berval           *op_ndn,
313         ObjectClass             *group_oc,
314         AttributeDescription    *group_at )
315 {
316         slap_overinfo *oi;
317         slap_overinst *on;
318         BackendInfo *bi = op->o_bd->bd_info;
319         BackendDB *be = op->o_bd, db;
320         int rc = SLAP_CB_CONTINUE;
321
322         /* FIXME: used to happen for instance during abandon
323          * when global overlays are used... */
324         assert( op->o_bd != NULL );
325
326         oi = op->o_bd->bd_info->bi_private;
327         on = oi->oi_list;
328
329         for ( ; on; on = on->on_next ) {
330                 if ( on->on_bi.bi_acl_group ) {
331                         /* NOTE: do not copy the structure until required */
332                         if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
333                                 db = *op->o_bd;
334                                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
335                                 op->o_bd = &db;
336                         }
337
338                         op->o_bd->bd_info = (BackendInfo *)on;
339                         rc = on->on_bi.bi_acl_group( op, e,
340                                 gr_ndn, op_ndn, group_oc, group_at );
341                         if ( rc != SLAP_CB_CONTINUE ) break;
342                 }
343         }
344
345         if ( rc == SLAP_CB_CONTINUE ) {
346                 BI_acl_group            *bi_acl_group;
347
348                 /* if the database structure was changed, o_bd points to a
349                  * copy of the structure; put the original bd_info in place */
350                 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
351                         op->o_bd->bd_info = oi->oi_orig;
352                 }
353
354                 if ( oi->oi_orig->bi_acl_group ) {
355                         bi_acl_group = oi->oi_orig->bi_acl_group;
356                 } else {
357                         bi_acl_group = backend_group;
358                 }
359
360                 rc = bi_acl_group( op, e,
361                         gr_ndn, op_ndn, group_oc, group_at );
362         }
363         /* should not fall thru this far without anything happening... */
364         if ( rc == SLAP_CB_CONTINUE ) {
365                 /* access not allowed */
366                 rc = 0;
367         }
368
369         op->o_bd = be;
370         op->o_bd->bd_info = bi;
371
372         return rc;
373 }
374
375 static int
376 over_acl_attribute(
377         Operation               *op,
378         Entry                   *target,
379         struct berval           *entry_ndn,
380         AttributeDescription    *entry_at,
381         BerVarray               *vals,
382         slap_access_t           access )
383 {
384         slap_overinfo *oi;
385         slap_overinst *on;
386         BackendInfo *bi = op->o_bd->bd_info;
387         BackendDB *be = op->o_bd, db;
388         int rc = SLAP_CB_CONTINUE;
389
390         /* FIXME: used to happen for instance during abandon
391          * when global overlays are used... */
392         assert( op->o_bd != NULL );
393
394         oi = op->o_bd->bd_info->bi_private;
395         on = oi->oi_list;
396
397         for ( ; on; on = on->on_next ) {
398                 if ( on->on_bi.bi_acl_attribute ) {
399                         /* NOTE: do not copy the structure until required */
400                         if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
401                                 db = *op->o_bd;
402                                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
403                                 op->o_bd = &db;
404                         }
405
406                         op->o_bd->bd_info = (BackendInfo *)on;
407                         rc = on->on_bi.bi_acl_attribute( op, target,
408                                 entry_ndn, entry_at, vals, access );
409                         if ( rc != SLAP_CB_CONTINUE ) break;
410                 }
411         }
412
413         if ( rc == SLAP_CB_CONTINUE ) {
414                 BI_acl_attribute                *bi_acl_attribute;
415
416                 /* if the database structure was changed, o_bd points to a
417                  * copy of the structure; put the original bd_info in place */
418                 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
419                         op->o_bd->bd_info = oi->oi_orig;
420                 }
421
422                 if ( oi->oi_orig->bi_acl_attribute ) {
423                         bi_acl_attribute = oi->oi_orig->bi_acl_attribute;
424                 } else {
425                         bi_acl_attribute = backend_attribute;
426                 }
427
428                 rc = bi_acl_attribute( op, target,
429                         entry_ndn, entry_at, vals, access );
430         }
431         /* should not fall thru this far without anything happening... */
432         if ( rc == SLAP_CB_CONTINUE ) {
433                 /* access not allowed */
434                 rc = 0;
435         }
436
437         op->o_bd = be;
438         op->o_bd->bd_info = bi;
439
440         return rc;
441 }
442 #endif /* SLAP_OVERLAY_ACCESS */
443
444 /*
445  * default return code in case of missing backend function
446  * and overlay stack returning SLAP_CB_CONTINUE
447  */
448 static int op_rc[ op_last ] = {
449         LDAP_UNWILLING_TO_PERFORM,      /* bind */
450         LDAP_UNWILLING_TO_PERFORM,      /* unbind */
451         LDAP_UNWILLING_TO_PERFORM,      /* search */
452         SLAP_CB_CONTINUE,               /* compare; pass to frontend */
453         LDAP_UNWILLING_TO_PERFORM,      /* modify */
454         LDAP_UNWILLING_TO_PERFORM,      /* modrdn */
455         LDAP_UNWILLING_TO_PERFORM,      /* add */
456         LDAP_UNWILLING_TO_PERFORM,      /* delete */
457         LDAP_UNWILLING_TO_PERFORM,      /* abandon */
458         LDAP_UNWILLING_TO_PERFORM,      /* cancel */
459         LDAP_UNWILLING_TO_PERFORM,      /* extended */
460         LDAP_SUCCESS,                   /* aux_operational */
461         LDAP_SUCCESS,                   /* aux_chk_referrals */
462         SLAP_CB_CONTINUE                /* aux_chk_controls; pass to frontend */
463 };
464
465 int overlay_op_walk(
466         Operation *op,
467         SlapReply *rs,
468         slap_operation_t which,
469         slap_overinfo *oi,
470         slap_overinst *on
471 )
472 {
473         BI_op_bind **func;
474         int rc = SLAP_CB_CONTINUE;
475
476         for (; on; on=on->on_next ) {
477                 func = &on->on_bi.bi_op_bind;
478                 if ( func[which] ) {
479                         op->o_bd->bd_info = (BackendInfo *)on;
480                         rc = func[which]( op, rs );
481                         if ( rc != SLAP_CB_CONTINUE ) break;
482                 }
483         }
484
485         func = &oi->oi_orig->bi_op_bind;
486         if ( func[which] && rc == SLAP_CB_CONTINUE ) {
487                 op->o_bd->bd_info = oi->oi_orig;
488                 rc = func[which]( op, rs );
489         }
490         /* should not fall thru this far without anything happening... */
491         if ( rc == SLAP_CB_CONTINUE ) {
492                 rc = op_rc[ which ];
493         }
494
495         /* The underlying backend didn't handle the request, make sure
496          * overlay cleanup is processed.
497          */
498         if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
499                 slap_callback *sc_next;
500                 for ( ; op->o_callback && op->o_callback->sc_response !=
501                         over_back_response; op->o_callback = sc_next ) {
502                         sc_next = op->o_callback->sc_next;
503                         if ( op->o_callback->sc_cleanup ) {
504                                 op->o_callback->sc_cleanup( op, rs );
505                         }
506                 }
507         }
508         return rc;
509 }
510
511 static int
512 over_op_func(
513         Operation *op,
514         SlapReply *rs,
515         slap_operation_t which
516 )
517 {
518         slap_overinfo *oi;
519         slap_overinst *on;
520         BI_op_bind **func;
521         BackendDB *be = op->o_bd, db;
522         slap_callback cb = {NULL, over_back_response, NULL, NULL};
523         int rc = SLAP_CB_CONTINUE;
524
525         /* FIXME: used to happen for instance during abandon
526          * when global overlays are used... */
527         assert( op->o_bd != NULL );
528
529         oi = op->o_bd->bd_info->bi_private;
530         on = oi->oi_list;
531
532         if ( !SLAP_ISOVERLAY( op->o_bd )) {
533                 db = *op->o_bd;
534                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
535                 op->o_bd = &db;
536         }
537         cb.sc_next = op->o_callback;
538         cb.sc_private = oi;
539         op->o_callback = &cb;
540
541         rc = overlay_op_walk( op, rs, which, oi, on );
542
543         op->o_bd = be;
544         op->o_callback = cb.sc_next;
545         return rc;
546 }
547
548 static int
549 over_op_bind( Operation *op, SlapReply *rs )
550 {
551         return over_op_func( op, rs, op_bind );
552 }
553
554 static int
555 over_op_unbind( Operation *op, SlapReply *rs )
556 {
557         return over_op_func( op, rs, op_unbind );
558 }
559
560 static int
561 over_op_search( Operation *op, SlapReply *rs )
562 {
563         return over_op_func( op, rs, op_search );
564 }
565
566 static int
567 over_op_compare( Operation *op, SlapReply *rs )
568 {
569         return over_op_func( op, rs, op_compare );
570 }
571
572 static int
573 over_op_modify( Operation *op, SlapReply *rs )
574 {
575         return over_op_func( op, rs, op_modify );
576 }
577
578 static int
579 over_op_modrdn( Operation *op, SlapReply *rs )
580 {
581         return over_op_func( op, rs, op_modrdn );
582 }
583
584 static int
585 over_op_add( Operation *op, SlapReply *rs )
586 {
587         return over_op_func( op, rs, op_add );
588 }
589
590 static int
591 over_op_delete( Operation *op, SlapReply *rs )
592 {
593         return over_op_func( op, rs, op_delete );
594 }
595
596 static int
597 over_op_abandon( Operation *op, SlapReply *rs )
598 {
599         return over_op_func( op, rs, op_abandon );
600 }
601
602 static int
603 over_op_cancel( Operation *op, SlapReply *rs )
604 {
605         return over_op_func( op, rs, op_cancel );
606 }
607
608 static int
609 over_op_extended( Operation *op, SlapReply *rs )
610 {
611         return over_op_func( op, rs, op_extended );
612 }
613
614 static int
615 over_aux_operational( Operation *op, SlapReply *rs )
616 {
617         return over_op_func( op, rs, op_aux_operational );
618 }
619
620 static int
621 over_aux_chk_referrals( Operation *op, SlapReply *rs )
622 {
623         return over_op_func( op, rs, op_aux_chk_referrals );
624 }
625
626 static int
627 over_aux_chk_controls( Operation *op, SlapReply *rs )
628 {
629         return over_op_func( op, rs, op_aux_chk_controls );
630 }
631
632 enum conn_which {
633         conn_init = 0,
634         conn_destroy,
635         conn_last
636 };
637
638 static int
639 over_connection_func(
640         BackendDB       *bd,
641         Connection      *conn,
642         enum conn_which which
643 )
644 {
645         slap_overinfo           *oi;
646         slap_overinst           *on;
647         BackendDB               db;
648         int                     rc = SLAP_CB_CONTINUE;
649         BI_connection_init      **func;
650
651         /* FIXME: used to happen for instance during abandon
652          * when global overlays are used... */
653         assert( bd != NULL );
654
655         oi = bd->bd_info->bi_private;
656         on = oi->oi_list;
657
658         if ( !SLAP_ISOVERLAY( bd ) ) {
659                 db = *bd;
660                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
661                 bd = &db;
662         }
663
664         for ( ; on; on = on->on_next ) {
665                 func = &on->on_bi.bi_connection_init;
666                 if ( func[ which ] ) {
667                         bd->bd_info = (BackendInfo *)on;
668                         rc = func[ which ]( bd, conn );
669                         if ( rc != SLAP_CB_CONTINUE ) break;
670                 }
671         }
672
673         func = &oi->oi_orig->bi_connection_init;
674         if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
675                 bd->bd_info = oi->oi_orig;
676                 rc = func[ which ]( bd, conn );
677         }
678         /* should not fall thru this far without anything happening... */
679         if ( rc == SLAP_CB_CONTINUE ) {
680                 rc = LDAP_UNWILLING_TO_PERFORM;
681         }
682
683         return rc;
684 }
685
686 static int
687 over_connection_init(
688         BackendDB       *bd,
689         Connection      *conn
690 )
691 {
692         return over_connection_func( bd, conn, conn_init );
693 }
694
695 static int
696 over_connection_destroy(
697         BackendDB       *bd,
698         Connection      *conn
699 )
700 {
701         return over_connection_func( bd, conn, conn_destroy );
702 }
703
704 int
705 overlay_register(
706         slap_overinst *on
707 )
708 {
709         on->on_next = overlays;
710         overlays = on;
711         return 0;
712 }
713
714 /*
715  * iterator on registered overlays; overlay_next( NULL ) returns the first
716  * overlay; * subsequent calls with the previously returned value allow to 
717  * iterate * over the entire list; returns NULL when no more overlays are 
718  * registered.
719  */
720
721 slap_overinst *
722 overlay_next(
723         slap_overinst *on
724 )
725 {
726         if ( on == NULL ) {
727                 return overlays;
728         }
729
730         return on->on_next;
731 }
732
733 /*
734  * returns a specific registered overlay based on the type; NULL if not
735  * registered.
736  */
737
738 slap_overinst *
739 overlay_find( const char *over_type )
740 {
741         slap_overinst *on = overlays;
742
743         assert( over_type != NULL );
744
745         for ( ; on; on = on->on_next ) {
746                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
747                         break;
748                 }
749         }
750
751         return on;
752 }
753
754 static const char overtype[] = "over";
755
756 /*
757  * returns TRUE (1) if the database is actually an overlay instance;
758  * FALSE (0) otherwise.
759  */
760
761 int
762 overlay_is_over( BackendDB *be )
763 {
764         return be->bd_info->bi_type == overtype;
765 }
766
767 /*
768  * returns TRUE (1) if the given database is actually an overlay
769  * instance and, somewhere in the list, contains the requested overlay;
770  * FALSE (0) otherwise.
771  */
772
773 int
774 overlay_is_inst( BackendDB *be, const char *over_type )
775 {
776         slap_overinst   *on;
777
778         assert( be != NULL );
779
780         if ( !overlay_is_over( be ) ) {
781                 return 0;
782         }
783         
784         on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
785         for ( ; on; on = on->on_next ) {
786                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
787                         return 1;
788                 }
789         }
790
791         return 0;
792 }
793
794 int
795 overlay_register_control( BackendDB *be, const char *oid )
796 {
797         int             rc = 0;
798         int             gotit = 0;
799         int             cid;
800
801         if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
802                 return -1;
803         }
804
805         if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) {
806                 BackendDB *bd;
807                 
808                 /* add to all backends... */
809                 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
810                         if ( be == bd ) {
811                                 gotit = 1;
812                         }
813
814                         bd->be_ctrls[ cid ] = 1;
815                         bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
816                 }
817
818         }
819         
820         if ( rc == 0 && !gotit ) {
821                 be->be_ctrls[ cid ] = 1;
822                 be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
823         }
824
825         return rc;
826 }
827
828 void
829 overlay_destroy_one( BackendDB *be, slap_overinst *on )
830 {
831         slap_overinfo *oi = on->on_info;
832         slap_overinst **oidx;
833
834         for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
835                 if ( *oidx == on ) {
836                         *oidx = on->on_next;
837                         if ( on->on_bi.bi_db_destroy ) {
838                                 BackendInfo *bi_orig = be->bd_info;
839                                 be->bd_info = (BackendInfo *)on;
840                                 on->on_bi.bi_db_destroy( be );
841                                 be->bd_info = bi_orig;
842                         }
843                         free( on );
844                         break;
845                 }
846         }
847 }
848
849 /* add an overlay to a particular backend. */
850 int
851 overlay_config( BackendDB *be, const char *ov )
852 {
853         slap_overinst *on = NULL, *on2 = NULL;
854         slap_overinfo *oi = NULL;
855         BackendInfo *bi = NULL;
856
857         on = overlay_find( ov );
858         if ( !on ) {
859                 Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
860                 return 1;
861         }
862
863         /* If this is the first overlay on this backend, set up the
864          * overlay info structure
865          */
866         if ( !overlay_is_over( be ) ) {
867                 oi = ch_malloc( sizeof( slap_overinfo ) );
868                 oi->oi_orig = be->bd_info;
869                 oi->oi_bi = *be->bd_info;
870
871                 /* NOTE: the first time a global overlay is configured,
872                  * frontendDB gets this flag; it is used later by overlays
873                  * to determine if they're stacked on top of the frontendDB */
874                 if ( oi->oi_orig == frontendDB->bd_info ) {
875                         SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
876                 }
877
878                 /* Save a pointer to ourself in bi_private.
879                  */
880                 oi->oi_bi.bi_private = oi;
881                 oi->oi_list = NULL;
882                 bi = (BackendInfo *)oi;
883
884                 bi->bi_type = (char *)overtype;
885
886                 bi->bi_db_config = over_db_config;
887                 bi->bi_db_open = over_db_open;
888                 bi->bi_db_close = over_db_close;
889                 bi->bi_db_destroy = over_db_destroy;
890
891                 bi->bi_op_bind = over_op_bind;
892                 bi->bi_op_unbind = over_op_unbind;
893                 bi->bi_op_search = over_op_search;
894                 bi->bi_op_compare = over_op_compare;
895                 bi->bi_op_modify = over_op_modify;
896                 bi->bi_op_modrdn = over_op_modrdn;
897                 bi->bi_op_add = over_op_add;
898                 bi->bi_op_delete = over_op_delete;
899                 bi->bi_op_abandon = over_op_abandon;
900                 bi->bi_op_cancel = over_op_cancel;
901
902                 bi->bi_extended = over_op_extended;
903
904                 /*
905                  * this is fine because it has the same
906                  * args of the operations; we need to rework
907                  * all the hooks to share the same args
908                  * of the operations...
909                  */
910                 bi->bi_operational = over_aux_operational;
911                 bi->bi_chk_referrals = over_aux_chk_referrals;
912                 bi->bi_chk_controls = over_aux_chk_controls;
913
914 #ifdef SLAP_OVERLAY_ACCESS
915                 /* these have specific arglists */
916                 bi->bi_access_allowed = over_access_allowed;
917                 bi->bi_acl_group = over_acl_group;
918                 bi->bi_acl_attribute = over_acl_attribute;
919 #endif /* SLAP_OVERLAY_ACCESS */
920                 
921                 bi->bi_connection_init = over_connection_init;
922                 bi->bi_connection_destroy = over_connection_destroy;
923
924                 be->bd_info = bi;
925
926         } else {
927                 if ( overlay_is_inst( be, ov ) ) {
928                         Debug( LDAP_DEBUG_ANY, "overlay_config(): "
929                                         "warning, overlay \"%s\" "
930                                         "already in list\n", ov, 0, 0 );
931                 }
932
933                 oi = be->bd_info->bi_private;
934         }
935
936         /* Insert new overlay on head of list. Overlays are executed
937          * in reverse of config order...
938          */
939         on2 = ch_calloc( 1, sizeof(slap_overinst) );
940         *on2 = *on;
941         on2->on_info = oi;
942         on2->on_next = oi->oi_list;
943         oi->oi_list = on2;
944
945         /* Any initialization needed? */
946         if ( on->on_bi.bi_db_init ) {
947                 int rc;
948                 be->bd_info = (BackendInfo *)on2;
949                 rc = on2->on_bi.bi_db_init( be );
950                 be->bd_info = (BackendInfo *)oi;
951                 if ( rc ) return rc;
952         }
953
954         return 0;
955 }
956