]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/bconfig.c
fix typo
[openldap] / servers / slapd / bconfig.c
index 6a6e56d61f4f28acc943c92c712edef099494c5d..60dd39362dccd71156d3950dd7a0d7b8463afa0a 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2005-2007 The OpenLDAP Foundation.
+ * Copyright 2005-2008 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -77,6 +77,7 @@ typedef struct {
 static CfBackInfo cfBackInfo;
 
 static char    *passwd_salt;
+static FILE *logfile;
 static char    *logfileName;
 #ifdef SLAP_AUTH_REWRITE
 static BerVarray authz_rewrites;
@@ -177,6 +178,8 @@ enum {
        CFG_HIDDEN,
        CFG_MONITORING,
        CFG_SERVERID,
+       CFG_SORTVALS,
+       CFG_IX_INTLEN,
 
        CFG_LAST
 };
@@ -186,8 +189,8 @@ typedef struct {
 } OidRec;
 
 static OidRec OidMacros[] = {
-       /* OpenLDAProot:666.11.1 */
-       { "OLcfg", "1.3.6.1.4.1.4203.666.11.1" },
+       /* OpenLDAProot:1.12.2 */
+       { "OLcfg", "1.3.6.1.4.1.4203.1.12.2" },
        { "OLcfgAt", "OLcfg:3" },
        { "OLcfgGlAt", "OLcfgAt:0" },
        { "OLcfgBkAt", "OLcfgAt:1" },
@@ -227,6 +230,7 @@ static OidRec OidMacros[] = {
  * OLcfg{Bk|Db}{Oc|At}:4               -> back-monitor
  * OLcfg{Bk|Db}{Oc|At}:5               -> back-relay
  * OLcfg{Bk|Db}{Oc|At}:6               -> back-sql
+ * OLcfg{Bk|Db}{Oc|At}:7               -> back-sock
  */
 
 /*
@@ -250,6 +254,7 @@ static OidRec OidMacros[] = {
  * OLcfgOv{Oc|At}:17                   -> dyngroup
  * OLcfgOv{Oc|At}:18                   -> memberof
  * OLcfgOv{Oc|At}:19                   -> collect
+ * OLcfgOv{Oc|At}:20                   -> retcode
  */
 
 /* alphabetical ordering */
@@ -370,6 +375,9 @@ static ConfigTable config_back_cf_table[] = {
        { "index_substr_any_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO,
                &index_substr_any_step, "( OLcfgGlAt:23 NAME 'olcIndexSubstrAnyStep' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+       { "index_intlen", "len", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_IX_INTLEN,
+               &config_generic, "( OLcfgGlAt:84 NAME 'olcIndexIntLen' "
+                       "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
        { "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD,
                &config_generic, "( OLcfgDbAt:0.4 NAME 'olcLastMod' "
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
@@ -494,6 +502,7 @@ static ConfigTable config_back_cf_table[] = {
                        "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
        { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_rootdn, "( OLcfgDbAt:0.8 NAME 'olcRootDN' "
+                       "EQUALITY distinguishedNameMatch "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE,
                &config_generic, "( OLcfgGlAt:51 NAME 'olcRootDSE' "
@@ -506,7 +515,7 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, NULL, NULL, NULL },
        { "sasl-host", "host", 2, 2, 0,
 #ifdef HAVE_CYRUS_SASL
-               ARG_STRING|ARG_UNIQUE, &global_host,
+               ARG_STRING|ARG_UNIQUE, &sasl_host,
 #else
                ARG_IGNORED, NULL,
 #endif
@@ -534,6 +543,7 @@ static ConfigTable config_back_cf_table[] = {
                &config_generic, NULL, NULL, NULL },
        { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
                &config_schema_dn, "( OLcfgGlAt:58 NAME 'olcSchemaDN' "
+                       "EQUALITY distinguishedNameMatch "
                        "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
        { "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
                &config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' "
@@ -552,6 +562,11 @@ static ConfigTable config_back_cf_table[] = {
        { "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T,
                &sockbuf_max_incoming_auth, "( OLcfgGlAt:62 NAME 'olcSockbufMaxIncomingAuth' "
                        "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
+       { "sortvals", "attr", 2, 0, 0, ARG_MAGIC|CFG_SORTVALS,
+               &config_generic, "( OLcfgGlAt:83 NAME 'olcSortVals' "
+                       "DESC 'Attributes whose values will always be sorted' "
+                       "EQUALITY caseIgnoreMatch "
+                       "SYNTAX OMsDirectoryString )", NULL, NULL },
        { "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC,
                &config_subordinate, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' "
                        "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
@@ -702,8 +717,8 @@ static ConfigOCs cf_ocs[] = {
                 "olcConnMaxPending $ olcConnMaxPendingAuth $ "
                 "olcDisallows $ olcGentleHUP $ olcIdleTimeout $ "
                 "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
-                "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcLocalSSF $ "
-                "olcLogLevel $ "
+                "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexIntLen $ "
+                "olcLocalSSF $ olcLogLevel $ "
                 "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
                 "olcPluginLogFile $ olcReadOnly $ olcReferral $ "
                 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
@@ -765,7 +780,7 @@ static ConfigOCs cf_ocs[] = {
                "NAME 'olcFrontendConfig' "
                "DESC 'OpenLDAP frontend configuration' "
                "AUXILIARY "
-               "MAY ( olcDefaultSearchBase $ olcPasswordHash ) )",
+               "MAY ( olcDefaultSearchBase $ olcPasswordHash $ olcSortVals ) )",
                Cft_Database, NULL, NULL },
 #ifdef SLAPD_MODULES
        { "( OLcfgGlOc:8 "
@@ -786,6 +801,18 @@ typedef struct ServerID {
 
 static ServerID *sid_list;
 
+typedef struct voidList {
+       struct voidList *vl_next;
+       void *vl_ptr;
+} voidList;
+
+typedef struct ADlist {
+       struct ADlist *al_next;
+       AttributeDescription *al_desc;
+} ADlist;
+
+static ADlist *sortVals;
+
 static int
 config_generic(ConfigArgs *c) {
        int i;
@@ -865,7 +892,7 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
                case CFG_OID: {
-                       ConfigFile *cf = c->private;
+                       ConfigFile *cf = c->ca_private;
                        if ( !cf )
                                oidm_unparse( &c->rvalue_vals, NULL, NULL, 1 );
                        else if ( cf->c_om_head )
@@ -879,7 +906,7 @@ config_generic(ConfigArgs *c) {
                        ad_unparse_options( &c->rvalue_vals );
                        break;
                case CFG_OC: {
-                       ConfigFile *cf = c->private;
+                       ConfigFile *cf = c->ca_private;
                        if ( !cf )
                                oc_unparse( &c->rvalue_vals, NULL, NULL, 1 );
                        else if ( cf->c_oc_head )
@@ -890,7 +917,7 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
                case CFG_ATTR: {
-                       ConfigFile *cf = c->private;
+                       ConfigFile *cf = c->ca_private;
                        if ( !cf )
                                at_unparse( &c->rvalue_vals, NULL, NULL, 1 );
                        else if ( cf->c_at_head )
@@ -901,7 +928,7 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
                case CFG_DIT: {
-                       ConfigFile *cf = c->private;
+                       ConfigFile *cf = c->ca_private;
                        if ( !cf )
                                cr_unparse( &c->rvalue_vals, NULL, NULL, 1 );
                        else if ( cf->c_cr_head )
@@ -916,7 +943,12 @@ config_generic(ConfigArgs *c) {
                        AccessControl *a;
                        char *src, *dst, ibuf[11];
                        struct berval bv, abv;
-                       for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) {
+                       AccessControl *end;
+                       if ( c->be == frontendDB )
+                               end = NULL;
+                       else
+                               end = frontendDB->be_acl;
+                       for (i=0, a=c->be->be_acl; a && a != end; i++,a=a->acl_next) {
                                abv.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i );
                                if ( abv.bv_len >= sizeof( ibuf ) ) {
                                        ber_bvarray_free_x( c->rvalue_vals, NULL );
@@ -944,7 +976,7 @@ config_generic(ConfigArgs *c) {
                        break;
                }
                case CFG_ROOTDSE: {
-                       ConfigFile *cf = c->private;
+                       ConfigFile *cf = c->ca_private;
                        if ( cf->c_dseFiles ) {
                                value_add( &c->rvalue_vals, cf->c_dseFiles );
                        } else {
@@ -1000,9 +1032,20 @@ config_generic(ConfigArgs *c) {
                case CFG_SSTR_IF_MIN:
                        c->value_int = index_substr_if_minlen;
                        break;
+               case CFG_IX_INTLEN:
+                       c->value_int = index_intlen;
+                       break;
+               case CFG_SORTVALS: {
+                       ADlist *sv;
+                       rc = 1;
+                       for ( sv = sortVals; sv; sv = sv->al_next ) {
+                               value_add_one( &c->rvalue_vals, &sv->al_desc->ad_cname );
+                               rc = 0;
+                       }
+                       } break;
 #ifdef SLAPD_MODULES
                case CFG_MODLOAD: {
-                       ModPaths *mp = c->private;
+                       ModPaths *mp = c->ca_private;
                        if (mp->mp_loads) {
                                int i;
                                for (i=0; !BER_BVISNULL(&mp->mp_loads[i]); i++) {
@@ -1024,7 +1067,7 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
                case CFG_MODPATH: {
-                       ModPaths *mp = c->private;
+                       ModPaths *mp = c->ca_private;
                        if ( !BER_BVISNULL( &mp->mp_path ))
                                value_add_one( &c->rvalue_vals, &mp->mp_path );
 
@@ -1103,6 +1146,10 @@ config_generic(ConfigArgs *c) {
                case CFG_LOGFILE:
                        ch_free( logfileName );
                        logfileName = NULL;
+                       if ( logfile ) {
+                               fclose( logfile );
+                               logfile = NULL;
+                       }
                        break;
 
                case CFG_SERVERID: {
@@ -1125,6 +1172,12 @@ config_generic(ConfigArgs *c) {
                        c->be->be_flags &= ~SLAP_DBFLAG_HIDDEN;
                        break;
 
+               case CFG_IX_INTLEN:
+                       index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
+                       index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
+                               SLAP_INDEX_INTLEN_DEFAULT );
+                       break;
+
                case CFG_ACL:
                        if ( c->valx < 0 ) {
                                AccessControl *end;
@@ -1159,7 +1212,7 @@ config_generic(ConfigArgs *c) {
                                        return 1;
                                }
                        }
-                       cfn = c->private;
+                       cfn = c->ca_private;
                        if ( c->valx < 0 ) {
                                ObjectClass *oc;
 
@@ -1197,7 +1250,7 @@ config_generic(ConfigArgs *c) {
                                        return 1;
                                }
                        }
-                       cfn = c->private;
+                       cfn = c->ca_private;
                        if ( c->valx < 0 ) {
                                AttributeType *at;
 
@@ -1224,6 +1277,27 @@ config_generic(ConfigArgs *c) {
                                }
                        }
                        break;
+               case CFG_SORTVALS:
+                       if ( c->valx < 0 ) {
+                               ADlist *sv;
+                               for ( sv = sortVals; sv; sv = sortVals ) {
+                                       sortVals = sv->al_next;
+                                       sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
+                                       ch_free( sv );
+                               }
+                       } else {
+                               ADlist *sv, **prev;
+                               int i = 0;
+
+                               for ( prev = &sortVals, sv = sortVals; i < c->valx; i++ ) {
+                                       prev = &sv->al_next;
+                                       sv = sv->al_next;
+                               }
+                               sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
+                               *prev = sv->al_next;
+                               ch_free( sv );
+                       }
+                       break;
 
                case CFG_LIMITS:
                        /* FIXME: there is no limits_free function */
@@ -1356,8 +1430,8 @@ config_generic(ConfigArgs *c) {
                case CFG_OID: {
                        OidMacro *om;
 
-                       if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
-                               cfn = c->private;
+                       if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
+                               cfn = c->ca_private;
                        if(parse_oidm(c, 1, &om))
                                return(1);
                        if (!cfn->c_om_head) cfn->c_om_head = om;
@@ -1368,8 +1442,8 @@ config_generic(ConfigArgs *c) {
                case CFG_OC: {
                        ObjectClass *oc, *prev;
 
-                       if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
-                               cfn = c->private;
+                       if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
+                               cfn = c->ca_private;
                        if ( c->valx < 0 ) {
                                prev = cfn->c_oc_tail;
                        } else {
@@ -1400,8 +1474,8 @@ config_generic(ConfigArgs *c) {
                case CFG_ATTR: {
                        AttributeType *at, *prev;
 
-                       if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
-                               cfn = c->private;
+                       if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
+                               cfn = c->ca_private;
                        if ( c->valx < 0 ) {
                                prev = cfn->c_at_tail;
                        } else {
@@ -1432,8 +1506,8 @@ config_generic(ConfigArgs *c) {
                case CFG_DIT: {
                        ContentRule *cr;
 
-                       if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
-                               cfn = c->private;
+                       if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
+                               cfn = c->ca_private;
                        if(parse_cr(c, &cr)) return(1);
                        if (!cfn->c_cr_head) cfn->c_cr_head = cr;
                        cfn->c_cr_tail = cr;
@@ -1447,6 +1521,63 @@ config_generic(ConfigArgs *c) {
                                        return(1);
                        break;
 
+               case CFG_IX_INTLEN:
+                       if ( c->value_int < SLAP_INDEX_INTLEN_DEFAULT )
+                               c->value_int = SLAP_INDEX_INTLEN_DEFAULT;
+                       else if ( c->value_int > 255 )
+                               c->value_int = 255;
+                       index_intlen = c->value_int;
+                       index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
+                               index_intlen );
+                       break;
+                       
+               case CFG_SORTVALS: {
+                       ADlist *svnew = NULL, *svtail, *sv;
+
+                       for ( i = 1; i < c->argc; i++ ) {
+                               AttributeDescription *ad = NULL;
+                               const char *text;
+                               int rc;
+
+                               rc = slap_str2ad( c->argv[i], &ad, &text );
+                               if ( rc ) {
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown attribute type #%d",
+                                               c->argv[0], i );
+sortval_reject:
+                                       Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+                                               c->log, c->cr_msg, c->argv[i] );
+                                       for ( sv = svnew; sv; sv = svnew ) {
+                                               svnew = sv->al_next;
+                                               ch_free( sv );
+                                       }
+                                       return 1;
+                               }
+                               if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) ||
+                                       ad->ad_type->sat_single_value ) {
+                                       snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> inappropriate attribute type #%d",
+                                               c->argv[0], i );
+                                       goto sortval_reject;
+                               }
+                               sv = ch_malloc( sizeof( ADlist ));
+                               sv->al_desc = ad;
+                               if ( !svnew ) {
+                                       svnew = sv;
+                               } else {
+                                       svtail->al_next = sv;
+                               }
+                               svtail = sv;
+                       }
+                       sv->al_next = NULL;
+                       for ( sv = svnew; sv; sv = sv->al_next )
+                               sv->al_desc->ad_type->sat_flags |= SLAP_AT_SORTED_VAL;
+                       for ( sv = sortVals; sv && sv->al_next; sv = sv->al_next );
+                       if ( sv )
+                               sv->al_next = svnew;
+                       else
+                               sortVals = svnew;
+                       }
+                       break;
+
                case CFG_ACL:
                        /* Don't append to the global ACL if we're on a specific DB */
                        i = c->valx;
@@ -1472,8 +1603,8 @@ config_generic(ConfigArgs *c) {
                        {
                                struct berval bv;
                                ber_str2bv( c->argv[1], 0, 1, &bv );
-                               if ( c->op == LDAP_MOD_ADD && c->private && cfn != c->private )
-                                       cfn = c->private;
+                               if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
+                                       cfn = c->ca_private;
                                ber_bvarray_add( &cfn->c_dseFiles, &bv );
                        }
                        break;
@@ -1548,7 +1679,7 @@ config_generic(ConfigArgs *c) {
                                                Listener **l = slapd_get_listeners();
                                                int i;
 
-                                               for ( i=0; l[i]; i++ ) {
+                                               for ( i=0; l && l[i]; i++ ) {
                                                        LDAPURLDesc *lu2;
                                                        int isMe = 0;
                                                        ldap_url_parse( l[i]->sl_url.bv_val, &lu2 );
@@ -1594,7 +1725,6 @@ config_generic(ConfigArgs *c) {
                        }
                        break;
                case CFG_LOGFILE: {
-                               FILE *logfile;
                                if ( logfileName ) ch_free( logfileName );
                                logfileName = c->value_string;
                                logfile = fopen(logfileName, "w");
@@ -1668,8 +1798,8 @@ config_generic(ConfigArgs *c) {
                        /* If we're just adding a module on an existing modpath,
                         * make sure we've selected the current path.
                         */
-                       if ( c->op == LDAP_MOD_ADD && c->private && modcur != c->private ) {
-                               modcur = c->private;
+                       if ( c->op == LDAP_MOD_ADD && c->ca_private && modcur != c->ca_private ) {
+                               modcur = c->ca_private;
                                /* This should never fail */
                                if ( module_path( modcur->mp_path.bv_val )) {
                                        snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> module path no longer valid",
@@ -1717,7 +1847,7 @@ config_generic(ConfigArgs *c) {
                                mp->mp_next = NULL;
                                mp->mp_loads = NULL;
                                modlast = mp;
-                               c->private = mp;
+                               c->ca_private = mp;
                                modcur = mp;
                        }
                        
@@ -1776,8 +1906,8 @@ config_generic(ConfigArgs *c) {
 static int
 config_fname(ConfigArgs *c) {
        if(c->op == SLAP_CONFIG_EMIT) {
-               if (c->private) {
-                       ConfigFile *cf = c->private;
+               if (c->ca_private) {
+                       ConfigFile *cf = c->ca_private;
                        value_add_one( &c->rvalue_vals, &cf->c_file );
                        return 0;
                }
@@ -2013,13 +2143,13 @@ config_overlay(ConfigArgs *c) {
                assert(0);
        }
        if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1],
-               c->valx, &c->bi)) {
+               c->valx, &c->bi, &c->reply)) {
                /* log error */
                Debug( LDAP_DEBUG_ANY,
                        "%s: (optional) %s overlay \"%s\" configuration failed.\n",
                        c->log, c->be == frontendDB ? "global " : "", &c->argv[1][1]);
                return 1;
-       } else if(overlay_config(c->be, c->argv[1], c->valx, &c->bi)) {
+       } else if(overlay_config(c->be, c->argv[1], c->valx, &c->bi, &c->reply)) {
                return(1);
        }
        return(0);
@@ -2151,8 +2281,17 @@ config_suffix(ConfigArgs *c)
        }
 #endif
 
+       if (SLAP_DB_ONE_SUFFIX( c->be ) && c->be->be_suffix ) {
+               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> Only one suffix is allowed on this %s backend",
+                       c->argv[0], c->be->bd_info->bi_type );
+               Debug(LDAP_DEBUG_ANY, "%s: %s\n",
+                       c->log, c->cr_msg, 0);
+               return(1);
+       }
+
        pdn = c->value_dn;
        ndn = c->value_ndn;
+
        if (SLAP_DBHIDDEN( c->be ))
                tbe = NULL;
        else
@@ -2909,7 +3048,7 @@ config_include(ConfigArgs *c) {
                ch_free( cf->c_file.bv_val );
                ch_free( cf );
        } else {
-               c->private = cf;
+               c->ca_private = cf;
        }
        return(rc);
 }
@@ -3743,7 +3882,7 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
                if ( isconfig && index == -1 ) {
                        index = 0;
                }
-               if ( !isfrontend && index == -1 ) {
+               if (( !isfrontend && index == -1 ) || ( index > nsibs ) ){
                        index = nsibs;
                }
 
@@ -3834,14 +3973,14 @@ cfAddSchema( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
        /* This entry is hardcoded, don't re-parse it */
        if ( p->ce_type == Cft_Global ) {
                cfn = p->ce_private;
-               ca->private = cfn;
+               ca->ca_private = cfn;
                return LDAP_COMPARE_TRUE;
        }
        if ( p->ce_type != Cft_Schema )
                return LDAP_CONSTRAINT_VIOLATION;
 
        cfn = ch_calloc( 1, sizeof(ConfigFile) );
-       ca->private = cfn;
+       ca->ca_private = cfn;
        cfo = p->ce_private;
        cfn->c_sibs = cfo->c_kids;
        cfo->c_kids = cfn;
@@ -3854,6 +3993,11 @@ cfAddDatabase( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
        if ( p->ce_type != Cft_Global ) {
                return LDAP_CONSTRAINT_VIOLATION;
        }
+       /* config must be {0}, nothing else allowed */
+       if ( !strncmp( e->e_nname.bv_val, "olcDatabase={0}", STRLENOF("olcDatabase={0}")) &&
+               strncmp( e->e_nname.bv_val + STRLENOF("olcDatabase={0}"), "config,", STRLENOF("config,") )) {
+               return LDAP_CONSTRAINT_VIOLATION;
+       }
        ca->be = frontendDB;    /* just to get past check_vals */
        return LDAP_SUCCESS;
 }
@@ -4093,16 +4237,31 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
        rc = LDAP_CONSTRAINT_VIOLATION;
        if ( coptr->co_type == Cft_Global && !last ) {
                cfn = cfb->cb_config;
-               ca->private = cfn;
+               ca->ca_private = cfn;
                ca->be = frontendDB;    /* just to get past check_vals */
                rc = LDAP_SUCCESS;
        }
 
+       colst = count_ocs( oc_at, &nocs );
+
        /* Check whether the Add is allowed by its parent, and do
         * any necessary arg setup
         */
        if ( last ) {
                rc = config_add_oc( &coptr, last, e, ca );
+               if ( rc == LDAP_CONSTRAINT_VIOLATION ) {
+                       for ( i = 0; i<nocs; i++ ) {
+                               /* Already checked these */
+                               if ( colst[i]->co_oc->soc_kind == LDAP_SCHEMA_STRUCTURAL )
+                                       continue;
+                               if ( colst[i]->co_ldadd &&
+                                       ( rc = colst[i]->co_ldadd( last, e, ca ))
+                                               != LDAP_CONSTRAINT_VIOLATION ) {
+                                       coptr = colst[i];
+                                       break;
+                               }
+                       }
+               }
                if ( rc == LDAP_CONSTRAINT_VIOLATION ) {
                        Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
                                "DN=\"%s\" no structural objectClass add function\n",
@@ -4111,8 +4270,6 @@ config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
                }
        }
 
-       colst = count_ocs( oc_at, &nocs );
-
        /* Add the entry but don't parse it, we already have its contents */
        if ( rc == LDAP_COMPARE_TRUE ) {
                rc = LDAP_SUCCESS;
@@ -4211,6 +4368,8 @@ ok:
                                rc = ca->bi->bi_db_open( ca->be, &ca->reply );
                                ca->be->bd_info = bi_orig;
                        }
+               } else if ( ca->cleanup ) {
+                       rc = ca->cleanup( ca );
                }
                if ( rc ) {
                        if (ca->cr_msg[0] == '\0')
@@ -4231,7 +4390,7 @@ ok:
        ce->ce_type = colst[0]->co_type;
        ce->ce_be = ca->be;
        ce->ce_bi = ca->bi;
-       ce->ce_private = ca->private;
+       ce->ce_private = ca->ca_private;
        ca->ca_entry = ce->ce_entry;
        if ( !last ) {
                cfb->cb_root = ce;
@@ -4514,7 +4673,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
        init_config_argv( ca );
        ca->be = ce->ce_be;
        ca->bi = ce->ce_bi;
-       ca->private = ce->ce_private;
+       ca->ca_private = ce->ce_private;
        ca->ca_entry = e;
        ca->fname = "slapd";
        ca->ca_op = op;
@@ -4544,7 +4703,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                         */
                        if ( ct && ml->sml_values ) {
                                delrec *d;
-                               for (i=0; ml->sml_values[i].bv_val; i++);
+                               i = ml->sml_numvals;
                                d = ch_malloc( sizeof(delrec) + (i - 1)* sizeof(int));
                                d->nidx = i;
                                d->next = NULL;
@@ -4577,8 +4736,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                                if ( ct->arg_type & ARG_NO_INSERT ) {
                                        Attribute *a = attr_find( e->e_attrs, ml->sml_desc );
                                        if ( a ) {
-                                               for (i = 0; a->a_vals[i].bv_val; i++ );
-                                               navals = i;
+                                               navals = a->a_numvals;
                                        }
                                }
                                for ( i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++ ) {
@@ -4630,8 +4788,9 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
                /* check that the entry still obeys the schema */
                rc = entry_schema_check(op, e, NULL, 0, 0,
                        &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) );
-               if ( rc ) goto out_noop;
        }
+       if ( rc ) goto out_noop;
+
        /* Basic syntax checks are OK. Do the actual settings. */
        for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
                ct = config_find_table( colst, nocs, ml->sml_desc, ca );
@@ -4723,6 +4882,7 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
 out:
        /* Undo for a failed operation */
        if ( rc != LDAP_SUCCESS ) {
+               ConfigReply msg = ca->reply;
                for ( s = save_attrs; s; s = s->a_next ) {
                        if ( s->a_flags & SLAP_ATTR_IXDEL ) {
                                s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
@@ -4759,6 +4919,7 @@ out:
                                }
                        }
                }
+               ca->reply = msg;
        }
 
        if ( ca->cleanup )
@@ -4791,6 +4952,7 @@ config_back_modify( Operation *op, SlapReply *rs )
        struct berval rdn;
        char *ptr;
        AttributeDescription *rad = NULL;
+       int do_pause = 1;
 
        cfb = (CfBackInfo *)op->o_bd->be_private;
 
@@ -4821,11 +4983,16 @@ config_back_modify( Operation *op, SlapReply *rs )
                        rs->sr_text = "Use modrdn to change the entry name";
                        goto out;
                }
+               /* Internal update of contextCSN? */
+               if ( ml->sml_desc == slap_schema.si_ad_contextCSN && op->o_conn->c_conn_idx == -1 ) {
+                       do_pause = 0;
+                       break;
+               }
        }
 
        slap_mods_opattrs( op, &op->orm_modlist, 1 );
 
-       if ( !slapd_shutdown )
+       if ( do_pause )
                ldap_pvt_thread_pool_pause( &connection_pool );
 
        /* Strategy:
@@ -4858,7 +5025,7 @@ config_back_modify( Operation *op, SlapReply *rs )
                op->o_ndn = ndn;
        }
 
-       if ( !slapd_shutdown )
+       if ( do_pause )
                ldap_pvt_thread_pool_resume( &connection_pool );
 out:
        send_ldap_result( op, rs );
@@ -5066,7 +5233,102 @@ out:
 static int
 config_back_delete( Operation *op, SlapReply *rs )
 {
-       send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, NULL );
+#ifdef SLAP_CONFIG_DELETE
+       CfBackInfo *cfb;
+       CfEntryInfo *ce, *last, *ce2;
+
+       cfb = (CfBackInfo *)op->o_bd->be_private;
+
+       ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last );
+       if ( !ce ) {
+               if ( last )
+                       rs->sr_matched = last->ce_entry->e_name.bv_val;
+               rs->sr_err = LDAP_NO_SUCH_OBJECT;
+       } else if ( ce->ce_kids ) {
+               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+       } else if ( ce->ce_type == Cft_Overlay || ce->ce_type == Cft_Database ){
+               char *iptr;
+               int count, ixold;
+
+               ldap_pvt_thread_pool_pause( &connection_pool );
+
+               if ( ce->ce_type == Cft_Overlay ){
+                       overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi );
+               } else { /* Cft_Database*/
+                       if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){
+                               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+                               rs->sr_text = "Cannot delete config or frontend database";
+                               ldap_pvt_thread_pool_resume( &connection_pool );
+                               goto out;
+                       } 
+                       if ( ce->ce_be->bd_info->bi_db_close ) {
+                               ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL );
+                       }
+                       backend_destroy_one( ce->ce_be, 1);
+               }
+
+               /* remove CfEntryInfo from the siblings list */
+               if ( ce->ce_parent->ce_kids == ce ) {
+                       ce->ce_parent->ce_kids = ce->ce_sibs;
+               } else {
+                       for ( ce2 = ce->ce_parent->ce_kids ; ce2; ce2 = ce2->ce_sibs ) {
+                               if ( ce2->ce_sibs == ce ) {
+                                       ce2->ce_sibs = ce->ce_sibs;
+                                       break;
+                               }
+                       }
+               }
+
+               /* remove from underlying database */
+               if ( cfb->cb_use_ldif ) {
+                       BackendDB *be = op->o_bd;
+                       slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
+                       struct berval dn, ndn, req_dn, req_ndn;
+
+                       op->o_bd = &cfb->cb_db;
+
+                       dn = op->o_dn;
+                       ndn = op->o_ndn;
+                       req_dn = op->o_req_dn;
+                       req_ndn = op->o_req_ndn;
+
+                       op->o_dn = op->o_bd->be_rootdn;
+                       op->o_ndn = op->o_bd->be_rootndn;
+                       op->o_req_dn = ce->ce_entry->e_name;
+                       op->o_req_ndn = ce->ce_entry->e_nname;
+
+                       scp = op->o_callback;
+                       op->o_callback = &sc;
+                       op->o_bd->be_delete( op, rs );
+                       op->o_bd = be;
+                       op->o_callback = scp;
+                       op->o_dn = dn;
+                       op->o_ndn = ndn;
+                       op->o_req_dn = req_dn;
+                       op->o_req_ndn = req_ndn;
+               }
+
+               /* renumber siblings */
+               iptr = ber_bvchr( &op->o_req_ndn, '{' ) + 1;
+               ixold = strtol( iptr, NULL, 0 );
+               for (ce2 = ce->ce_sibs, count=0; ce2; ce2=ce2->ce_sibs) {
+                       config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
+                               count+ixold, 0, cfb->cb_use_ldif );
+                       count++;
+               }
+
+               ce->ce_entry->e_private=NULL;
+               entry_free(ce->ce_entry);
+               ch_free(ce);
+               ldap_pvt_thread_pool_resume( &connection_pool );
+       } else {
+               rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+       }
+#else
+       rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
+#endif /* SLAP_CONFIG_DELETE */
+out:
+       send_ldap_result( op, rs );
        return rs->sr_err;
 }
 
@@ -5139,18 +5401,23 @@ int config_back_entry_get(
 {
        CfBackInfo *cfb;
        CfEntryInfo *ce, *last;
+       int rc = LDAP_NO_SUCH_OBJECT;
 
        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;
+               if ( *ent ) {
+                       rc = LDAP_SUCCESS;
+                       if ( oc && !is_entry_objectclass_or_sub( *ent, oc ) ) {
+                               rc = LDAP_NO_SUCH_ATTRIBUTE;
+                               *ent = NULL;
+                       }
                }
        }
 
-       return ( *ent == NULL ? 1 : 0 );
+       return rc;
 }
 
 static void
@@ -5208,7 +5475,7 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
        ce->ce_parent = parent;
        if ( parent ) {
                pdn = parent->ce_entry->e_nname;
-               if ( parent->ce_kids )
+               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 );
@@ -5216,7 +5483,7 @@ config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
                BER_BVZERO( &pdn );
        }
 
-       ce->ce_private = c->private;
+       ce->ce_private = c->ca_private;
        ce->ce_be = c->be;
        ce->ce_bi = c->bi;
 
@@ -5260,14 +5527,23 @@ 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->cr_msg,
                sizeof(c->cr_msg), op ? op->o_tmpmemctx : NULL );
+       if ( rc != LDAP_SUCCESS ) {
+               Debug( LDAP_DEBUG_ANY,
+                       "config_build_entry: build \"%s\" failed: \"%s\"\n",
+                       rdn->bv_val, text, 0);
+               return NULL;
+       }
        attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL );
-       if ( op && !op->o_noop ) {
+       if ( op ) {
                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) ) {
-                       return NULL;
+               slap_add_opattrs( op, NULL, NULL, 0, 0 );
+               if ( !op->o_noop ) {
+                       op->o_bd->be_add( op, rs );
+                       if ( ( rs->sr_err != LDAP_SUCCESS ) 
+                                       && (rs->sr_err != LDAP_ALREADY_EXISTS) ) {
+                               return NULL;
+                       }
                }
        }
        if ( ceprev ) {
@@ -5286,7 +5562,7 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent,
        Operation *op, SlapReply *rs )
 {
        Entry *e;
-       ConfigFile *cf = c->private;
+       ConfigFile *cf = c->ca_private;
        char *ptr;
        struct berval bv;
 
@@ -5315,13 +5591,13 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent,
                c->value_dn.bv_len += bv.bv_len;
                c->value_dn.bv_val[c->value_dn.bv_len] ='\0';
 
-               c->private = cf;
+               c->ca_private = cf;
                e = config_build_entry( op, rs, ceparent, c, &c->value_dn,
                        &CFOC_SCHEMA, NULL );
                if ( !e ) {
                        return -1;
                } else if ( e && cf->c_kids ) {
-                       c->private = cf->c_kids;
+                       c->ca_private = cf->c_kids;
                        config_build_schema_inc( c, e->e_private, op, rs );
                }
        }
@@ -5346,7 +5622,7 @@ config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent,
                        /* FIXME: how can indicate error? */
                        return -1;
                }
-               c->private = mp;
+               c->ca_private = mp;
                if ( ! config_build_entry( op, rs, ceparent, c, &c->value_dn, &CFOC_MODULE, NULL )) {
                        return -1;
                }
@@ -5423,7 +5699,7 @@ config_check_schema(Operation *op, CfBackInfo *cfb)
                }
        } else {
                SlapReply rs = {REP_RESULT};
-               c.private = NULL;
+               c.ca_private = NULL;
                e = config_build_entry( op, &rs, cfb->cb_root, &c, &schema_rdn,
                        &CFOC_SCHEMA, NULL );
                if ( !e ) {
@@ -5489,7 +5765,7 @@ config_back_db_open( BackendDB *be, ConfigReply *cr )
 
        /* create root of tree */
        rdn = config_rdn;
-       c.private = cfb->cb_config;
+       c.ca_private = cfb->cb_config;
        c.be = frontendDB;
        e = config_build_entry( op, &rs, NULL, &c, &rdn, &CFOC_GLOBAL, NULL );
        if ( !e ) {
@@ -5515,7 +5791,7 @@ config_back_db_open( BackendDB *be, ConfigReply *cr )
         * files.
         */
        rdn = schema_rdn;
-       c.private = NULL;
+       c.ca_private = NULL;
        e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_SCHEMA, NULL );
        if ( !e ) {
                return -1;
@@ -5529,7 +5805,7 @@ config_back_db_open( BackendDB *be, ConfigReply *cr )
        /* Create schema nodes for included schema... */
        if ( cfb->cb_config->c_kids ) {
                c.depth = 0;
-               c.private = cfb->cb_config->c_kids;
+               c.ca_private = cfb->cb_config->c_kids;
                if (config_build_schema_inc( &c, ce, op, &rs )) {
                        return -1;
                }
@@ -5612,8 +5888,19 @@ config_back_db_open( BackendDB *be, ConfigReply *cr )
                        slap_overinst *on;
                        Entry *oe;
                        int j;
-
-                       for (j=0,on=oi->oi_list; on; j++,on=on->on_next) {
+                       voidList *vl, *v0 = NULL;
+
+                       /* overlays are in LIFO order, must reverse stack */
+                       for (on=oi->oi_list; on; on=on->on_next) {
+                               vl = ch_malloc( sizeof( voidList ));
+                               vl->vl_next = v0;
+                               v0 = vl;
+                               vl->vl_ptr = on;
+                       }
+                       for (j=0; vl; j++,vl=v0) {
+                               on = vl->vl_ptr;
+                               v0 = vl->vl_next;
+                               ch_free( vl );
                                if ( on->on_bi.bi_db_config && !on->on_bi.bi_cf_ocs ) {
                                        Debug( LDAP_DEBUG_ANY,
                                                "WARNING: No dynamic config support for overlay %s.\n",
@@ -5827,6 +6114,7 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
        Connection conn = {0};
        Operation *op = NULL;
        void *thrctx;
+       int isFrontend = 0;
 
        /* Create entry for frontend database if it does not exist already */
        if ( !entry_put_got_frontend ) {
@@ -5876,11 +6164,12 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
                                }
                        } else {
                                entry_put_got_frontend++;
+                               isFrontend = 1;
                        }
                }
        }
        /* Create entry for config database if it does not exist already */
-       if ( !entry_put_got_config ) {
+       if ( !entry_put_got_config && !isFrontend ) {
                if ( !strncmp( e->e_nname.bv_val, "olcDatabase",
                                STRLENOF( "olcDatabase" ))) {
                        if ( strncmp( e->e_nname.bv_val +