]> git.sur5r.net Git - openldap/blob - servers/slapd/backover.c
ITS#3842 from jtownsend@opendarwin.org - don't free slap_listeners until
[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 { db_open = 0, db_close, db_destroy };
33
34 static int
35 over_db_func(
36         BackendDB *be,
37         enum db_which which
38 )
39 {
40         slap_overinfo *oi = be->bd_info->bi_private;
41         slap_overinst *on = oi->oi_list;
42         BackendInfo *bi_orig = be->bd_info;
43         BI_db_open **func;
44         int rc = 0;
45
46         func = &oi->oi_orig->bi_db_open;
47         if ( func[which] ) {
48                 be->bd_info = oi->oi_orig;
49                 rc = func[which]( be );
50         }
51
52         for (; on && rc == 0; on=on->on_next) {
53                 be->bd_info = &on->on_bi;
54                 func = &on->on_bi.bi_db_open;
55                 if (func[which]) {
56                         rc = func[which]( be );
57                 }
58         }
59         be->bd_info = bi_orig;
60         return rc;
61 }
62
63 static int
64 over_db_config(
65         BackendDB *be,
66         const char *fname,
67         int lineno,
68         int argc,
69         char **argv
70 )
71 {
72         slap_overinfo *oi = be->bd_info->bi_private;
73         slap_overinst *on = oi->oi_list;
74         BackendInfo *bi_orig = be->bd_info;
75         struct ConfigOCs *be_cf_ocs = be->be_cf_ocs;
76         ConfigArgs ca = {0};
77         ConfigTable *ct;
78         int rc = 0;
79
80         if ( oi->oi_orig->bi_db_config ) {
81                 be->bd_info = oi->oi_orig;
82                 be->be_cf_ocs = oi->oi_orig->bi_cf_ocs;
83                 rc = oi->oi_orig->bi_db_config( be, fname, lineno,
84                         argc, argv );
85
86                 if ( be->bd_info != oi->oi_orig ) {
87                         slap_overinfo   *oi2;
88                         slap_overinst   *on2, **onp;
89                         BackendDB       be2 = *be;
90                         int             i;
91
92                         /* a database added an overlay;
93                          * work it around... */
94                         assert( overlay_is_over( be ) );
95                         
96                         oi2 = ( slap_overinfo * )be->bd_info->bi_private;
97                         on2 = oi2->oi_list;
98
99                         /* need to put a uniqueness check here as well;
100                          * note that in principle there could be more than
101                          * one overlay as a result of multiple calls to
102                          * overlay_config() */
103                         be2.bd_info = (BackendInfo *)oi;
104
105                         for ( i = 0, onp = &on2; *onp; i++, onp = &(*onp)->on_next ) {
106                                 if ( overlay_is_inst( &be2, (*onp)->on_bi.bi_type ) ) {
107                                         Debug( LDAP_DEBUG_ANY, "over_db_config(): "
108                                                         "warning, freshly added "
109                                                         "overlay #%d \"%s\" is already in list\n",
110                                                         i, (*onp)->on_bi.bi_type, 0 );
111
112                                         /* NOTE: if the overlay already exists,
113                                          * there is no way to merge the results
114                                          * of the configuration that may have 
115                                          * occurred during bi_db_config(); we
116                                          * just issue a warning, and the 
117                                          * administrator should deal with this */
118                                 }
119                         }
120                         *onp = oi->oi_list;
121
122                         oi->oi_list = on2;
123
124                         ch_free( be->bd_info );
125                 }
126
127                 be->bd_info = (BackendInfo *)oi;
128                 if ( rc != SLAP_CONF_UNKNOWN ) return rc;
129         }
130
131         ca.argv = argv;
132         ca.argc = argc;
133         ca.fname = fname;
134         ca.lineno = lineno;
135         ca.be = be;
136         for (; on; on=on->on_next) {
137                 rc = SLAP_CONF_UNKNOWN;
138                 if (on->on_bi.bi_cf_ocs) {
139                         ConfigTable *ct;
140                         ca.bi = &on->on_bi;
141                         ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
142                         if ( ct ) {
143                                 rc = config_add_vals( ct, &ca );
144                         }
145                 }
146                 if (on->on_bi.bi_db_config && rc == SLAP_CONF_UNKNOWN) {
147                         be->bd_info = &on->on_bi;
148                         rc = on->on_bi.bi_db_config( be, fname, lineno,
149                                 argc, argv );
150                         if ( rc != SLAP_CONF_UNKNOWN ) break;
151                 }
152         }
153         be->bd_info = bi_orig;
154         be->be_cf_ocs = be_cf_ocs;
155         
156         return rc;
157 }
158
159 static int
160 over_db_open(
161         BackendDB *be
162 )
163 {
164         return over_db_func( be, db_open );
165 }
166
167 static int
168 over_db_close(
169         BackendDB *be
170 )
171 {
172         slap_overinfo *oi = be->bd_info->bi_private;
173         slap_overinst *on = oi->oi_list;
174         BackendInfo *bi_orig = be->bd_info;
175         int rc = 0;
176
177         for (; on && rc == 0; on=on->on_next) {
178                 be->bd_info = &on->on_bi;
179                 if ( be->bd_info->bi_db_close ) {
180                         rc = be->bd_info->bi_db_close( be );
181                 }
182         }
183
184         if ( oi->oi_orig->bi_db_close ) {
185                 be->bd_info = oi->oi_orig;
186                 rc = be->bd_info->bi_db_close( be );
187         }
188
189         be->bd_info = bi_orig;
190         return rc;
191 }
192
193 static int
194 over_db_destroy(
195         BackendDB *be
196 )
197 {
198         slap_overinfo *oi = be->bd_info->bi_private;
199         slap_overinst *on = oi->oi_list, *next;
200         int rc;
201
202         rc = over_db_func( be, db_destroy );
203
204         for (next = on->on_next; on; on=next) {
205                 next = on->on_next;
206                 free( on );
207         }
208         free( oi );
209         return rc;
210 }
211
212 static int
213 over_back_response ( Operation *op, SlapReply *rs )
214 {
215         slap_overinfo *oi = op->o_callback->sc_private;
216         slap_overinst *on = oi->oi_list;
217         int rc = SLAP_CB_CONTINUE;
218         BackendDB *be = op->o_bd, db = *op->o_bd;
219
220         db.be_flags |= SLAP_DBFLAG_OVERLAY;
221         op->o_bd = &db;
222         for (; on; on=on->on_next ) {
223                 if ( on->on_response ) {
224                         db.bd_info = (BackendInfo *)on;
225                         rc = on->on_response( op, rs );
226                         if ( rc != SLAP_CB_CONTINUE ) break;
227                 }
228         }
229         op->o_bd = be;
230         return rc;
231 }
232
233 #ifdef SLAP_OVERLAY_ACCESS
234 static int
235 over_access_allowed(
236         Operation               *op,
237         Entry                   *e,
238         AttributeDescription    *desc,
239         struct berval           *val,
240         slap_access_t           access,
241         AccessControlState      *state,
242         slap_mask_t             *maskp )
243 {
244         slap_overinfo *oi;
245         slap_overinst *on;
246         BackendInfo *bi = op->o_bd->bd_info;
247         BackendDB *be = op->o_bd, db;
248         int rc = SLAP_CB_CONTINUE;
249
250         /* FIXME: used to happen for instance during abandon
251          * when global overlays are used... */
252         assert( op->o_bd != NULL );
253
254         oi = op->o_bd->bd_info->bi_private;
255         on = oi->oi_list;
256
257         for ( ; on; on = on->on_next ) {
258                 if ( on->on_bi.bi_access_allowed ) {
259                         /* NOTE: do not copy the structure until required */
260                         if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
261                                 db = *op->o_bd;
262                                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
263                                 op->o_bd = &db;
264                         }
265
266                         op->o_bd->bd_info = (BackendInfo *)on;
267                         rc = on->on_bi.bi_access_allowed( op, e,
268                                 desc, val, access, state, maskp );
269                         if ( rc != SLAP_CB_CONTINUE ) break;
270                 }
271         }
272
273         if ( rc == SLAP_CB_CONTINUE ) {
274                 BI_access_allowed       *bi_access_allowed;
275
276                 /* if the database structure was changed, o_bd points to a
277                  * copy of the structure; put the original bd_info in place */
278                 if ( SLAP_ISOVERLAY( op->o_bd ) ) {
279                         op->o_bd->bd_info = oi->oi_orig;
280                 }
281
282                 if ( oi->oi_orig->bi_access_allowed ) {
283                         bi_access_allowed = oi->oi_orig->bi_access_allowed;
284                 } else {
285                         bi_access_allowed = slap_access_allowed;
286                 }
287
288                 rc = bi_access_allowed( op, e,
289                         desc, val, access, state, maskp );
290         }
291         /* should not fall thru this far without anything happening... */
292         if ( rc == SLAP_CB_CONTINUE ) {
293                 /* access not allowed */
294                 rc = 0;
295         }
296
297         op->o_bd = be;
298         op->o_bd->bd_info = bi;
299
300         return rc;
301 }
302 #endif /* SLAP_OVERLAY_ACCESS */
303
304 enum op_which {
305         op_bind = 0,
306         op_unbind,
307         op_search,
308         op_compare,
309         op_modify,
310         op_modrdn,
311         op_add,
312         op_delete,
313         op_abandon,
314         op_cancel,
315         op_extended,
316         op_aux_operational,
317         op_aux_chk_referrals,
318         op_aux_chk_controls,
319         op_last
320 };
321
322 /*
323  * default return code in case of missing backend function
324  * and overlay stack returning SLAP_CB_CONTINUE
325  */
326 static int op_rc[] = {
327         LDAP_UNWILLING_TO_PERFORM,      /* bind */
328         LDAP_UNWILLING_TO_PERFORM,      /* unbind */
329         LDAP_UNWILLING_TO_PERFORM,      /* search */
330         SLAP_CB_CONTINUE,               /* compare; pass to frontend */
331         LDAP_UNWILLING_TO_PERFORM,      /* modify */
332         LDAP_UNWILLING_TO_PERFORM,      /* modrdn */
333         LDAP_UNWILLING_TO_PERFORM,      /* add */
334         LDAP_UNWILLING_TO_PERFORM,      /* delete */
335         LDAP_UNWILLING_TO_PERFORM,      /* abandon */
336         LDAP_UNWILLING_TO_PERFORM,      /* cancel */
337         LDAP_UNWILLING_TO_PERFORM,      /* extended */
338         LDAP_SUCCESS,                   /* aux_operational */
339         LDAP_SUCCESS,                   /* aux_chk_referrals */
340         SLAP_CB_CONTINUE                /* aux_chk_controls; pass to frontend */
341 };
342
343 static int
344 over_op_func(
345         Operation *op,
346         SlapReply *rs,
347         enum op_which which
348 )
349 {
350         slap_overinfo *oi;
351         slap_overinst *on;
352         BI_op_bind **func;
353         BackendDB *be = op->o_bd, db;
354         slap_callback cb = {NULL, over_back_response, NULL, NULL};
355         int rc = SLAP_CB_CONTINUE;
356
357         /* FIXME: used to happen for instance during abandon
358          * when global overlays are used... */
359         assert( op->o_bd != NULL );
360
361         oi = op->o_bd->bd_info->bi_private;
362         on = oi->oi_list;
363
364         if ( !SLAP_ISOVERLAY( op->o_bd )) {
365                 db = *op->o_bd;
366                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
367                 op->o_bd = &db;
368         }
369         cb.sc_next = op->o_callback;
370         cb.sc_private = oi;
371         op->o_callback = &cb;
372
373         for (; on; on=on->on_next ) {
374                 func = &on->on_bi.bi_op_bind;
375                 if ( func[which] ) {
376                         op->o_bd->bd_info = (BackendInfo *)on;
377                         rc = func[which]( op, rs );
378                         if ( rc != SLAP_CB_CONTINUE ) break;
379                 }
380         }
381
382         func = &oi->oi_orig->bi_op_bind;
383         if ( func[which] && rc == SLAP_CB_CONTINUE ) {
384                 op->o_bd->bd_info = oi->oi_orig;
385                 rc = func[which]( op, rs );
386         }
387         /* should not fall thru this far without anything happening... */
388         if ( rc == SLAP_CB_CONTINUE ) {
389                 rc = op_rc[ which ];
390         }
391
392         /* The underlying backend didn't handle the request, make sure
393          * overlay cleanup is processed.
394          */
395         if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
396                 slap_callback *sc_next;
397                 for ( ; op->o_callback && op->o_callback != cb.sc_next; 
398                         op->o_callback = sc_next ) {
399                         sc_next = op->o_callback->sc_next;
400                         if ( op->o_callback->sc_cleanup ) {
401                                 op->o_callback->sc_cleanup( op, rs );
402                         }
403                 }
404         }
405         op->o_bd = be;
406         op->o_callback = cb.sc_next;
407         return rc;
408 }
409
410 static int
411 over_op_bind( Operation *op, SlapReply *rs )
412 {
413         return over_op_func( op, rs, op_bind );
414 }
415
416 static int
417 over_op_unbind( Operation *op, SlapReply *rs )
418 {
419         return over_op_func( op, rs, op_unbind );
420 }
421
422 static int
423 over_op_search( Operation *op, SlapReply *rs )
424 {
425         return over_op_func( op, rs, op_search );
426 }
427
428 static int
429 over_op_compare( Operation *op, SlapReply *rs )
430 {
431         return over_op_func( op, rs, op_compare );
432 }
433
434 static int
435 over_op_modify( Operation *op, SlapReply *rs )
436 {
437         return over_op_func( op, rs, op_modify );
438 }
439
440 static int
441 over_op_modrdn( Operation *op, SlapReply *rs )
442 {
443         return over_op_func( op, rs, op_modrdn );
444 }
445
446 static int
447 over_op_add( Operation *op, SlapReply *rs )
448 {
449         return over_op_func( op, rs, op_add );
450 }
451
452 static int
453 over_op_delete( Operation *op, SlapReply *rs )
454 {
455         return over_op_func( op, rs, op_delete );
456 }
457
458 static int
459 over_op_abandon( Operation *op, SlapReply *rs )
460 {
461         return over_op_func( op, rs, op_abandon );
462 }
463
464 static int
465 over_op_cancel( Operation *op, SlapReply *rs )
466 {
467         return over_op_func( op, rs, op_cancel );
468 }
469
470 static int
471 over_op_extended( Operation *op, SlapReply *rs )
472 {
473         return over_op_func( op, rs, op_extended );
474 }
475
476 static int
477 over_aux_operational( Operation *op, SlapReply *rs )
478 {
479         return over_op_func( op, rs, op_aux_operational );
480 }
481
482 static int
483 over_aux_chk_referrals( Operation *op, SlapReply *rs )
484 {
485         return over_op_func( op, rs, op_aux_chk_referrals );
486 }
487
488 static int
489 over_aux_chk_controls( Operation *op, SlapReply *rs )
490 {
491         return over_op_func( op, rs, op_aux_chk_controls );
492 }
493
494 enum conn_which {
495         conn_init = 0,
496         conn_destroy
497 };
498
499 static int
500 over_connection_func(
501         BackendDB       *bd,
502         Connection      *conn,
503         enum conn_which which
504 )
505 {
506         slap_overinfo           *oi;
507         slap_overinst           *on;
508         BackendDB               db;
509         int                     rc = SLAP_CB_CONTINUE;
510         BI_connection_init      **func;
511
512         /* FIXME: used to happen for instance during abandon
513          * when global overlays are used... */
514         assert( bd != NULL );
515
516         oi = bd->bd_info->bi_private;
517         on = oi->oi_list;
518
519         if ( !SLAP_ISOVERLAY( bd ) ) {
520                 db = *bd;
521                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
522                 bd = &db;
523         }
524
525         for ( ; on; on = on->on_next ) {
526                 func = &on->on_bi.bi_connection_init;
527                 if ( func[ which ] ) {
528                         bd->bd_info = (BackendInfo *)on;
529                         rc = func[ which ]( bd, conn );
530                         if ( rc != SLAP_CB_CONTINUE ) break;
531                 }
532         }
533
534         func = &oi->oi_orig->bi_connection_init;
535         if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
536                 bd->bd_info = oi->oi_orig;
537                 rc = func[ which ]( bd, conn );
538         }
539         /* should not fall thru this far without anything happening... */
540         if ( rc == SLAP_CB_CONTINUE ) {
541                 rc = LDAP_UNWILLING_TO_PERFORM;
542         }
543
544         return rc;
545 }
546
547 static int
548 over_connection_init(
549         BackendDB       *bd,
550         Connection      *conn
551 )
552 {
553         return over_connection_func( bd, conn, conn_init );
554 }
555
556 static int
557 over_connection_destroy(
558         BackendDB       *bd,
559         Connection      *conn
560 )
561 {
562         return over_connection_func( bd, conn, conn_destroy );
563 }
564
565 int
566 overlay_register(
567         slap_overinst *on
568 )
569 {
570         on->on_next = overlays;
571         overlays = on;
572         return 0;
573 }
574
575 /*
576  * iterator on registered overlays; overlay_next( NULL ) returns the first
577  * overlay; * subsequent calls with the previously returned value allow to 
578  * iterate * over the entire list; returns NULL when no more overlays are 
579  * registered.
580  */
581
582 slap_overinst *
583 overlay_next(
584         slap_overinst *on
585 )
586 {
587         if ( on == NULL ) {
588                 return overlays;
589         }
590
591         return on->on_next;
592 }
593
594 /*
595  * returns a specific registered overlay based on the type; NULL if not
596  * registered.
597  */
598
599 slap_overinst *
600 overlay_find( const char *over_type )
601 {
602         slap_overinst *on = overlays;
603
604         assert( over_type );
605
606         for ( ; on; on = on->on_next ) {
607                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
608                         break;
609                 }
610         }
611
612         return on;
613 }
614
615 static const char overtype[] = "over";
616
617 /*
618  * returns TRUE (1) if the database is actually an overlay instance;
619  * FALSE (0) otherwise.
620  */
621
622 int
623 overlay_is_over( BackendDB *be )
624 {
625         return be->bd_info->bi_type == overtype;
626 }
627
628 /*
629  * returns TRUE (1) if the given database is actually an overlay
630  * instance and, somewhere in the list, contains the requested overlay;
631  * FALSE (0) otherwise.
632  */
633
634 int
635 overlay_is_inst( BackendDB *be, const char *over_type )
636 {
637         slap_overinst   *on;
638
639         assert( be );
640
641         if ( !overlay_is_over( be ) ) {
642                 return 0;
643         }
644         
645         on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
646         for ( ; on; on = on->on_next ) {
647                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
648                         return 1;
649                 }
650         }
651
652         return 0;
653 }
654
655 int
656 overlay_register_control( BackendDB *be, const char *oid )
657 {
658         int             rc = 0;
659         int             gotit = 0;
660         int             cid;
661
662         if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
663                 return -1;
664         }
665
666         if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) {
667                 BackendDB *bd;
668                 
669                 /* add to all backends... */
670                 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
671                         if ( be == bd ) {
672                                 gotit = 1;
673                         }
674
675                         bd->be_ctrls[ cid ] = 1;
676                         bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
677                 }
678
679         }
680         
681         if ( rc == 0 && !gotit ) {
682                 be->be_ctrls[ cid ] = 1;
683                 be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
684         }
685
686         return rc;
687 }
688
689 void
690 overlay_destroy_one( BackendDB *be, slap_overinst *on )
691 {
692         slap_overinfo *oi = on->on_info;
693         slap_overinst **oidx;
694
695         for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
696                 if ( *oidx == on ) {
697                         *oidx = on->on_next;
698                         if ( on->on_bi.bi_db_destroy ) {
699                                 BackendInfo *bi_orig = be->bd_info;
700                                 be->bd_info = (BackendInfo *)on;
701                                 on->on_bi.bi_db_destroy( be );
702                                 be->bd_info = bi_orig;
703                         }
704                         free( on );
705                         break;
706                 }
707         }
708 }
709
710 /* add an overlay to a particular backend. */
711 int
712 overlay_config( BackendDB *be, const char *ov )
713 {
714         slap_overinst *on = NULL, *on2 = NULL;
715         slap_overinfo *oi = NULL;
716         BackendInfo *bi = NULL;
717
718         on = overlay_find( ov );
719         if ( !on ) {
720                 Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
721                 return 1;
722         }
723
724         /* If this is the first overlay on this backend, set up the
725          * overlay info structure
726          */
727         if ( !overlay_is_over( be ) ) {
728                 oi = ch_malloc( sizeof( slap_overinfo ) );
729                 oi->oi_orig = be->bd_info;
730                 oi->oi_bi = *be->bd_info;
731
732                 /* NOTE: the first time a global overlay is configured,
733                  * frontendDB gets this flag; it is used later by overlays
734                  * to determine if they're stacked on top of the frontendDB */
735                 if ( oi->oi_orig == frontendDB->bd_info ) {
736                         SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
737                 }
738
739                 /* Save a pointer to ourself in bi_private.
740                  */
741                 oi->oi_bi.bi_private = oi;
742                 oi->oi_list = NULL;
743                 bi = (BackendInfo *)oi;
744
745                 bi->bi_type = (char *)overtype;
746
747                 bi->bi_db_config = over_db_config;
748                 bi->bi_db_open = over_db_open;
749                 bi->bi_db_close = over_db_close;
750                 bi->bi_db_destroy = over_db_destroy;
751
752                 bi->bi_op_bind = over_op_bind;
753                 bi->bi_op_unbind = over_op_unbind;
754                 bi->bi_op_search = over_op_search;
755                 bi->bi_op_compare = over_op_compare;
756                 bi->bi_op_modify = over_op_modify;
757                 bi->bi_op_modrdn = over_op_modrdn;
758                 bi->bi_op_add = over_op_add;
759                 bi->bi_op_delete = over_op_delete;
760                 bi->bi_op_abandon = over_op_abandon;
761                 bi->bi_op_cancel = over_op_cancel;
762
763                 bi->bi_extended = over_op_extended;
764
765                 /*
766                  * this is fine because it has the same
767                  * args of the operations; we need to rework
768                  * all the hooks to share the same args
769                  * of the operations...
770                  */
771                 bi->bi_operational = over_aux_operational;
772                 bi->bi_chk_referrals = over_aux_chk_referrals;
773                 bi->bi_chk_controls = over_aux_chk_controls;
774
775 #ifdef SLAP_OVERLAY_ACCESS
776                 /* this has a specific arglist */
777                 bi->bi_access_allowed = over_access_allowed;
778 #endif /* SLAP_OVERLAY_ACCESS */
779                 
780                 bi->bi_connection_init = over_connection_init;
781                 bi->bi_connection_destroy = over_connection_destroy;
782
783                 be->bd_info = bi;
784
785         } else {
786                 if ( overlay_is_inst( be, ov ) ) {
787                         Debug( LDAP_DEBUG_ANY, "overlay_config(): "
788                                         "warning, overlay \"%s\" "
789                                         "already in list\n", ov, 0, 0 );
790                 }
791
792                 oi = be->bd_info->bi_private;
793         }
794
795         /* Insert new overlay on head of list. Overlays are executed
796          * in reverse of config order...
797          */
798         on2 = ch_calloc( 1, sizeof(slap_overinst) );
799         *on2 = *on;
800         on2->on_info = oi;
801         on2->on_next = oi->oi_list;
802         oi->oi_list = on2;
803
804         /* Any initialization needed? */
805         if ( on->on_bi.bi_db_init ) {
806                 int rc;
807                 be->bd_info = (BackendInfo *)on2;
808                 rc = on2->on_bi.bi_db_init( be );
809                 be->bd_info = (BackendInfo *)oi;
810                 if ( rc ) return rc;
811         }
812
813         return 0;
814 }
815