Back to index

openldap  2.4.31
backover.c
Go to the documentation of this file.
00001 /* backover.c - backend overlay routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2003-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 /* Functions to overlay other modules over a backend. */
00018 
00019 #include "portable.h"
00020 
00021 #include <stdio.h>
00022 
00023 #include <ac/string.h>
00024 #include <ac/socket.h>
00025 
00026 #define SLAPD_TOOLS
00027 #include "slap.h"
00028 #include "config.h"
00029 
00030 static slap_overinst *overlays;
00031 
00032 static int
00033 over_db_config(
00034        BackendDB *be,
00035        const char *fname,
00036        int lineno,
00037        int argc,
00038        char **argv
00039 )
00040 {
00041        slap_overinfo *oi = be->bd_info->bi_private;
00042        slap_overinst *on = oi->oi_list;
00043        BackendInfo *bi_orig = be->bd_info;
00044        struct ConfigOCs *be_cf_ocs = be->be_cf_ocs;
00045        ConfigArgs ca = {0};
00046        int rc = 0;
00047 
00048        if ( oi->oi_orig->bi_db_config ) {
00049               be->bd_info = oi->oi_orig;
00050               be->be_cf_ocs = oi->oi_orig->bi_cf_ocs;
00051               rc = oi->oi_orig->bi_db_config( be, fname, lineno,
00052                      argc, argv );
00053 
00054               if ( be->bd_info != oi->oi_orig ) {
00055                      slap_overinfo *oi2;
00056                      slap_overinst *on2, **onp;
00057                      BackendDB     be2 = *be;
00058                      int           i;
00059 
00060                      /* a database added an overlay;
00061                       * work it around... */
00062                      assert( overlay_is_over( be ) );
00063                      
00064                      oi2 = ( slap_overinfo * )be->bd_info->bi_private;
00065                      on2 = oi2->oi_list;
00066 
00067                      /* need to put a uniqueness check here as well;
00068                       * note that in principle there could be more than
00069                       * one overlay as a result of multiple calls to
00070                       * overlay_config() */
00071                      be2.bd_info = (BackendInfo *)oi;
00072 
00073                      for ( i = 0, onp = &on2; *onp; i++, onp = &(*onp)->on_next ) {
00074                             if ( overlay_is_inst( &be2, (*onp)->on_bi.bi_type ) ) {
00075                                    Debug( LDAP_DEBUG_ANY, "over_db_config(): "
00076                                                  "warning, freshly added "
00077                                                  "overlay #%d \"%s\" is already in list\n",
00078                                                  i, (*onp)->on_bi.bi_type, 0 );
00079 
00080                                    /* NOTE: if the overlay already exists,
00081                                     * there is no way to merge the results
00082                                     * of the configuration that may have 
00083                                     * occurred during bi_db_config(); we
00084                                     * just issue a warning, and the 
00085                                     * administrator should deal with this */
00086                             }
00087                      }
00088                      *onp = oi->oi_list;
00089 
00090                      oi->oi_list = on2;
00091 
00092                      ch_free( be->bd_info );
00093               }
00094 
00095               be->bd_info = (BackendInfo *)oi;
00096               if ( rc != SLAP_CONF_UNKNOWN ) return rc;
00097        }
00098 
00099        ca.argv = argv;
00100        ca.argc = argc;
00101        ca.fname = fname;
00102        ca.lineno = lineno;
00103        ca.be = be;
00104        snprintf( ca.log, sizeof( ca.log ), "%s: line %d",
00105                      ca.fname, ca.lineno );
00106        ca.op = SLAP_CONFIG_ADD;
00107        ca.valx = -1;
00108 
00109        for (; on; on=on->on_next) {
00110               rc = SLAP_CONF_UNKNOWN;
00111               if (on->on_bi.bi_cf_ocs) {
00112                      ConfigTable *ct;
00113                      ca.bi = &on->on_bi;
00114                      ct = config_find_keyword( on->on_bi.bi_cf_ocs->co_table, &ca );
00115                      if ( ct ) {
00116                             ca.table = on->on_bi.bi_cf_ocs->co_type;
00117                             rc = config_add_vals( ct, &ca );
00118                             if ( rc != SLAP_CONF_UNKNOWN )
00119                                    break;
00120                      }
00121               }
00122               if (on->on_bi.bi_db_config && rc == SLAP_CONF_UNKNOWN) {
00123                      be->bd_info = &on->on_bi;
00124                      rc = on->on_bi.bi_db_config( be, fname, lineno,
00125                             argc, argv );
00126                      if ( rc != SLAP_CONF_UNKNOWN ) break;
00127               }
00128        }
00129        be->bd_info = bi_orig;
00130        be->be_cf_ocs = be_cf_ocs;
00131        
00132        return rc;
00133 }
00134 
00135 static int
00136 over_db_open(
00137        BackendDB *be,
00138        ConfigReply *cr
00139 )
00140 {
00141        slap_overinfo *oi = be->bd_info->bi_private;
00142        slap_overinst *on = oi->oi_list;
00143        BackendDB db = *be;
00144        int rc = 0;
00145 
00146        db.be_flags |= SLAP_DBFLAG_OVERLAY;
00147        db.bd_info = oi->oi_orig;
00148        if ( db.bd_info->bi_db_open ) {
00149               rc = db.bd_info->bi_db_open( &db, cr );
00150        }
00151 
00152        for (; on && rc == 0; on=on->on_next) {
00153               db.bd_info = &on->on_bi;
00154               if ( db.bd_info->bi_db_open ) {
00155                      rc = db.bd_info->bi_db_open( &db, cr );
00156               }
00157        }
00158 
00159        return rc;
00160 }
00161 
00162 static int
00163 over_db_close(
00164        BackendDB *be,
00165        ConfigReply *cr
00166 )
00167 {
00168        slap_overinfo *oi = be->bd_info->bi_private;
00169        slap_overinst *on = oi->oi_list;
00170        BackendInfo *bi_orig = be->bd_info;
00171        int rc = 0;
00172 
00173        for (; on && rc == 0; on=on->on_next) {
00174               be->bd_info = &on->on_bi;
00175               if ( be->bd_info->bi_db_close ) {
00176                      rc = be->bd_info->bi_db_close( be, cr );
00177               }
00178        }
00179 
00180        if ( oi->oi_orig->bi_db_close ) {
00181               be->bd_info = oi->oi_orig;
00182               rc = be->bd_info->bi_db_close( be, cr );
00183        }
00184 
00185        be->bd_info = bi_orig;
00186        return rc;
00187 }
00188 
00189 static int
00190 over_db_destroy(
00191        BackendDB *be,
00192        ConfigReply *cr
00193 )
00194 {
00195        slap_overinfo *oi = be->bd_info->bi_private;
00196        slap_overinst *on = oi->oi_list, *next;
00197        BackendInfo *bi_orig = be->bd_info;
00198        int rc = 0;
00199 
00200        be->bd_info = oi->oi_orig;
00201        if ( be->bd_info->bi_db_destroy ) {
00202               rc = be->bd_info->bi_db_destroy( be, cr );
00203        }
00204 
00205        for (; on && rc == 0; on=on->on_next) {
00206               be->bd_info = &on->on_bi;
00207               if ( be->bd_info->bi_db_destroy ) {
00208                      rc = be->bd_info->bi_db_destroy( be, cr );
00209               }
00210        }
00211 
00212        on = oi->oi_list;
00213        if ( on ) {
00214               for (next = on->on_next; on; on=next) {
00215                      next = on->on_next;
00216                      free( on );
00217               }
00218        }
00219        be->bd_info = bi_orig;
00220        free( oi );
00221        return rc;
00222 }
00223 
00224 static int
00225 over_back_response ( Operation *op, SlapReply *rs )
00226 {
00227        slap_overinfo *oi = op->o_callback->sc_private;
00228        slap_overinst *on = oi->oi_list;
00229        int rc = SLAP_CB_CONTINUE;
00230        BackendDB *be = op->o_bd, db = *op->o_bd;
00231 
00232        db.be_flags |= SLAP_DBFLAG_OVERLAY;
00233        op->o_bd = &db;
00234        for (; on; on=on->on_next ) {
00235               if ( on->on_response ) {
00236                      db.bd_info = (BackendInfo *)on;
00237                      rc = on->on_response( op, rs );
00238                      if ( rc != SLAP_CB_CONTINUE ) break;
00239               }
00240        }
00241        /* Bypass the remaining on_response layers, but allow
00242         * normal execution to continue.
00243         */
00244        if ( rc == SLAP_CB_BYPASS )
00245               rc = SLAP_CB_CONTINUE;
00246        op->o_bd = be;
00247        return rc;
00248 }
00249 
00250 static int
00251 over_access_allowed(
00252        Operation            *op,
00253        Entry                *e,
00254        AttributeDescription *desc,
00255        struct berval        *val,
00256        slap_access_t        access,
00257        AccessControlState   *state,
00258        slap_mask_t          *maskp )
00259 {
00260        slap_overinfo *oi;
00261        slap_overinst *on;
00262        BackendInfo *bi;
00263        BackendDB *be = op->o_bd, db;
00264        int rc = SLAP_CB_CONTINUE;
00265 
00266        /* FIXME: used to happen for instance during abandon
00267         * when global overlays are used... */
00268        assert( op->o_bd != NULL );
00269 
00270        bi = op->o_bd->bd_info;
00271        /* Were we invoked on the frontend? */
00272        if ( !bi->bi_access_allowed ) {
00273               oi = frontendDB->bd_info->bi_private;
00274        } else {
00275               oi = op->o_bd->bd_info->bi_private;
00276        }
00277        on = oi->oi_list;
00278 
00279        for ( ; on; on = on->on_next ) {
00280               if ( on->on_bi.bi_access_allowed ) {
00281                      /* NOTE: do not copy the structure until required */
00282                      if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
00283                             db = *op->o_bd;
00284                             db.be_flags |= SLAP_DBFLAG_OVERLAY;
00285                             op->o_bd = &db;
00286                      }
00287 
00288                      op->o_bd->bd_info = (BackendInfo *)on;
00289                      rc = on->on_bi.bi_access_allowed( op, e,
00290                             desc, val, access, state, maskp );
00291                      if ( rc != SLAP_CB_CONTINUE ) break;
00292               }
00293        }
00294 
00295        if ( rc == SLAP_CB_CONTINUE ) {
00296               BI_access_allowed    *bi_access_allowed;
00297 
00298               /* if the database structure was changed, o_bd points to a
00299                * copy of the structure; put the original bd_info in place */
00300               if ( SLAP_ISOVERLAY( op->o_bd ) ) {
00301                      op->o_bd->bd_info = oi->oi_orig;
00302               }
00303 
00304               if ( oi->oi_orig->bi_access_allowed ) {
00305                      bi_access_allowed = oi->oi_orig->bi_access_allowed;
00306               } else {
00307                      bi_access_allowed = slap_access_allowed;
00308               }
00309 
00310               rc = bi_access_allowed( op, e,
00311                      desc, val, access, state, maskp );
00312        }
00313        /* should not fall thru this far without anything happening... */
00314        if ( rc == SLAP_CB_CONTINUE ) {
00315               /* access not allowed */
00316               rc = 0;
00317        }
00318 
00319        op->o_bd = be;
00320        op->o_bd->bd_info = bi;
00321 
00322        return rc;
00323 }
00324 
00325 int
00326 overlay_entry_get_ov(
00327        Operation            *op,
00328        struct berval *dn,
00329        ObjectClass          *oc,
00330        AttributeDescription *ad,
00331        int    rw,
00332        Entry  **e,
00333        slap_overinst *on )
00334 {
00335        slap_overinfo *oi = on->on_info;
00336        BackendDB *be = op->o_bd, db;
00337        BackendInfo *bi = op->o_bd->bd_info;
00338        int rc = SLAP_CB_CONTINUE;
00339 
00340        for ( ; on; on = on->on_next ) {
00341               if ( on->on_bi.bi_entry_get_rw ) {
00342                      /* NOTE: do not copy the structure until required */
00343                      if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
00344                             db = *op->o_bd;
00345                             db.be_flags |= SLAP_DBFLAG_OVERLAY;
00346                             op->o_bd = &db;
00347                      }
00348 
00349                      op->o_bd->bd_info = (BackendInfo *)on;
00350                      rc = on->on_bi.bi_entry_get_rw( op, dn,
00351                             oc, ad, rw, e );
00352                      if ( rc != SLAP_CB_CONTINUE ) break;
00353               }
00354        }
00355 
00356        if ( rc == SLAP_CB_CONTINUE ) {
00357               /* if the database structure was changed, o_bd points to a
00358                * copy of the structure; put the original bd_info in place */
00359               if ( SLAP_ISOVERLAY( op->o_bd ) ) {
00360                      op->o_bd->bd_info = oi->oi_orig;
00361               }
00362 
00363               if ( oi->oi_orig->bi_entry_get_rw ) {
00364                      rc = oi->oi_orig->bi_entry_get_rw( op, dn,
00365                             oc, ad, rw, e );
00366               }
00367        }
00368        /* should not fall thru this far without anything happening... */
00369        if ( rc == SLAP_CB_CONTINUE ) {
00370               rc = LDAP_UNWILLING_TO_PERFORM;
00371        }
00372 
00373        op->o_bd = be;
00374        op->o_bd->bd_info = bi;
00375 
00376        return rc;
00377 }
00378 
00379 static int
00380 over_entry_get_rw(
00381        Operation            *op,
00382        struct berval *dn,
00383        ObjectClass          *oc,
00384        AttributeDescription *ad,
00385        int    rw,
00386        Entry  **e )
00387 {
00388        slap_overinfo *oi;
00389        slap_overinst *on;
00390 
00391        assert( op->o_bd != NULL );
00392 
00393        oi = op->o_bd->bd_info->bi_private;
00394        on = oi->oi_list;
00395 
00396        return overlay_entry_get_ov( op, dn, oc, ad, rw, e, on );
00397 }
00398 
00399 int
00400 overlay_entry_release_ov(
00401        Operation     *op,
00402        Entry  *e,
00403        int rw,
00404        slap_overinst *on )
00405 {
00406        slap_overinfo *oi = on->on_info;
00407        BackendDB *be = op->o_bd, db;
00408        BackendInfo *bi = op->o_bd->bd_info;
00409        int rc = SLAP_CB_CONTINUE;
00410 
00411        for ( ; on; on = on->on_next ) {
00412               if ( on->on_bi.bi_entry_release_rw ) {
00413                      /* NOTE: do not copy the structure until required */
00414                      if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
00415                             db = *op->o_bd;
00416                             db.be_flags |= SLAP_DBFLAG_OVERLAY;
00417                             op->o_bd = &db;
00418                      }
00419 
00420                      op->o_bd->bd_info = (BackendInfo *)on;
00421                      rc = on->on_bi.bi_entry_release_rw( op, e, rw );
00422                      if ( rc != SLAP_CB_CONTINUE ) break;
00423               }
00424        }
00425 
00426        if ( rc == SLAP_CB_CONTINUE ) {
00427               /* if the database structure was changed, o_bd points to a
00428                * copy of the structure; put the original bd_info in place */
00429               if ( SLAP_ISOVERLAY( op->o_bd ) ) {
00430                      op->o_bd->bd_info = oi->oi_orig;
00431               }
00432 
00433               if ( oi->oi_orig->bi_entry_release_rw ) {
00434                      rc = oi->oi_orig->bi_entry_release_rw( op, e, rw );
00435               }
00436        }
00437        /* should not fall thru this far without anything happening... */
00438        if ( rc == SLAP_CB_CONTINUE ) {
00439               entry_free( e );
00440               rc = 0;
00441        }
00442 
00443        op->o_bd = be;
00444        op->o_bd->bd_info = bi;
00445 
00446        return rc;
00447 }
00448 
00449 static int
00450 over_entry_release_rw(
00451        Operation     *op,
00452        Entry  *e,
00453        int rw )
00454 {
00455        slap_overinfo *oi;
00456        slap_overinst *on;
00457 
00458        assert( op->o_bd != NULL );
00459 
00460        oi = op->o_bd->bd_info->bi_private;
00461        on = oi->oi_list;
00462 
00463        return overlay_entry_release_ov( op, e, rw, on );
00464 }
00465 
00466 static int
00467 over_acl_group(
00468        Operation            *op,
00469        Entry                *e,
00470        struct berval        *gr_ndn,
00471        struct berval        *op_ndn,
00472        ObjectClass          *group_oc,
00473        AttributeDescription *group_at )
00474 {
00475        slap_overinfo *oi;
00476        slap_overinst *on;
00477        BackendInfo *bi;
00478        BackendDB *be = op->o_bd, db;
00479        int rc = SLAP_CB_CONTINUE;
00480 
00481        /* FIXME: used to happen for instance during abandon
00482         * when global overlays are used... */
00483        assert( be != NULL );
00484 
00485        bi = be->bd_info;
00486        oi = bi->bi_private;
00487        on = oi->oi_list;
00488 
00489        for ( ; on; on = on->on_next ) {
00490               if ( on->on_bi.bi_acl_group ) {
00491                      /* NOTE: do not copy the structure until required */
00492                      if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
00493                             db = *op->o_bd;
00494                             db.be_flags |= SLAP_DBFLAG_OVERLAY;
00495                             op->o_bd = &db;
00496                      }
00497 
00498                      op->o_bd->bd_info = (BackendInfo *)on;
00499                      rc = on->on_bi.bi_acl_group( op, e,
00500                             gr_ndn, op_ndn, group_oc, group_at );
00501                      if ( rc != SLAP_CB_CONTINUE ) break;
00502               }
00503        }
00504 
00505        if ( rc == SLAP_CB_CONTINUE ) {
00506               BI_acl_group         *bi_acl_group;
00507 
00508               /* if the database structure was changed, o_bd points to a
00509                * copy of the structure; put the original bd_info in place */
00510               if ( SLAP_ISOVERLAY( op->o_bd ) ) {
00511                      op->o_bd->bd_info = oi->oi_orig;
00512               }
00513 
00514               if ( oi->oi_orig->bi_acl_group ) {
00515                      bi_acl_group = oi->oi_orig->bi_acl_group;
00516               } else {
00517                      bi_acl_group = backend_group;
00518               }
00519 
00520               rc = bi_acl_group( op, e,
00521                      gr_ndn, op_ndn, group_oc, group_at );
00522        }
00523        /* should not fall thru this far without anything happening... */
00524        if ( rc == SLAP_CB_CONTINUE ) {
00525               /* access not allowed */
00526               rc = 0;
00527        }
00528 
00529        op->o_bd = be;
00530        op->o_bd->bd_info = bi;
00531 
00532        return rc;
00533 }
00534 
00535 static int
00536 over_acl_attribute(
00537        Operation            *op,
00538        Entry                *target,
00539        struct berval        *entry_ndn,
00540        AttributeDescription *entry_at,
00541        BerVarray            *vals,
00542        slap_access_t        access )
00543 {
00544        slap_overinfo *oi;
00545        slap_overinst *on;
00546        BackendInfo *bi;
00547        BackendDB *be = op->o_bd, db;
00548        int rc = SLAP_CB_CONTINUE;
00549 
00550        /* FIXME: used to happen for instance during abandon
00551         * when global overlays are used... */
00552        assert( be != NULL );
00553 
00554        bi = be->bd_info;
00555        oi = bi->bi_private;
00556        on = oi->oi_list;
00557 
00558        for ( ; on; on = on->on_next ) {
00559               if ( on->on_bi.bi_acl_attribute ) {
00560                      /* NOTE: do not copy the structure until required */
00561                      if ( !SLAP_ISOVERLAY( op->o_bd ) ) {
00562                             db = *op->o_bd;
00563                             db.be_flags |= SLAP_DBFLAG_OVERLAY;
00564                             op->o_bd = &db;
00565                      }
00566 
00567                      op->o_bd->bd_info = (BackendInfo *)on;
00568                      rc = on->on_bi.bi_acl_attribute( op, target,
00569                             entry_ndn, entry_at, vals, access );
00570                      if ( rc != SLAP_CB_CONTINUE ) break;
00571               }
00572        }
00573 
00574        if ( rc == SLAP_CB_CONTINUE ) {
00575               BI_acl_attribute            *bi_acl_attribute;
00576 
00577               /* if the database structure was changed, o_bd points to a
00578                * copy of the structure; put the original bd_info in place */
00579               if ( SLAP_ISOVERLAY( op->o_bd ) ) {
00580                      op->o_bd->bd_info = oi->oi_orig;
00581               }
00582 
00583               if ( oi->oi_orig->bi_acl_attribute ) {
00584                      bi_acl_attribute = oi->oi_orig->bi_acl_attribute;
00585               } else {
00586                      bi_acl_attribute = backend_attribute;
00587               }
00588 
00589               rc = bi_acl_attribute( op, target,
00590                      entry_ndn, entry_at, vals, access );
00591        }
00592        /* should not fall thru this far without anything happening... */
00593        if ( rc == SLAP_CB_CONTINUE ) {
00594               /* access not allowed */
00595               rc = 0;
00596        }
00597 
00598        op->o_bd = be;
00599        op->o_bd->bd_info = bi;
00600 
00601        return rc;
00602 }
00603 
00604 int
00605 overlay_callback_after_backover( Operation *op, slap_callback *sc, int append )
00606 {
00607        slap_callback **scp;
00608 
00609        for ( scp = &op->o_callback; *scp != NULL; scp = &(*scp)->sc_next ) {
00610               if ( (*scp)->sc_response == over_back_response ) {
00611                      sc->sc_next = (*scp)->sc_next;
00612                      (*scp)->sc_next = sc;
00613                      return 0;
00614               }
00615        }
00616 
00617        if ( append ) {
00618               *scp = sc;
00619               return 0;
00620        }
00621 
00622        return 1;
00623 }
00624 
00625 /*
00626  * default return code in case of missing backend function
00627  * and overlay stack returning SLAP_CB_CONTINUE
00628  */
00629 static int op_rc[ op_last ] = {
00630        LDAP_UNWILLING_TO_PERFORM,  /* bind */
00631        LDAP_UNWILLING_TO_PERFORM,  /* unbind */
00632        LDAP_UNWILLING_TO_PERFORM,  /* search */
00633        SLAP_CB_CONTINUE,           /* compare; pass to frontend */
00634        LDAP_UNWILLING_TO_PERFORM,  /* modify */
00635        LDAP_UNWILLING_TO_PERFORM,  /* modrdn */
00636        LDAP_UNWILLING_TO_PERFORM,  /* add */
00637        LDAP_UNWILLING_TO_PERFORM,  /* delete */
00638        LDAP_UNWILLING_TO_PERFORM,  /* abandon */
00639        LDAP_UNWILLING_TO_PERFORM,  /* cancel */
00640        LDAP_UNWILLING_TO_PERFORM,  /* extended */
00641        LDAP_SUCCESS,               /* aux_operational */
00642        LDAP_SUCCESS,               /* aux_chk_referrals */
00643        SLAP_CB_CONTINUE            /* aux_chk_controls; pass to frontend */
00644 };
00645 
00646 int overlay_op_walk(
00647        Operation *op,
00648        SlapReply *rs,
00649        slap_operation_t which,
00650        slap_overinfo *oi,
00651        slap_overinst *on
00652 )
00653 {
00654        BI_op_bind **func;
00655        int rc = SLAP_CB_CONTINUE;
00656 
00657        for (; on; on=on->on_next ) {
00658               func = &on->on_bi.bi_op_bind;
00659               if ( func[which] ) {
00660                      op->o_bd->bd_info = (BackendInfo *)on;
00661                      rc = func[which]( op, rs );
00662                      if ( rc != SLAP_CB_CONTINUE ) break;
00663               }
00664        }
00665        if ( rc == SLAP_CB_BYPASS )
00666               rc = SLAP_CB_CONTINUE;
00667 
00668        func = &oi->oi_orig->bi_op_bind;
00669        if ( func[which] && rc == SLAP_CB_CONTINUE ) {
00670               op->o_bd->bd_info = oi->oi_orig;
00671               rc = func[which]( op, rs );
00672        }
00673        /* should not fall thru this far without anything happening... */
00674        if ( rc == SLAP_CB_CONTINUE ) {
00675               rc = op_rc[ which ];
00676        }
00677 
00678        /* The underlying backend didn't handle the request, make sure
00679         * overlay cleanup is processed.
00680         */
00681        if ( rc == LDAP_UNWILLING_TO_PERFORM ) {
00682               slap_callback *sc_next;
00683               for ( ; op->o_callback && op->o_callback->sc_response !=
00684                      over_back_response; op->o_callback = sc_next ) {
00685                      sc_next = op->o_callback->sc_next;
00686                      if ( op->o_callback->sc_cleanup ) {
00687                             op->o_callback->sc_cleanup( op, rs );
00688                      }
00689               }
00690        }
00691        return rc;
00692 }
00693 
00694 static int
00695 over_op_func(
00696        Operation *op,
00697        SlapReply *rs,
00698        slap_operation_t which
00699 )
00700 {
00701        slap_overinfo *oi;
00702        slap_overinst *on;
00703        BackendDB *be = op->o_bd, db;
00704        slap_callback cb = {NULL, over_back_response, NULL, NULL}, **sc;
00705        int rc = SLAP_CB_CONTINUE;
00706 
00707        /* FIXME: used to happen for instance during abandon
00708         * when global overlays are used... */
00709        assert( op->o_bd != NULL );
00710 
00711        oi = op->o_bd->bd_info->bi_private;
00712        on = oi->oi_list;
00713 
00714        if ( !SLAP_ISOVERLAY( op->o_bd )) {
00715               db = *op->o_bd;
00716               db.be_flags |= SLAP_DBFLAG_OVERLAY;
00717               op->o_bd = &db;
00718        }
00719        cb.sc_next = op->o_callback;
00720        cb.sc_private = oi;
00721        op->o_callback = &cb;
00722 
00723        rc = overlay_op_walk( op, rs, which, oi, on );
00724        for ( sc = &op->o_callback; *sc; sc = &(*sc)->sc_next ) {
00725               if ( *sc == &cb ) {
00726                      *sc = cb.sc_next;
00727                      break;
00728               }
00729        }
00730 
00731        op->o_bd = be;
00732        return rc;
00733 }
00734 
00735 static int
00736 over_op_bind( Operation *op, SlapReply *rs )
00737 {
00738        return over_op_func( op, rs, op_bind );
00739 }
00740 
00741 static int
00742 over_op_unbind( Operation *op, SlapReply *rs )
00743 {
00744        return over_op_func( op, rs, op_unbind );
00745 }
00746 
00747 static int
00748 over_op_search( Operation *op, SlapReply *rs )
00749 {
00750        return over_op_func( op, rs, op_search );
00751 }
00752 
00753 static int
00754 over_op_compare( Operation *op, SlapReply *rs )
00755 {
00756        return over_op_func( op, rs, op_compare );
00757 }
00758 
00759 static int
00760 over_op_modify( Operation *op, SlapReply *rs )
00761 {
00762        return over_op_func( op, rs, op_modify );
00763 }
00764 
00765 static int
00766 over_op_modrdn( Operation *op, SlapReply *rs )
00767 {
00768        return over_op_func( op, rs, op_modrdn );
00769 }
00770 
00771 static int
00772 over_op_add( Operation *op, SlapReply *rs )
00773 {
00774        return over_op_func( op, rs, op_add );
00775 }
00776 
00777 static int
00778 over_op_delete( Operation *op, SlapReply *rs )
00779 {
00780        return over_op_func( op, rs, op_delete );
00781 }
00782 
00783 static int
00784 over_op_abandon( Operation *op, SlapReply *rs )
00785 {
00786        return over_op_func( op, rs, op_abandon );
00787 }
00788 
00789 static int
00790 over_op_cancel( Operation *op, SlapReply *rs )
00791 {
00792        return over_op_func( op, rs, op_cancel );
00793 }
00794 
00795 static int
00796 over_op_extended( Operation *op, SlapReply *rs )
00797 {
00798        return over_op_func( op, rs, op_extended );
00799 }
00800 
00801 static int
00802 over_aux_operational( Operation *op, SlapReply *rs )
00803 {
00804        return over_op_func( op, rs, op_aux_operational );
00805 }
00806 
00807 static int
00808 over_aux_chk_referrals( Operation *op, SlapReply *rs )
00809 {
00810        return over_op_func( op, rs, op_aux_chk_referrals );
00811 }
00812 
00813 static int
00814 over_aux_chk_controls( Operation *op, SlapReply *rs )
00815 {
00816        return over_op_func( op, rs, op_aux_chk_controls );
00817 }
00818 
00819 enum conn_which {
00820        conn_init = 0,
00821        conn_destroy,
00822        conn_last
00823 };
00824 
00825 static int
00826 over_connection_func(
00827        BackendDB     *bd,
00828        Connection    *conn,
00829        enum conn_which      which
00830 )
00831 {
00832        slap_overinfo        *oi;
00833        slap_overinst        *on;
00834        BackendDB            db;
00835        int                  rc = SLAP_CB_CONTINUE;
00836        BI_connection_init   **func;
00837 
00838        /* FIXME: used to happen for instance during abandon
00839         * when global overlays are used... */
00840        assert( bd != NULL );
00841 
00842        oi = bd->bd_info->bi_private;
00843        on = oi->oi_list;
00844 
00845        if ( !SLAP_ISOVERLAY( bd ) ) {
00846               db = *bd;
00847               db.be_flags |= SLAP_DBFLAG_OVERLAY;
00848               bd = &db;
00849        }
00850 
00851        for ( ; on; on = on->on_next ) {
00852               func = &on->on_bi.bi_connection_init;
00853               if ( func[ which ] ) {
00854                      bd->bd_info = (BackendInfo *)on;
00855                      rc = func[ which ]( bd, conn );
00856                      if ( rc != SLAP_CB_CONTINUE ) break;
00857               }
00858        }
00859 
00860        func = &oi->oi_orig->bi_connection_init;
00861        if ( func[ which ] && rc == SLAP_CB_CONTINUE ) {
00862               bd->bd_info = oi->oi_orig;
00863               rc = func[ which ]( bd, conn );
00864        }
00865        /* should not fall thru this far without anything happening... */
00866        if ( rc == SLAP_CB_CONTINUE ) {
00867               rc = LDAP_UNWILLING_TO_PERFORM;
00868        }
00869 
00870        return rc;
00871 }
00872 
00873 static int
00874 over_connection_init(
00875        BackendDB     *bd,
00876        Connection    *conn
00877 )
00878 {
00879        return over_connection_func( bd, conn, conn_init );
00880 }
00881 
00882 static int
00883 over_connection_destroy(
00884        BackendDB     *bd,
00885        Connection    *conn
00886 )
00887 {
00888        return over_connection_func( bd, conn, conn_destroy );
00889 }
00890 
00891 int
00892 overlay_register(
00893        slap_overinst *on
00894 )
00895 {
00896        slap_overinst *tmp;
00897 
00898        /* FIXME: check for duplicates? */
00899        for ( tmp = overlays; tmp != NULL; tmp = tmp->on_next ) {
00900               if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_type ) == 0 ) {
00901                      Debug( LDAP_DEBUG_ANY,
00902                             "overlay_register(\"%s\"): "
00903                             "name already in use.\n",
00904                             on->on_bi.bi_type, 0, 0 );
00905                      return -1;
00906               }
00907 
00908               if ( on->on_bi.bi_obsolete_names != NULL ) {
00909                      int    i;
00910 
00911                      for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
00912                             if ( strcmp( on->on_bi.bi_obsolete_names[ i ], tmp->on_bi.bi_type ) == 0 ) {
00913                                    Debug( LDAP_DEBUG_ANY,
00914                                           "overlay_register(\"%s\"): "
00915                                           "obsolete name \"%s\" already in use "
00916                                           "by overlay \"%s\".\n",
00917                                           on->on_bi.bi_type,
00918                                           on->on_bi.bi_obsolete_names[ i ],
00919                                           tmp->on_bi.bi_type );
00920                                    return -1;
00921                             }
00922                      }
00923               }
00924 
00925               if ( tmp->on_bi.bi_obsolete_names != NULL ) {
00926                      int    i;
00927 
00928                      for ( i = 0; tmp->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
00929                             int    j;
00930 
00931                             if ( strcmp( on->on_bi.bi_type, tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
00932                                    Debug( LDAP_DEBUG_ANY,
00933                                           "overlay_register(\"%s\"): "
00934                                           "name already in use "
00935                                           "as obsolete by overlay \"%s\".\n",
00936                                           on->on_bi.bi_type,
00937                                           tmp->on_bi.bi_obsolete_names[ i ], 0 );
00938                                    return -1;
00939                             }
00940 
00941                             if ( on->on_bi.bi_obsolete_names != NULL ) {
00942                                    for ( j = 0; on->on_bi.bi_obsolete_names[ j ] != NULL; j++ ) {
00943                                           if ( strcmp( on->on_bi.bi_obsolete_names[ j ], tmp->on_bi.bi_obsolete_names[ i ] ) == 0 ) {
00944                                                  Debug( LDAP_DEBUG_ANY,
00945                                                         "overlay_register(\"%s\"): "
00946                                                         "obsolete name \"%s\" already in use "
00947                                                         "as obsolete by overlay \"%s\".\n",
00948                                                         on->on_bi.bi_type,
00949                                                         on->on_bi.bi_obsolete_names[ j ],
00950                                                         tmp->on_bi.bi_type );
00951                                                  return -1;
00952                                           }
00953                                    }
00954                             }
00955                      }
00956               }
00957        }
00958 
00959        on->on_next = overlays;
00960        overlays = on;
00961        return 0;
00962 }
00963 
00964 /*
00965  * iterator on registered overlays; overlay_next( NULL ) returns the first
00966  * overlay; subsequent calls with the previously returned value allow to 
00967  * iterate over the entire list; returns NULL when no more overlays are 
00968  * registered.
00969  */
00970 
00971 slap_overinst *
00972 overlay_next(
00973        slap_overinst *on
00974 )
00975 {
00976        if ( on == NULL ) {
00977               return overlays;
00978        }
00979 
00980        return on->on_next;
00981 }
00982 
00983 /*
00984  * returns a specific registered overlay based on the type; NULL if not
00985  * registered.
00986  */
00987 
00988 slap_overinst *
00989 overlay_find( const char *over_type )
00990 {
00991        slap_overinst *on = overlays;
00992 
00993        assert( over_type != NULL );
00994 
00995        for ( ; on; on = on->on_next ) {
00996               if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
00997                      goto foundit;
00998               }
00999 
01000               if ( on->on_bi.bi_obsolete_names != NULL ) {
01001                      int    i;
01002 
01003                      for ( i = 0; on->on_bi.bi_obsolete_names[ i ] != NULL; i++ ) {
01004                             if ( strcmp( on->on_bi.bi_obsolete_names[ i ], over_type ) == 0 ) {
01005                                    Debug( LDAP_DEBUG_ANY,
01006                                           "overlay_find(\"%s\"): "
01007                                           "obsolete name for \"%s\".\n",
01008                                           on->on_bi.bi_obsolete_names[ i ],
01009                                           on->on_bi.bi_type, 0 );
01010                                    goto foundit;
01011                             }
01012                      }
01013               }
01014        }
01015 
01016 foundit:;
01017        return on;
01018 }
01019 
01020 static const char overtype[] = "over";
01021 
01022 /*
01023  * returns TRUE (1) if the database is actually an overlay instance;
01024  * FALSE (0) otherwise.
01025  */
01026 
01027 int
01028 overlay_is_over( BackendDB *be )
01029 {
01030        return be->bd_info->bi_type == overtype;
01031 }
01032 
01033 /*
01034  * returns TRUE (1) if the given database is actually an overlay
01035  * instance and, somewhere in the list, contains the requested overlay;
01036  * FALSE (0) otherwise.
01037  */
01038 
01039 int
01040 overlay_is_inst( BackendDB *be, const char *over_type )
01041 {
01042        slap_overinst *on;
01043 
01044        assert( be != NULL );
01045 
01046        if ( !overlay_is_over( be ) ) {
01047               return 0;
01048        }
01049        
01050        on = ((slap_overinfo *)be->bd_info->bi_private)->oi_list;
01051        for ( ; on; on = on->on_next ) {
01052               if ( strcmp( on->on_bi.bi_type, over_type ) == 0 ) {
01053                      return 1;
01054               }
01055        }
01056 
01057        return 0;
01058 }
01059 
01060 int
01061 overlay_register_control( BackendDB *be, const char *oid )
01062 {
01063        int           gotit = 0;
01064        int           cid;
01065 
01066        if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
01067               return -1;
01068        }
01069 
01070        if ( SLAP_ISGLOBALOVERLAY( be ) ) {
01071               BackendDB *bd;
01072               
01073               /* add to all backends... */
01074               LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
01075                      if ( bd == be->bd_self ) {
01076                             gotit = 1;
01077                      }
01078 
01079                      /* overlays can be instanciated multiple times, use
01080                       * be_ctrls[ cid ] as an instance counter, so that the
01081                       * overlay's controls are only really disabled after the
01082                       * last instance called overlay_register_control() */
01083                      bd->be_ctrls[ cid ]++;
01084                      bd->be_ctrls[ SLAP_MAX_CIDS ] = 1;
01085               }
01086 
01087        }
01088        
01089        if ( !gotit ) {
01090               /* overlays can be instanciated multiple times, use
01091                * be_ctrls[ cid ] as an instance counter, so that the
01092                * overlay's controls are only really unregistered after the
01093                * last instance called overlay_register_control() */
01094               be->bd_self->be_ctrls[ cid ]++;
01095               be->bd_self->be_ctrls[ SLAP_MAX_CIDS ] = 1;
01096        }
01097 
01098        return 0;
01099 }
01100 
01101 #ifdef SLAP_CONFIG_DELETE
01102 void
01103 overlay_unregister_control( BackendDB *be, const char *oid )
01104 {
01105        int           gotit = 0;
01106        int           cid;
01107 
01108        if ( slap_find_control_id( oid, &cid ) == LDAP_CONTROL_NOT_FOUND ) {
01109               return;
01110        }
01111 
01112        if ( SLAP_ISGLOBALOVERLAY( be ) ) {
01113               BackendDB *bd;
01114 
01115               /* remove from all backends... */
01116               LDAP_STAILQ_FOREACH( bd, &backendDB, be_next ) {
01117                      if ( bd == be->bd_self ) {
01118                             gotit = 1;
01119                      }
01120 
01121                      bd->be_ctrls[ cid ]--;
01122               }
01123        }
01124 
01125        if ( !gotit ) {
01126               be->bd_self->be_ctrls[ cid ]--;
01127        }
01128 }
01129 #endif /* SLAP_CONFIG_DELETE */
01130 
01131 void
01132 overlay_destroy_one( BackendDB *be, slap_overinst *on )
01133 {
01134        slap_overinfo *oi = on->on_info;
01135        slap_overinst **oidx;
01136 
01137        for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
01138               if ( *oidx == on ) {
01139                      *oidx = on->on_next;
01140                      if ( on->on_bi.bi_db_destroy ) {
01141                             BackendInfo *bi_orig = be->bd_info;
01142                             be->bd_info = (BackendInfo *)on;
01143                             on->on_bi.bi_db_destroy( be, NULL );
01144                             be->bd_info = bi_orig;
01145                      }
01146                      free( on );
01147                      break;
01148               }
01149        }
01150 }
01151 
01152 #ifdef SLAP_CONFIG_DELETE
01153 typedef struct ov_remove_ctx {
01154        BackendDB *be;
01155        slap_overinst *on;
01156 } ov_remove_ctx;
01157 
01158 int
01159 overlay_remove_cb( Operation *op, SlapReply *rs )
01160 {
01161        ov_remove_ctx *rm_ctx = (ov_remove_ctx*) op->o_callback->sc_private;
01162        BackendInfo *bi_orig = rm_ctx->be->bd_info;
01163 
01164        rm_ctx->be->bd_info = (BackendInfo*) rm_ctx->on;
01165 
01166        if ( rm_ctx->on->on_bi.bi_db_close ) {
01167               rm_ctx->on->on_bi.bi_db_close( rm_ctx->be, NULL );
01168        }
01169        if ( rm_ctx->on->on_bi.bi_db_destroy ) {
01170               rm_ctx->on->on_bi.bi_db_destroy( rm_ctx->be, NULL );
01171        }
01172 
01173        /* clean up after removing last overlay */
01174        if ( ! rm_ctx->on->on_info->oi_list ) {
01175               /* reset db flags and bd_info to orig */
01176               SLAP_DBFLAGS( rm_ctx->be ) &= ~SLAP_DBFLAG_GLOBAL_OVERLAY;
01177               rm_ctx->be->bd_info = rm_ctx->on->on_info->oi_orig;
01178               ch_free(rm_ctx->on->on_info);
01179        } else {
01180               rm_ctx->be->bd_info = bi_orig;
01181        }
01182        free( rm_ctx->on );
01183        op->o_tmpfree(rm_ctx, op->o_tmpmemctx);
01184        return SLAP_CB_CONTINUE;
01185 }
01186 
01187 void
01188 overlay_remove( BackendDB *be, slap_overinst *on, Operation *op )
01189 {
01190        slap_overinfo *oi = on->on_info;
01191        slap_overinst **oidx;
01192        ov_remove_ctx *rm_ctx;
01193        slap_callback *rm_cb, *cb;
01194 
01195        /* remove overlay from oi_list */
01196        for ( oidx = &oi->oi_list; *oidx; oidx = &(*oidx)->on_next ) {
01197               if ( *oidx == on ) {
01198                      *oidx = on->on_next;
01199                      break;
01200               }
01201        }
01202 
01203        /* The db_close and db_destroy handlers to cleanup a release
01204         * the overlay's resources are called from the cleanup callback
01205         */
01206        rm_ctx = op->o_tmpalloc( sizeof( ov_remove_ctx ), op->o_tmpmemctx );
01207        rm_ctx->be = be;
01208        rm_ctx->on = on;
01209 
01210        rm_cb = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx );
01211        rm_cb->sc_next = NULL;
01212        rm_cb->sc_cleanup = overlay_remove_cb;
01213        rm_cb->sc_response = NULL;
01214        rm_cb->sc_private = (void*) rm_ctx;
01215 
01216        /* Append callback to the end of the list */
01217        for ( cb = op->o_callback; cb->sc_next; cb = cb->sc_next );
01218        cb->sc_next = rm_cb;
01219 }
01220 #endif /* SLAP_CONFIG_DELETE */
01221 
01222 void
01223 overlay_insert( BackendDB *be, slap_overinst *on2, slap_overinst ***prev,
01224        int idx )
01225 {
01226        slap_overinfo *oi = (slap_overinfo *)be->bd_info;
01227 
01228        if ( idx == -1 ) {
01229               on2->on_next = oi->oi_list;
01230               oi->oi_list = on2;
01231        } else {
01232               int i, novs;
01233               slap_overinst *on, **prev;
01234 
01235               /* Since the list is in reverse order and is singly linked,
01236                * we have to count the overlays and then insert backwards.
01237                * Adding on overlay at a specific point should be a pretty
01238                * infrequent occurrence.
01239                */
01240               novs = 0;
01241               for ( on = oi->oi_list; on; on=on->on_next )
01242                      novs++;
01243 
01244               if (idx > novs)
01245                      idx = 0;
01246               else
01247                      idx = novs - idx;
01248 
01249               /* advance to insertion point */
01250               prev = &oi->oi_list;
01251               for ( i=0; i<idx; i++ ) {
01252                      on = *prev;
01253                      prev = &on->on_next;
01254               }
01255               /* insert */
01256               on2->on_next = *prev;
01257               *prev = on2;
01258        }
01259 }
01260 
01261 void
01262 overlay_move( BackendDB *be, slap_overinst *on, int idx )
01263 {
01264        slap_overinfo *oi = (slap_overinfo *)be->bd_info;
01265        slap_overinst **onp;
01266 
01267        for (onp = &oi->oi_list; *onp; onp= &(*onp)->on_next) {
01268               if ( *onp == on ) {
01269                      *onp = on->on_next;
01270                      break;
01271               }
01272        }
01273        overlay_insert( be, on, &onp, idx );
01274 }
01275 
01276 /* add an overlay to a particular backend. */
01277 int
01278 overlay_config( BackendDB *be, const char *ov, int idx, BackendInfo **res, ConfigReply *cr )
01279 {
01280        slap_overinst *on = NULL, *on2 = NULL, **prev;
01281        slap_overinfo *oi = NULL;
01282        BackendInfo *bi = NULL;
01283 
01284        if ( res )
01285               *res = NULL;
01286 
01287        on = overlay_find( ov );
01288        if ( !on ) {
01289               Debug( LDAP_DEBUG_ANY, "overlay \"%s\" not found\n", ov, 0, 0 );
01290               return 1;
01291        }
01292 
01293        /* If this is the first overlay on this backend, set up the
01294         * overlay info structure
01295         */
01296        if ( !overlay_is_over( be ) ) {
01297               int    isglobal = 0;
01298 
01299               /* NOTE: the first time a global overlay is configured,
01300                * frontendDB gets this flag; it is used later by overlays
01301                * to determine if they're stacked on top of the frontendDB */
01302               if ( be->bd_info == frontendDB->bd_info || SLAP_ISGLOBALOVERLAY( be ) ) {
01303                      isglobal = 1;
01304                      if ( on->on_bi.bi_flags & SLAPO_BFLAG_DBONLY ) {
01305                             Debug( LDAP_DEBUG_ANY, "overlay_config(): "
01306                                    "overlay \"%s\" cannot be global.\n",
01307                                    ov, 0, 0 );
01308                             return 1;
01309                      }
01310 
01311               } else if ( on->on_bi.bi_flags & SLAPO_BFLAG_GLOBONLY ) {
01312                      Debug( LDAP_DEBUG_ANY, "overlay_config(): "
01313                             "overlay \"%s\" can only be global.\n",
01314                             ov, 0, 0 );
01315                      return 1;
01316               }
01317 
01318               oi = ch_malloc( sizeof( slap_overinfo ) );
01319               oi->oi_orig = be->bd_info;
01320               oi->oi_bi = *be->bd_info;
01321               oi->oi_origdb = be;
01322 
01323               if ( isglobal ) {
01324                      SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_GLOBAL_OVERLAY;
01325               }
01326 
01327               /* Save a pointer to ourself in bi_private.
01328                */
01329               oi->oi_bi.bi_private = oi;
01330               oi->oi_list = NULL;
01331               bi = (BackendInfo *)oi;
01332 
01333               bi->bi_type = (char *)overtype;
01334 
01335               bi->bi_db_config = over_db_config;
01336               bi->bi_db_open = over_db_open;
01337               bi->bi_db_close = over_db_close;
01338               bi->bi_db_destroy = over_db_destroy;
01339 
01340               bi->bi_op_bind = over_op_bind;
01341               bi->bi_op_unbind = over_op_unbind;
01342               bi->bi_op_search = over_op_search;
01343               bi->bi_op_compare = over_op_compare;
01344               bi->bi_op_modify = over_op_modify;
01345               bi->bi_op_modrdn = over_op_modrdn;
01346               bi->bi_op_add = over_op_add;
01347               bi->bi_op_delete = over_op_delete;
01348               bi->bi_op_abandon = over_op_abandon;
01349               bi->bi_op_cancel = over_op_cancel;
01350 
01351               bi->bi_extended = over_op_extended;
01352 
01353               /*
01354                * this is fine because it has the same
01355                * args of the operations; we need to rework
01356                * all the hooks to share the same args
01357                * of the operations...
01358                */
01359               bi->bi_operational = over_aux_operational;
01360               bi->bi_chk_referrals = over_aux_chk_referrals;
01361               bi->bi_chk_controls = over_aux_chk_controls;
01362 
01363               /* these have specific arglists */
01364               bi->bi_entry_get_rw = over_entry_get_rw;
01365               bi->bi_entry_release_rw = over_entry_release_rw;
01366               bi->bi_access_allowed = over_access_allowed;
01367               bi->bi_acl_group = over_acl_group;
01368               bi->bi_acl_attribute = over_acl_attribute;
01369               
01370               bi->bi_connection_init = over_connection_init;
01371               bi->bi_connection_destroy = over_connection_destroy;
01372 
01373               be->bd_info = bi;
01374 
01375        } else {
01376               if ( overlay_is_inst( be, ov ) ) {
01377                      if ( SLAPO_SINGLE( be ) ) {
01378                             Debug( LDAP_DEBUG_ANY, "overlay_config(): "
01379                                    "overlay \"%s\" already in list\n",
01380                                    ov, 0, 0 );
01381                             return 1;
01382                      }
01383               }
01384 
01385               oi = be->bd_info->bi_private;
01386        }
01387 
01388        /* Insert new overlay into list. By default overlays are
01389         * added to head of list and executed in LIFO order.
01390         */
01391        on2 = ch_calloc( 1, sizeof(slap_overinst) );
01392        *on2 = *on;
01393        on2->on_info = oi;
01394 
01395        prev = &oi->oi_list;
01396        /* Do we need to find the insertion point? */
01397        if ( idx >= 0 ) {
01398               int i;
01399 
01400               /* count current overlays */
01401               for ( i=0, on=oi->oi_list; on; on=on->on_next, i++ );
01402 
01403               /* are we just appending a new one? */
01404               if ( idx >= i )
01405                      idx = -1;
01406        }
01407        overlay_insert( be, on2, &prev, idx );
01408 
01409        /* Any initialization needed? */
01410        if ( on2->on_bi.bi_db_init ) {
01411               int rc;
01412               be->bd_info = (BackendInfo *)on2;
01413               rc = on2->on_bi.bi_db_init( be, cr);
01414               be->bd_info = (BackendInfo *)oi;
01415               if ( rc ) {
01416                      *prev = on2->on_next;
01417                      ch_free( on2 );
01418                      on2 = NULL;
01419                      return rc;
01420               }
01421        }
01422 
01423        if ( res )
01424               *res = &on2->on_bi;
01425 
01426        return 0;
01427 }
01428