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