]> git.sur5r.net Git - openldap/blob - servers/slapd/backover.c
make sure we notice if this gets out of sync with slap_operation_e
[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 /*
304  * default return code in case of missing backend function
305  * and overlay stack returning SLAP_CB_CONTINUE
306  */
307 static int op_rc[ op_last ] = {
308         LDAP_UNWILLING_TO_PERFORM,      /* bind */
309         LDAP_UNWILLING_TO_PERFORM,      /* unbind */
310         LDAP_UNWILLING_TO_PERFORM,      /* search */
311         SLAP_CB_CONTINUE,               /* compare; pass to frontend */
312         LDAP_UNWILLING_TO_PERFORM,      /* modify */
313         LDAP_UNWILLING_TO_PERFORM,      /* modrdn */
314         LDAP_UNWILLING_TO_PERFORM,      /* add */
315         LDAP_UNWILLING_TO_PERFORM,      /* delete */
316         LDAP_UNWILLING_TO_PERFORM,      /* abandon */
317         LDAP_UNWILLING_TO_PERFORM,      /* cancel */
318         LDAP_UNWILLING_TO_PERFORM,      /* extended */
319         LDAP_SUCCESS,                   /* aux_operational */
320         LDAP_SUCCESS,                   /* aux_chk_referrals */
321         SLAP_CB_CONTINUE                /* aux_chk_controls; pass to frontend */
322 };
323
324 int overlay_op_walk(
325         Operation *op,
326         SlapReply *rs,
327         slap_operation_t which,
328         slap_overinfo *oi,
329         slap_overinst *on
330 )
331 {
332         BI_op_bind **func;
333         int rc = SLAP_CB_CONTINUE;
334
335         for (; on; on=on->on_next ) {
336                 func = &on->on_bi.bi_op_bind;
337                 if ( func[which] ) {
338                         op->o_bd->bd_info = (BackendInfo *)on;
339                         rc = func[which]( op, rs );
340                         if ( rc != SLAP_CB_CONTINUE ) break;
341                 }
342         }
343
344         func = &oi->oi_orig->bi_op_bind;
345         if ( func[which] && rc == SLAP_CB_CONTINUE ) {
346                 op->o_bd->bd_info = oi->oi_orig;
347                 rc = func[which]( op, rs );
348         }
349         /* should not fall thru this far without anything happening... */
350         if ( rc == SLAP_CB_CONTINUE ) {
351                 rc = op_rc[ which ];
352         }
353
354         /* The underlying backend didn't handle the request, make sure
355          * overlay cleanup is processed.
356          */
357         if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
358                 slap_callback *sc_next;
359                 for ( ; op->o_callback && op->o_callback->sc_response !=
360                         over_back_response; op->o_callback = sc_next ) {
361                         sc_next = op->o_callback->sc_next;
362                         if ( op->o_callback->sc_cleanup ) {
363                                 op->o_callback->sc_cleanup( op, rs );
364                         }
365                 }
366         }
367         return rc;
368 }
369
370 static int
371 over_op_func(
372         Operation *op,
373         SlapReply *rs,
374         slap_operation_t which
375 )
376 {
377         slap_overinfo *oi;
378         slap_overinst *on;
379         BI_op_bind **func;
380         BackendDB *be = op->o_bd, db;
381         slap_callback cb = {NULL, over_back_response, NULL, NULL};
382         int rc = SLAP_CB_CONTINUE;
383
384         /* FIXME: used to happen for instance during abandon
385          * when global overlays are used... */
386         assert( op->o_bd != NULL );
387
388         oi = op->o_bd->bd_info->bi_private;
389         on = oi->oi_list;
390
391         if ( !SLAP_ISOVERLAY( op->o_bd )) {
392                 db = *op->o_bd;
393                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
394                 op->o_bd = &db;
395         }
396         cb.sc_next = op->o_callback;
397         cb.sc_private = oi;
398         op->o_callback = &cb;
399
400         rc = overlay_op_walk( op, rs, which, oi, on );
401
402         op->o_bd = be;
403         op->o_callback = cb.sc_next;
404         return rc;
405 }
406
407 static int
408 over_op_bind( Operation *op, SlapReply *rs )
409 {
410         return over_op_func( op, rs, op_bind );
411 }
412
413 static int
414 over_op_unbind( Operation *op, SlapReply *rs )
415 {
416         return over_op_func( op, rs, op_unbind );
417 }
418
419 static int
420 over_op_search( Operation *op, SlapReply *rs )
421 {
422         return over_op_func( op, rs, op_search );
423 }
424
425 static int
426 over_op_compare( Operation *op, SlapReply *rs )
427 {
428         return over_op_func( op, rs, op_compare );
429 }
430
431 static int
432 over_op_modify( Operation *op, SlapReply *rs )
433 {
434         return over_op_func( op, rs, op_modify );
435 }
436
437 static int
438 over_op_modrdn( Operation *op, SlapReply *rs )
439 {
440         return over_op_func( op, rs, op_modrdn );
441 }
442
443 static int
444 over_op_add( Operation *op, SlapReply *rs )
445 {
446         return over_op_func( op, rs, op_add );
447 }
448
449 static int
450 over_op_delete( Operation *op, SlapReply *rs )
451 {
452         return over_op_func( op, rs, op_delete );
453 }
454
455 static int
456 over_op_abandon( Operation *op, SlapReply *rs )
457 {
458         return over_op_func( op, rs, op_abandon );
459 }
460
461 static int
462 over_op_cancel( Operation *op, SlapReply *rs )
463 {
464         return over_op_func( op, rs, op_cancel );
465 }
466
467 static int
468 over_op_extended( Operation *op, SlapReply *rs )
469 {
470         return over_op_func( op, rs, op_extended );
471 }
472
473 static int
474 over_aux_operational( Operation *op, SlapReply *rs )
475 {
476         return over_op_func( op, rs, op_aux_operational );
477 }
478
479 static int
480 over_aux_chk_referrals( Operation *op, SlapReply *rs )
481 {
482         return over_op_func( op, rs, op_aux_chk_referrals );
483 }
484
485 static int
486 over_aux_chk_controls( Operation *op, SlapReply *rs )
487 {
488         return over_op_func( op, rs, op_aux_chk_controls );
489 }
490
491 enum conn_which {
492         conn_init = 0,
493         conn_destroy
494 };
495
496 static int
497 over_connection_func(
498         BackendDB       *bd,
499         Connection      *conn,
500         enum conn_which which
501 )
502 {
503         slap_overinfo           *oi;
504         slap_overinst           *on;
505         BackendDB               db;
506         int                     rc = SLAP_CB_CONTINUE;
507         BI_connection_init      **func;
508
509         /* FIXME: used to happen for instance during abandon
510          * when global overlays are used... */
511         assert( bd != NULL );
512
513         oi = bd->bd_info->bi_private;
514         on = oi->oi_list;
515
516         if ( !SLAP_ISOVERLAY( bd ) ) {
517                 db = *bd;
518                 db.be_flags |= SLAP_DBFLAG_OVERLAY;
519                 bd = &db;
520         }
521
522         for ( ; on; on = on->on_next ) {
523                 func = &on->on_bi.bi_connection_init;
524                 if ( func[ which ] ) {
525                         bd->bd_info = (BackendInfo *)on;
526                         rc = func[ which ]( bd, conn );
527                         if ( rc != SLAP_CB_CONTINUE ) break;
528                 }
529         }
530
531         func = &oi->oi_orig->bi_connection_init;
532         if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
533                 bd->bd_info = oi->oi_orig;
534                 rc = func[ which ]( bd, conn );
535         }
536         /* should not fall thru this far without anything happening... */
537         if ( rc == SLAP_CB_CONTINUE ) {
538                 rc = LDAP_UNWILLING_TO_PERFORM;
539         }
540
541         return rc;
542 }
543
544 static int
545 over_connection_init(
546         BackendDB       *bd,
547         Connection      *conn
548 )
549 {
550         return over_connection_func( bd, conn, conn_init );
551 }
552
553 static int
554 over_connection_destroy(
555         BackendDB       *bd,
556         Connection      *conn
557 )
558 {
559         return over_connection_func( bd, conn, conn_destroy );
560 }
561
562 int
563 overlay_register(
564         slap_overinst *on
565 )
566 {
567         on->on_next = overlays;
568         overlays = on;
569         return 0;
570 }
571
572 /*
573  * iterator on registered overlays; overlay_next( NULL ) returns the first
574  * overlay; * subsequent calls with the previously returned value allow to 
575  * iterate * over the entire list; returns NULL when no more overlays are 
576  * registered.
577  */
578
579 slap_overinst *
580 overlay_next(
581         slap_overinst *on
582 )
583 {
584         if ( on == NULL ) {
585                 return overlays;
586         }
587
588         return on->on_next;
589 }
590
591 /*
592  * returns a specific registered overlay based on the type; NULL if not
593  * registered.
594  */
595
596 slap_overinst *
597 overlay_find( const char *over_type )
598 {
599         slap_overinst *on = overlays;
600
601         assert( over_type != NULL );
602
603         for ( ; on; on = on->on_next ) {
604                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
605                         break;
606                 }
607         }
608
609         return on;
610 }
611
612 static const char overtype[] = "over";
613
614 /*
615  * returns TRUE (1) if the database is actually an overlay instance;
616  * FALSE (0) otherwise.
617  */
618
619 int
620 overlay_is_over( BackendDB *be )
621 {
622         return be->bd_info->bi_type == overtype;
623 }
624
625 /*
626  * returns TRUE (1) if the given database is actually an overlay
627  * instance and, somewhere in the list, contains the requested overlay;
628  * FALSE (0) otherwise.
629  */
630
631 int
632 overlay_is_inst( BackendDB *be, const char *over_type )
633 {
634         slap_overinst   *on;
635
636         assert( be != NULL );
637
638         if ( !overlay_is_over( be ) ) {
639                 return 0;
640         }
641         
642         on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
643         for ( ; on; on = on->on_next ) {
644                 if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
645                         return 1;
646                 }
647         }
648
649         return 0;
650 }
651
652 int
653 overlay_register_control( BackendDB *be, const char *oid )
654 {
655         int             rc = 0;
656         int             gotit = 0;
657         int             cid;
658
659         if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
660                 return -1;
661         }
662
663         if ( SLAP_DBFLAGS( be ) & SLAP_DBFLAG_GLOBAL_OVERLAY ) {
664                 BackendDB *bd;
665                 
666                 /* add to all backends... */
667                 LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
668                         if ( be == bd ) {
669                                 gotit = 1;
670                         }
671
672                         bd->be_ctrls[ cid ] = 1;
673                         bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
674                 }
675
676         }
677         
678         if ( rc == 0 && !gotit ) {
679                 be->be_ctrls[ cid ] = 1;
680                 be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
681         }
682
683         return rc;
684 }
685
686 void
687 overlay_destroy_one( BackendDB *be, slap_overinst *on )
688 {
689         slap_overinfo *oi = on->on_info;
690         slap_overinst **oidx;
691
692         for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
693                 if ( *oidx == on ) {
694                         *oidx = on->on_next;
695                         if ( on->on_bi.bi_db_destroy ) {
696                                 BackendInfo *bi_orig = be->bd_info;
697                                 be->bd_info = (BackendInfo *)on;
698                                 on->on_bi.bi_db_destroy( be );
699                                 be->bd_info = bi_orig;
700                         }
701                         free( on );
702                         break;
703                 }
704         }
705 }
706
707 /* add an overlay to a particular backend. */
708 int
709 overlay_config( BackendDB *be, const char *ov )
710 {
711         slap_overinst *on = NULL, *on2 = NULL;
712         slap_overinfo *oi = NULL;
713         BackendInfo *bi = NULL;
714
715         on = overlay_find( ov );
716         if ( !on ) {
717                 Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
718                 return 1;
719         }
720
721         /* If this is the first overlay on this backend, set up the
722          * overlay info structure
723          */
724         if ( !overlay_is_over( be ) ) {
725                 oi = ch_malloc( sizeof( slap_overinfo ) );
726                 oi->oi_orig = be->bd_info;
727                 oi->oi_bi = *be->bd_info;
728
729                 /* NOTE: the first time a global overlay is configured,
730                  * frontendDB gets this flag; it is used later by overlays
731                  * to determine if they're stacked on top of the frontendDB */
732                 if ( oi->oi_orig == frontendDB->bd_info ) {
733                         SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
734                 }
735
736                 /* Save a pointer to ourself in bi_private.
737                  */
738                 oi->oi_bi.bi_private = oi;
739                 oi->oi_list = NULL;
740                 bi = (BackendInfo *)oi;
741
742                 bi->bi_type = (char *)overtype;
743
744                 bi->bi_db_config = over_db_config;
745                 bi->bi_db_open = over_db_open;
746                 bi->bi_db_close = over_db_close;
747                 bi->bi_db_destroy = over_db_destroy;
748
749                 bi->bi_op_bind = over_op_bind;
750                 bi->bi_op_unbind = over_op_unbind;
751                 bi->bi_op_search = over_op_search;
752                 bi->bi_op_compare = over_op_compare;
753                 bi->bi_op_modify = over_op_modify;
754                 bi->bi_op_modrdn = over_op_modrdn;
755                 bi->bi_op_add = over_op_add;
756                 bi->bi_op_delete = over_op_delete;
757                 bi->bi_op_abandon = over_op_abandon;
758                 bi->bi_op_cancel = over_op_cancel;
759
760                 bi->bi_extended = over_op_extended;
761
762                 /*
763                  * this is fine because it has the same
764                  * args of the operations; we need to rework
765                  * all the hooks to share the same args
766                  * of the operations...
767                  */
768                 bi->bi_operational = over_aux_operational;
769                 bi->bi_chk_referrals = over_aux_chk_referrals;
770                 bi->bi_chk_controls = over_aux_chk_controls;
771
772 #ifdef SLAP_OVERLAY_ACCESS
773                 /* this has a specific arglist */
774                 bi->bi_access_allowed = over_access_allowed;
775 #endif /* SLAP_OVERLAY_ACCESS */
776                 
777                 bi->bi_connection_init = over_connection_init;
778                 bi->bi_connection_destroy = over_connection_destroy;
779
780                 be->bd_info = bi;
781
782         } else {
783                 if ( overlay_is_inst( be, ov ) ) {
784                         Debug( LDAP_DEBUG_ANY, "overlay_config(): "
785                                         "warning, overlay \"%s\" "
786                                         "already in list\n", ov, 0, 0 );
787                 }
788
789                 oi = be->bd_info->bi_private;
790         }
791
792         /* Insert new overlay on head of list. Overlays are executed
793          * in reverse of config order...
794          */
795         on2 = ch_calloc( 1, sizeof(slap_overinst) );
796         *on2 = *on;
797         on2->on_info = oi;
798         on2->on_next = oi->oi_list;
799         oi->oi_list = on2;
800
801         /* Any initialization needed? */
802         if ( on->on_bi.bi_db_init ) {
803                 int rc;
804                 be->bd_info = (BackendInfo *)on2;
805                 rc = on2->on_bi.bi_db_init( be );
806                 be->bd_info = (BackendInfo *)oi;
807                 if ( rc ) return rc;
808         }
809
810         return 0;
811 }
812