]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/bconfig.c
Fix prev commit, don't generate a new ctxcsn if we're a consumer with
[openldap] / servers / slapd / bconfig.c
index 9f4f1c936cb7b01c37adc0b3d1f01b75d3a557f8..9ec4b7f10ba52a0ebb69c38179206d8ada26aba3 100644 (file)
@@ -103,7 +103,7 @@ static OidMacro *cf_om_tail;
 static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
        SlapReply *rs, int *renumber, Operation *op );
 
-static int config_check_schema( CfBackInfo *cfb );
+static int config_check_schema( Operation *op, CfBackInfo *cfb );
 
 static ConfigDriver config_fname;
 static ConfigDriver config_cfdir;
@@ -179,6 +179,7 @@ enum {
        CFG_MIRRORMODE,
        CFG_HIDDEN,
        CFG_MONITORING,
+       CFG_SERVERID,
 
        CFG_LAST
 };
@@ -200,6 +201,12 @@ static OidRec OidMacros[] = {
        { "OLcfgBkOc", "OLcfgOc:1" },
        { "OLcfgDbOc", "OLcfgOc:2" },
        { "OLcfgOvOc", "OLcfgOc:3" },
+
+       /* Syntaxes. We should just start using the standard names and
+        * document that they are predefined and available for users
+        * to reference in their own schema. Defining schema without
+        * OID macros is for masochists...
+        */
        { "OMsyn", "1.3.6.1.4.1.1466.115.121.1" },
        { "OMsBoolean", "OMsyn:7" },
        { "OMsDN", "OMsyn:12" },
@@ -344,8 +351,7 @@ static ConfigTable config_back_cf_table[] = {
                &global_idletimeout, "( OLcfgGlAt:18 NAME 'olcIdleTimeout' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "include", "file", 2, 2, 0, ARG_MAGIC,
-               &config_include, "( OLcfgGlAt:19 NAME 'olcInclude' "
-                       "SUP labeledURI )", NULL, NULL },
+               &config_include, NULL, NULL, NULL },
        { "index_substr_if_minlen", "min", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN,
                &config_generic, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
@@ -527,6 +533,10 @@ static ConfigTable config_back_cf_table[] = {
                &config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' "
                        "EQUALITY caseIgnoreMatch "
                        "SYNTAX OMsDirectoryString )", NULL, NULL },
+       { "serverID", "number> <[URI]", 2, 3, 0, ARG_MAGIC|CFG_SERVERID,
+               &config_generic, "( OLcfgGlAt:81 NAME 'olcServerID' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
                &config_sizelimit, "( OLcfgGlAt:60 NAME 'olcSizeLimit' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
@@ -545,7 +555,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsDN )", NULL, NULL },
        { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
                &syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
-                       "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+                       "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
        { "threads", "count", 2, 2, 0,
 #ifdef NO_THREADS
                ARG_IGNORED, NULL,
@@ -646,7 +656,7 @@ static ConfigTable config_back_cf_table[] = {
 };
 
 /* Routines to check if a child can be added to this type */
-static ConfigLDAPadd cfAddSchema, cfAddInclude, cfAddDatabase,
+static ConfigLDAPadd cfAddSchema, cfAddDatabase,
        cfAddBackend, cfAddModule, cfAddOverlay;
 
 /* NOTE: be careful when defining array members
@@ -656,10 +666,9 @@ static ConfigLDAPadd cfAddSchema, cfAddInclude, cfAddDatabase,
 #define CFOC_BACKEND   cf_ocs[3]
 #define CFOC_DATABASE  cf_ocs[4]
 #define CFOC_OVERLAY   cf_ocs[5]
-#define CFOC_INCLUDE   cf_ocs[6]
-#define CFOC_FRONTEND  cf_ocs[7]
+#define CFOC_FRONTEND  cf_ocs[6]
 #ifdef SLAPD_MODULES
-#define CFOC_MODULE    cf_ocs[8]
+#define CFOC_MODULE    cf_ocs[7]
 #endif /* SLAPD_MODULES */
 
 static ConfigOCs cf_ocs[] = {
@@ -684,7 +693,7 @@ static ConfigOCs cf_ocs[] = {
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
                 "olcRootDSE $ "
                 "olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
-                "olcSecurity $ olcSizeLimit $ "
+                "olcSecurity $ olcServerID $ olcSizeLimit $ "
                 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
                 "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
                 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
@@ -724,13 +733,6 @@ static ConfigOCs cf_ocs[] = {
                "DESC 'OpenLDAP Overlay-specific options' "
                "SUP olcConfig STRUCTURAL "
                "MUST olcOverlay )", Cft_Overlay, NULL, cfAddOverlay },
-       { "( OLcfgGlOc:6 "
-               "NAME 'olcIncludeFile' "
-               "DESC 'OpenLDAP configuration include file' "
-               "SUP olcConfig STRUCTURAL "
-               "MUST olcInclude "
-               "MAY ( cn $ olcRootDSE ) )",
-               Cft_Include, NULL, cfAddInclude },
        /* This should be STRUCTURAL like all the other database classes, but
         * that would mean inheriting all of the olcDatabaseConfig attributes,
         * which causes them to be merged twice in config_build_entry.
@@ -752,6 +754,14 @@ static ConfigOCs cf_ocs[] = {
        { NULL, 0, NULL }
 };
 
+typedef struct ServerID {
+       struct ServerID *si_next;
+       struct berval si_url;
+       int si_num;
+} ServerID;
+
+static ServerID *sid_list;
+
 static int
 config_generic(ConfigArgs *c) {
        int i;
@@ -938,6 +948,30 @@ config_generic(ConfigArgs *c) {
                        }
                        }
                        break;
+               case CFG_SERVERID:
+                       if ( sid_list ) {
+                               ServerID *si;
+                               struct berval bv;
+                               char *ptr;
+
+                               for ( si = sid_list; si; si=si->si_next ) {
+                                       if ( !BER_BVISEMPTY( &si->si_url )) {
+                                               bv.bv_len = si->si_url.bv_len + 6;
+                                               bv.bv_val = ch_malloc( bv.bv_len );
+                                               sprintf( bv.bv_val, "%d %s", si->si_num,
+                                                       si->si_url.bv_val );
+                                               ber_bvarray_add( &c->rvalue_vals, &bv );
+                                       } else {
+                                               char buf[5];
+                                               bv.bv_val = buf;
+                                               bv.bv_len = sprintf( buf, "%d", si->si_num );
+                                               value_add_one( &c->rvalue_vals, &bv );
+                                       }
+                               }
+                       } else {
+                               rc = 1;
+                       }
+                       break;
                case CFG_LOGFILE:
                        if ( logfileName )
                                c->value_string = ch_strdup( logfileName );
@@ -1086,6 +1120,23 @@ config_generic(ConfigArgs *c) {
                        logfileName = NULL;
                        break;
 
+               case CFG_SERVERID: {
+                       int i;
+                       ServerID *si, **sip;
+
+                       for ( i=0, si = sid_list, sip = &sid_list;
+                               si; si = *sip, i++ ) {
+                               if ( c->valx == -1 || i == c->valx ) {
+                                       *sip = si->si_next;
+                                       ch_free( si );
+                                       if ( c->valx >= 0 )
+                                               break;
+                               } else {
+                                       sip = &si->si_next;
+                               }
+                       }
+                       }
+                       break;
                case CFG_HIDDEN:
                        c->be->be_flags &= ~SLAP_DBFLAG_HIDDEN;
                        break;
@@ -1516,6 +1567,111 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
 
+               case CFG_SERVERID:
+                       {
+                               ServerID *si, **sip;
+                               LDAPURLDesc *lud;
+                               int num = atoi( c->argv[1] );
+                               if ( num < 0 || num > SLAP_SYNC_SID_MAX ) {
+                                       snprintf( c->msg, sizeof( c->msg ),
+                                               "<%s> illegal server ID", c->argv[0] );
+                                       Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+                                               c->log, c->msg, c->argv[1] );
+                                       return 1;
+                               }
+                               /* only one value allowed if no URL is given */
+                               if ( c->argc > 2 ) {
+                                       int len;
+
+                                       if ( sid_list && BER_BVISEMPTY( &sid_list->si_url )) {
+                                               snprintf( c->msg, sizeof( c->msg ),
+                                                       "<%s> only one server ID allowed now", c->argv[0] );
+                                               Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+                                                       c->log, c->msg, c->argv[1] );
+                                               return 1;
+                                       }
+
+                                       if ( ldap_url_parse( c->argv[2], &lud )) {
+                                               snprintf( c->msg, sizeof( c->msg ),
+                                                       "<%s> invalid URL", c->argv[0] );
+                                               Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+                                                       c->log, c->msg, c->argv[2] );
+                                               return 1;
+                                       }
+                                       len = strlen( c->argv[2] );
+                                       si = ch_malloc( sizeof(ServerID) + len + 1 );
+                                       si->si_url.bv_val = (char *)(si+1);
+                                       si->si_url.bv_len = len;
+                                       strcpy( si->si_url.bv_val, c->argv[3] );
+                               } else {
+                                       if ( sid_list ) {
+                                               snprintf( c->msg, sizeof( c->msg ),
+                                                       "<%s> unqualified server ID not allowed now", c->argv[0] );
+                                               Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+                                                       c->log, c->msg, c->argv[1] );
+                                               return 1;
+                                       }
+                                       si = ch_malloc( sizeof(ServerID) );
+                                       slap_serverID = num;
+                               }
+                               si->si_next = NULL;
+                               si->si_num = num;
+                               for ( sip = &sid_list; *sip; sip = &(*sip)->si_next );
+                               *sip = si;
+
+                               if (( slapMode & SLAP_SERVER_MODE ) && c->argc > 2 ) {
+                                       /* If hostname is empty, or is localhost, or matches
+                                        * our hostname, this serverID refers to this host.
+                                        * Compare it against listeners and ports.
+                                        */
+                                       if ( !lud->lud_host || !lud->lud_host[0] ||
+                                               !strncasecmp("localhost", lud->lud_host,
+                                                       STRLENOF("localhost")) ||
+                                               !strcasecmp( global_host, lud->lud_host )) {
+                                               Listener **l = slapd_get_listeners();
+                                               int i;
+
+                                               for ( i=0; l[i]; i++ ) {
+                                                       LDAPURLDesc *lu2;
+                                                       int isMe = 0;
+                                                       ldap_url_parse( l[i]->sl_url.bv_val, &lu2 );
+                                                       do {
+                                                               if ( strcasecmp( lud->lud_scheme,
+                                                                       lu2->lud_scheme ))
+                                                                       break;
+                                                               if ( lud->lud_port != lu2->lud_port )
+                                                                       break;
+                                                               /* Listener on ANY address */
+                                                               if ( !lu2->lud_host || !lu2->lud_host[0] ) {
+                                                                       isMe = 1;
+                                                                       break;
+                                                               }
+                                                               /* URL on ANY address */
+                                                               if ( !lud->lud_host || !lud->lud_host[0] ) {
+                                                                       isMe = 1;
+                                                                       break;
+                                                               }
+                                                               /* Listener has specific host, must
+                                                                * match it
+                                                                */
+                                                               if ( !strcasecmp( lud->lud_host,
+                                                                       lu2->lud_host )) {
+                                                                       isMe = 1;
+                                                                       break;
+                                                               }
+                                                       } while(0);
+                                                       ldap_free_urldesc( lu2 );
+                                                       if ( isMe ) {
+                                                               slap_serverID = si->si_num;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                               if ( c->argc > 2 )
+                                       ldap_free_urldesc( lud );
+                       }
+                       break;
                case CFG_LOGFILE: {
                                FILE *logfile;
                                if ( logfileName ) ch_free( logfileName );
@@ -1620,7 +1776,7 @@ config_generic(ConfigArgs *c) {
                        }
                        /* Check for any new hardcoded schema */
                        if ( c->op == LDAP_MOD_ADD && CONFIG_ONLINE_ADD( c )) {
-                               config_check_schema( &cfBackInfo );
+                               config_check_schema( NULL, &cfBackInfo );
                        }
                        break;
 
@@ -2959,9 +3115,6 @@ config_shadow( ConfigArgs *c, int flag )
 
        } else if ( SLAP_MONITOR(c->be) ) {
                notallowed = "monitor";
-
-       } else if ( SLAP_CONFIG(c->be) ) {
-               notallowed = "config";
        }
 
        if ( notallowed != NULL ) {
@@ -2996,7 +3149,7 @@ config_updateref(ConfigArgs *c) {
                }
                return 0;
        }
-       if(!SLAP_SHADOW(c->be)) {
+       if(!SLAP_SHADOW(c->be) && !c->be->be_syncinfo) {
                snprintf( c->msg, sizeof( c->msg ), "<%s> must appear after syncrepl or updatedn",
                        c->argv[0] );
                Debug(LDAP_DEBUG_ANY, "%s: %s\n",
@@ -3022,15 +3175,8 @@ config_include(ConfigArgs *c) {
        ConfigFile *cf;
        ConfigFile *cfsave = cfn;
        ConfigFile *cf2 = NULL;
-       if (c->op == SLAP_CONFIG_EMIT) {
-               if (c->private) {
-                       ConfigFile *cf = c->private;
-                       value_add_one( &c->rvalue_vals, &cf->c_file );
-                       return 0;
-               }
-               return 1;
-       } else if ( c->op == LDAP_MOD_DELETE ) {
-       }
+
+       /* No dynamic config for include files */
        cf = ch_calloc( 1, sizeof(ConfigFile));
        if ( cfn->c_kids ) {
                for (cf2=cfn->c_kids; cf2 && cf2->c_sibs; cf2=cf2->c_sibs) ;
@@ -3705,7 +3851,7 @@ config_rename_one( Operation *op, SlapReply *rs, Entry *e,
        if ( use_ldif ) {
                CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private;
                BackendDB *be = op->o_bd;
-               slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+               slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
                struct berval dn, ndn, xdn, xndn;
 
                op->o_bd = &cfb->cb_db;
@@ -3720,18 +3866,19 @@ config_rename_one( Operation *op, SlapReply *rs, Entry *e,
                op->o_req_dn = odn;
                op->o_req_ndn = ondn;
 
-               sc.sc_next = op->o_callback;
+               scp = op->o_callback;
                op->o_callback = &sc;
                op->orr_newrdn = *newrdn;
                op->orr_nnewrdn = *nnewrdn;
                op->orr_deleteoldrdn = 1;
                op->orr_modlist = NULL;
                slap_modrdn2mods( op, rs );
+               slap_mods_opattrs( op, &op->orr_modlist, 1 );
                rc = op->o_bd->be_modrdn( op, rs );
                slap_mods_free( op->orr_modlist, 1 );
 
                op->o_bd = be;
-               op->o_callback = sc.sc_next;
+               op->o_callback = scp;
                op->o_dn = dn;
                op->o_ndn = ndn;
                op->o_req_dn = xdn;
@@ -3803,7 +3950,7 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
 {
        CfEntryInfo *ce;
        int index = -1, gotindex = 0, nsibs, rc = 0;
-       int renumber = 0, tailindex = 0;
+       int renumber = 0, tailindex = 0, isfrontend = 0;
        char *ptr1, *ptr2 = NULL;
        struct berval rdn;
 
@@ -3813,11 +3960,14 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
        if ( ce_type == Cft_Global ) return 0;
        if ( ce_type == Cft_Schema && parent->ce_type == Cft_Global ) return 0;
 
-       if ( ce_type == Cft_Include || ce_type == Cft_Module )
+       if ( ce_type == Cft_Module )
                tailindex = 1;
 
        /* See if the rdn has an index already */
        dnRdn( &e->e_name, &rdn );
+       if ( ce_type == Cft_Database && !strncmp( rdn.bv_val + rdn.bv_len -
+               STRLENOF("frontend"), "frontend", STRLENOF("frontend") ))
+               isfrontend = 1;
        ptr1 = ber_bvchr( &e->e_name, '{' );
        if ( ptr1 && ptr1 - e->e_name.bv_val < rdn.bv_len ) {
                char    *next;
@@ -3833,9 +3983,7 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
                }
                if ( index < 0 ) {
                        /* Special case, we allow -1 for the frontendDB */
-                       if ( index != -1 || ce_type != Cft_Database ||
-                               strncmp( ptr2+1, "frontend,", STRLENOF("frontend,") ))
-
+                       if ( index != -1 || !isfrontend )
                                return LDAP_NAMING_VIOLATION;
                }
        }
@@ -3850,9 +3998,13 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
                        if ( index < nsibs ) {
                                if ( tailindex ) return LDAP_NAMING_VIOLATION;
                                /* Siblings need to be renumbered */
-                               renumber = 1;
+                               if ( index != -1 || !isfrontend )
+                                       renumber = 1;
                        }
                }
+               if ( !isfrontend && index == -1 )
+                       index = nsibs;
+
                /* just make index = nsibs */
                if ( !renumber ) {
                        rc = config_renumber_one( NULL, rs, parent, e, index, tailindex, 0 );
@@ -3892,21 +4044,6 @@ count_ocs( Attribute *oc_at, int *nocs )
        return colst;
 }
 
-static int
-cfAddInclude( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
-{
-       if ( p->ce_type != Cft_Global && p->ce_type != Cft_Include )
-               return LDAP_CONSTRAINT_VIOLATION;
-
-       /* If we're reading from a configdir, don't parse this entry */
-       if ( ca->lineno )
-               return LDAP_COMPARE_TRUE;
-
-       cfn = p->ce_private;
-       ca->private = cfn;
-       return LDAP_SUCCESS;
-}
-
 static int
 cfAddSchema( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
 {
@@ -3977,12 +4114,16 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        char *ptr;
 
        /* Make sure parent exists and entry does not. But allow
-        * Databases and Overlays to be inserted.
+        * Databases and Overlays to be inserted. Don't do any
+        * auto-renumbering if manageDSAit control is present.
         */
        ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
-       if ( ce && ce->ce_type != Cft_Database &&
-               ce->ce_type != Cft_Overlay )
+       if ( ce ) {
+               if (( op && op->o_managedsait ) ||
+                       ( ce->ce_type != Cft_Database && ce->ce_type != Cft_Overlay &&
+                         ce->ce_type != Cft_Module ))
                return LDAP_ALREADY_EXISTS;
+       }
 
        dnParent( &e->e_nname, &pdn );
 
@@ -4019,6 +4160,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
                ca->fname = cfdir.bv_val;
                ca->lineno = 1;
        }
+       ca->ca_op = op;
 
        colst = count_ocs( oc_at, &nocs );
 
@@ -4170,7 +4312,7 @@ ok:
 
                /* Advance to first of this type */
                cprev = &last->ce_kids;
-               for ( c2 = *cprev; c2 && c2->ce_type != ce->ce_type; ) {
+               for ( c2 = *cprev; c2 && c2->ce_type < ce->ce_type; ) {
                        cprev = &c2->ce_sibs;
                        c2 = c2->ce_sibs;
                }
@@ -4304,6 +4446,23 @@ config_back_add( Operation *op, SlapReply *rs )
 
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
+       /* add opattrs for syncprov */
+       {
+               char textbuf[SLAP_TEXT_BUFLEN];
+               size_t textlen = sizeof textbuf;
+               rs->sr_err = entry_schema_check(op, op->ora_e, NULL, 0, 1,
+                       &rs->sr_text, textbuf, sizeof( textbuf ) );
+               if ( rs->sr_err != LDAP_SUCCESS )
+                       goto out;
+               rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
+               if ( rs->sr_err != LDAP_SUCCESS ) {
+                       Debug( LDAP_DEBUG_TRACE,
+                               LDAP_XSTRING(config_back_add) ": entry failed op attrs add: "
+                               "%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
+                       goto out;
+               }
+       }
+
        ldap_pvt_thread_pool_pause( &connection_pool );
 
        /* Strategy:
@@ -4333,7 +4492,7 @@ config_back_add( Operation *op, SlapReply *rs )
 
        if ( cfb->cb_use_ldif ) {
                BackendDB *be = op->o_bd;
-               slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+               slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
                struct berval dn, ndn;
 
                op->o_bd = &cfb->cb_db;
@@ -4344,11 +4503,11 @@ config_back_add( Operation *op, SlapReply *rs )
                op->o_dn = op->o_bd->be_rootdn;
                op->o_ndn = op->o_bd->be_rootndn;
 
-               sc.sc_next = op->o_callback;
+               scp = op->o_callback;
                op->o_callback = &sc;
                op->o_bd->be_add( op, rs );
                op->o_bd = be;
-               op->o_callback = sc.sc_next;
+               op->o_callback = scp;
                op->o_dn = dn;
                op->o_ndn = ndn;
        }
@@ -4358,6 +4517,7 @@ out2:;
 
 out:;
        send_ldap_result( op, rs );
+       slap_graduate_commit_csn( op );
        return rs->sr_err;
 }
 
@@ -4394,6 +4554,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
        ca->private = ce->ce_private;
        ca->ca_entry = e;
        ca->fname = "slapd";
+       ca->ca_op = op;
        strcpy( ca->log, "back-config" );
 
        for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
@@ -4672,7 +4833,10 @@ config_back_modify( Operation *op, SlapReply *rs )
                }
        }
 
-       ldap_pvt_thread_pool_pause( &connection_pool );
+       slap_mods_opattrs( op, &op->orm_modlist, 1 );
+
+       if ( !slapd_shutdown )
+               ldap_pvt_thread_pool_pause( &connection_pool );
 
        /* Strategy:
         * 1) perform the Modify on the cached Entry.
@@ -4685,7 +4849,7 @@ config_back_modify( Operation *op, SlapReply *rs )
                rs->sr_text = ca.msg;
        } else if ( cfb->cb_use_ldif ) {
                BackendDB *be = op->o_bd;
-               slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+               slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
                struct berval dn, ndn;
 
                op->o_bd = &cfb->cb_db;
@@ -4695,18 +4859,20 @@ config_back_modify( Operation *op, SlapReply *rs )
                op->o_dn = op->o_bd->be_rootdn;
                op->o_ndn = op->o_bd->be_rootndn;
 
-               sc.sc_next = op->o_callback;
+               scp = op->o_callback;
                op->o_callback = &sc;
                op->o_bd->be_modify( op, rs );
                op->o_bd = be;
-               op->o_callback = sc.sc_next;
+               op->o_callback = scp;
                op->o_dn = dn;
                op->o_ndn = ndn;
        }
 
-       ldap_pvt_thread_pool_resume( &connection_pool );
+       if ( !slapd_shutdown )
+               ldap_pvt_thread_pool_resume( &connection_pool );
 out:
        send_ldap_result( op, rs );
+       slap_graduate_commit_csn( op );
        return rs->sr_err;
 }
 
@@ -4907,6 +5073,13 @@ out:
        return rs->sr_err;
 }
 
+static int
+config_back_delete( Operation *op, SlapReply *rs )
+{
+       send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, NULL );
+       return rs->sr_err;
+}
+
 static int
 config_back_search( Operation *op, SlapReply *rs )
 {
@@ -4952,6 +5125,41 @@ out:
        return 0;
 }
 
+/* no-op, we never free entries */
+int config_entry_release(
+       Operation *op,
+       Entry *e,
+       int rw )
+{
+       return LDAP_SUCCESS;
+}
+
+/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
+ */
+int config_back_entry_get(
+       Operation *op,
+       struct berval *ndn,
+       ObjectClass *oc,
+       AttributeDescription *at,
+       int rw,
+       Entry **ent )
+{
+       CfBackInfo *cfb;
+       CfEntryInfo *ce, *last;
+
+       cfb = (CfBackInfo *)op->o_bd->be_private;
+
+       ce = config_find_base( cfb->cb_root, ndn, &last );
+       if ( ce ) {
+               *ent = ce->ce_entry;
+               if ( *ent && oc && !is_entry_objectclass_or_sub( *ent, oc ) ) {
+                       *ent = NULL;
+               }
+       }
+
+       return ( *ent == NULL ? 1 : 0 );
+}
+
 static void
 config_build_attrs( Entry *e, AttributeType **at, AttributeDescription *ad,
        ConfigTable *ct, ConfigArgs *c )
@@ -5003,17 +5211,18 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
        Debug( LDAP_DEBUG_TRACE, "config_build_entry: \"%s\"\n", rdn->bv_val, 0, 0);
        e->e_private = ce;
        ce->ce_entry = e;
+       ce->ce_type = main->co_type;
        ce->ce_parent = parent;
        if ( parent ) {
                pdn = parent->ce_entry->e_nname;
-               if ( parent->ce_kids )
-                       for ( ceprev = parent->ce_kids; ceprev->ce_sibs;
+               if ( parent->ce_kids && parent->ce_kids->ce_type < ce->ce_type )
+                       for ( ceprev = parent->ce_kids; ceprev->ce_sibs &&
+                               ceprev->ce_type < ce->ce_type;
                                ceprev = ceprev->ce_sibs );
        } else {
                BER_BVZERO( &pdn );
        }
 
-       ce->ce_type = main->co_type;
        ce->ce_private = c->private;
        ce->ce_be = c->be;
        ce->ce_bi = c->bi;
@@ -5055,10 +5264,11 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
 
        oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
        rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->msg,
-               sizeof(c->msg), op->o_tmpmemctx );
+               sizeof(c->msg), op ? op->o_tmpmemctx : NULL );
        attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL );
-       if ( !op->o_noop ) {
+       if ( op && !op->o_noop ) {
                op->ora_e = e;
+               op->ora_modlist = NULL;
                op->o_bd->be_add( op, rs );
                if ( ( rs->sr_err != LDAP_SUCCESS ) 
                                && (rs->sr_err != LDAP_ALREADY_EXISTS) ) {
@@ -5066,8 +5276,10 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
                }
        }
        if ( ceprev ) {
+               ce->ce_sibs = ceprev->ce_sibs;
                ceprev->ce_sibs = ce;
        } else if ( parent ) {
+               ce->ce_sibs = parent->ce_kids;
                parent->ce_kids = ce;
        }
 
@@ -5118,34 +5330,6 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent,
        return 0;
 }
 
-static int
-config_build_includes( ConfigArgs *c, CfEntryInfo *ceparent,
-       Operation *op, SlapReply *rs )
-{
-       Entry *e;
-       int i;
-       ConfigFile *cf = c->private;
-
-       for (i=0; cf; cf=cf->c_sibs, i++) {
-               c->value_dn.bv_val = c->log;
-               c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=include" SLAP_X_ORDERED_FMT, i);
-               if ( c->value_dn.bv_len >= sizeof( c->log ) ) {
-                       /* FIXME: how can indicate error? */
-                       return -1;
-               }
-               c->private = cf;
-               e = config_build_entry( op, rs, ceparent, c, &c->value_dn,
-                       &CFOC_INCLUDE, NULL );
-               if ( ! e ) {
-                       return -1;
-               } else if ( e && cf->c_kids ) {
-                       c->private = cf->c_kids;
-                       config_build_includes( c, e->e_private, op, rs );
-               }
-       }
-       return 0;
-}
-
 #ifdef SLAPD_MODULES
 
 static int
@@ -5174,11 +5358,10 @@ config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent,
 #endif
 
 static int
-config_check_schema(CfBackInfo *cfb)
+config_check_schema(Operation *op, CfBackInfo *cfb)
 {
        struct berval schema_dn = BER_BVC(SCHEMA_RDN "," CONFIG_RDN);
        ConfigArgs c = {0};
-       ConfigFile *cf = cfb->cb_config;
        CfEntryInfo *ce, *last;
        Entry *e;
 
@@ -5240,7 +5423,7 @@ config_check_schema(CfBackInfo *cfb)
        } else {
                SlapReply rs = {REP_RESULT};
                c.private = NULL;
-               e = config_build_entry( NULL, &rs, cfb->cb_root, &c, &schema_rdn,
+               e = config_build_entry( op, &rs, cfb->cb_root, &c, &schema_rdn,
                        &CFOC_SCHEMA, NULL );
                if ( !e ) {
                        return -1;
@@ -5284,11 +5467,6 @@ config_back_db_open( BackendDB *be )
                parse_acl(be, "config_back_db_open", 0, 6, (char **)defacl, 0 );
        }
 
-       /* If we read the config from back-ldif, do some quick sanity checks */
-       if ( cfb->cb_got_ldif ) {
-               return config_check_schema( cfb );
-       }
-
        thrctx = ldap_pvt_thread_pool_context();
        op = (Operation *) &opbuf;
        connection_fake_init( &conn, op, thrctx );
@@ -5303,6 +5481,11 @@ config_back_db_open( BackendDB *be )
                op->o_noop = 1;
        }
 
+       /* If we read the config from back-ldif, do some quick sanity checks */
+       if ( cfb->cb_got_ldif ) {
+               return config_check_schema( op, cfb );
+       }
+
        /* create root of tree */
        rdn = config_rdn;
        c.private = cfb->cb_config;
@@ -5317,15 +5500,6 @@ config_back_db_open( BackendDB *be )
        parent = e;
        ceparent = ce;
 
-       /* Create includeFile nodes */
-       if ( cfb->cb_config->c_kids ) {
-               c.depth = 0;
-               c.private = cfb->cb_config->c_kids;
-               if ( config_build_includes( &c, ceparent, op, &rs ) ) {
-                       return -1;
-               }
-       }
-
 #ifdef SLAPD_MODULES
        /* Create Module nodes... */
        if ( modpaths.mp_loads ) {
@@ -5725,7 +5899,7 @@ config_back_initialize( BackendInfo *bi )
        bi->bi_op_modify = config_back_modify;
        bi->bi_op_modrdn = config_back_modrdn;
        bi->bi_op_add = config_back_add;
-       bi->bi_op_delete = 0;
+       bi->bi_op_delete = config_back_delete;
        bi->bi_op_abandon = 0;
 
        bi->bi_extended = 0;
@@ -5737,6 +5911,9 @@ config_back_initialize( BackendInfo *bi )
        bi->bi_connection_init = 0;
        bi->bi_connection_destroy = 0;
 
+       bi->bi_entry_release_rw = config_entry_release;
+       bi->bi_entry_get_rw = config_back_entry_get;
+
        bi->bi_tool_entry_open = config_tool_entry_open;
        bi->bi_tool_entry_close = config_tool_entry_close;
        bi->bi_tool_entry_first = config_tool_entry_first;