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