X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbconfig.c;h=d050122be294e76f174044fb3474f2d60a8f41bb;hb=5631f25839a4a83521993639a96909267ea7bce6;hp=c6588f9699654a34e61a728380642a867716e4c9;hpb=37ed2af7e7407a0a47ef112e905c4f01702703c1;p=openldap diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index c6588f9699..d050122be2 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -32,6 +32,7 @@ #include "slapi/slapi.h" #endif +#include #include #include "config.h" @@ -78,7 +79,9 @@ static int replicationInterval; static char *passwd_salt; static char *logfileName; +#ifdef SLAP_AUTH_REWRITE static BerVarray authz_rewrites; +#endif static struct berval cfdir; @@ -86,12 +89,12 @@ static struct berval cfdir; static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay, *cfAd_include; -static ConfigFile cf_prv, *cfn = &cf_prv; +static ConfigFile *cfn; static Avlnode *CfOcTree; -static int config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, - int *renumber ); +static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, + SlapReply *rs, int *renumber ); static ConfigDriver config_fname; static ConfigDriver config_cfdir; @@ -103,7 +106,6 @@ static ConfigDriver config_sizelimit; static ConfigDriver config_timelimit; static ConfigDriver config_overlay; static ConfigDriver config_suffix; -static ConfigDriver config_deref_depth; static ConfigDriver config_rootdn; static ConfigDriver config_rootpw; static ConfigDriver config_restrict; @@ -147,7 +149,6 @@ enum { CFG_DIT, CFG_ATTR, CFG_ATOPT, - CFG_CHECK, CFG_REPLOG, CFG_ROOTDSE, CFG_LOGFILE, @@ -160,6 +161,8 @@ enum { CFG_SASLSECP, CFG_SSTR_IF_MAX, CFG_SSTR_IF_MIN, + + CFG_LAST }; typedef struct { @@ -224,6 +227,10 @@ static ConfigTable config_back_cf_table[] = { "DESC 'File for slapd command line options' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, + { "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT, + &config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' " + "EQUALITY caseIgnoreMatch " + "SYNTAX OMsDirectoryString )", NULL, NULL }, { "attribute", "attribute", 2, 0, 9, ARG_PAREN|ARG_MAGIC|CFG_ATTR|ARG_NO_DELETE|ARG_NO_INSERT, &config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' " @@ -231,11 +238,7 @@ static ConfigTable config_back_cf_table[] = { "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL }, - { "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT, - &config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' " - "EQUALITY caseIgnoreMatch " - "SYNTAX OMsDirectoryString )", NULL, NULL }, - { "authid-rewrite", NULL, 2, 0, 0, + { "authid-rewrite", NULL, 2, 0, STRLENOF( "authid-rewrite" ), #ifdef SLAP_AUTH_REWRITE ARG_MAGIC|CFG_REWRITE|ARG_NO_INSERT, &config_generic, #else @@ -271,7 +274,7 @@ static ConfigTable config_back_cf_table[] = { &config_generic, "( OLcfgGlAt:13 NAME 'olcDatabase' " "DESC 'The backend type for a database instance' " "SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, - { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_MAGIC, + { "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, &config_search_base, "( OLcfgGlAt:14 NAME 'olcDefaultSearchBase' " "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, { "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC, @@ -307,7 +310,7 @@ static ConfigTable config_back_cf_table[] = { { "index_substr_any_len", "len", 2, 2, 0, ARG_INT|ARG_NONZERO, &index_substr_any_len, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' " "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, - { "index_substr_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO, + { "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 }, { "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD, @@ -416,7 +419,7 @@ static ConfigTable config_back_cf_table[] = { #endif "( OLcfgGlAt:49 NAME 'olcReverseLookup' " "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, - { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC, + { "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, &config_rootdn, "( OLcfgDbAt:0.8 NAME 'olcRootDN' " "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, { "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE, @@ -455,10 +458,7 @@ static ConfigTable config_back_cf_table[] = { "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, { "saslRegexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP, &config_generic, NULL, NULL, NULL }, - { "schemacheck", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_CHECK, - &config_generic, "( OLcfgGlAt:57 NAME 'olcSchemaCheck' " - "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, - { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_MAGIC, + { "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, &config_schema_dn, "( OLcfgGlAt:58 NAME 'olcSchemaDN' " "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, { "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC, @@ -481,7 +481,7 @@ static ConfigTable config_back_cf_table[] = { #endif "( OLcfgGlAt:63 NAME 'olcSrvtab' " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, - { "suffix", "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_MAGIC, + { "suffix", "suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, &config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' " "SYNTAX OMsDN )", NULL, NULL }, { "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC, @@ -559,7 +559,7 @@ static ConfigTable config_back_cf_table[] = { "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, { "ucdata-path", "path", 2, 2, 0, ARG_IGNORED, NULL, NULL, NULL, NULL }, - { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_MAGIC, + { "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC, &config_updatedn, "( OLcfgDbAt:0.12 NAME 'olcUpdateDN' " "SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL }, { "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC, @@ -573,20 +573,25 @@ static ConfigTable config_back_cf_table[] = { static ConfigLDAPadd cfAddSchema, cfAddInclude, cfAddDatabase, cfAddBackend, cfAddModule, cfAddOverlay; +/* NOTE: be careful when defining array members + * that can be conditionally compiled */ #define CFOC_GLOBAL cf_ocs[1] #define CFOC_SCHEMA cf_ocs[2] #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_MODULE cf_ocs[7] +#define CFOC_FRONTEND cf_ocs[7] +#ifdef SLAPD_MODULES +#define CFOC_MODULE cf_ocs[8] +#endif /* SLAPD_MODULES */ static ConfigOCs cf_ocs[] = { - { "( OLcfgGlOc:1 " + { "( OLcfgGlOc:0 " "NAME 'olcConfig' " "DESC 'OpenLDAP configuration object' " "ABSTRACT SUP top )", Cft_Abstract, NULL }, - { "( OLcfgGlOc:2 " + { "( OLcfgGlOc:1 " "NAME 'olcGlobal' " "DESC 'OpenLDAP Global configuration options' " "SUP olcConfig STRUCTURAL " @@ -602,9 +607,9 @@ static ConfigOCs cf_ocs[] = { "olcPluginLogFile $ olcReadOnly $ olcReferral $ " "olcReplicaPidFile $ olcReplicaArgsFile $ olcReplicationInterval $ " "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ " - "olcRootDSE $ olcRootPW $ " + "olcRootDSE $ " "olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ " - "olcSchemaCheck $ olcSecurity $ olcSizeLimit $ " + "olcSecurity $ olcSizeLimit $ " "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ olcSrvtab $ " "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ " "olcTLSCACertificatePath $ olcTLSCertificateFile $ " @@ -612,19 +617,19 @@ static ConfigOCs cf_ocs[] = { "olcTLSRandFile $ olcTLSVerifyClient $ " "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ " "olcDitContentRules ) )", Cft_Global }, - { "( OLcfgGlOc:3 " + { "( OLcfgGlOc:2 " "NAME 'olcSchemaConfig' " "DESC 'OpenLDAP schema object' " "SUP olcConfig STRUCTURAL " "MAY ( cn $ olcObjectIdentifier $ olcAttributeTypes $ " "olcObjectClasses $ olcDitContentRules ) )", Cft_Schema, NULL, cfAddSchema }, - { "( OLcfgGlOc:4 " + { "( OLcfgGlOc:3 " "NAME 'olcBackendConfig' " "DESC 'OpenLDAP Backend-specific options' " "SUP olcConfig STRUCTURAL " "MUST olcBackend )", Cft_Backend, NULL, cfAddBackend }, - { "( OLcfgGlOc:5 " + { "( OLcfgGlOc:4 " "NAME 'olcDatabaseConfig' " "DESC 'OpenLDAP Database-specific options' " "SUP olcConfig STRUCTURAL " @@ -635,25 +640,35 @@ static ConfigOCs cf_ocs[] = { "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncrepl $ " "olcTimeLimit $ olcUpdateDN $ olcUpdateRef ) )", Cft_Database, NULL, cfAddDatabase }, - { "( OLcfgGlOc:6 " + { "( OLcfgGlOc:5 " "NAME 'olcOverlayConfig' " "DESC 'OpenLDAP Overlay-specific options' " "SUP olcConfig STRUCTURAL " "MUST olcOverlay )", Cft_Overlay, NULL, cfAddOverlay }, - { "( OLcfgGlOc:7 " + { "( 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. + */ + { "( OLcfgGlOc:7 " + "NAME 'olcFrontendConfig' " + "DESC 'OpenLDAP frontend configuration' " + "AUXILIARY " + "MAY olcDefaultSearchBase )", + Cft_Database, NULL, NULL }, #ifdef SLAPD_MODULES { "( OLcfgGlOc:8 " "NAME 'olcModuleList' " "DESC 'OpenLDAP dynamic module info' " "SUP olcConfig STRUCTURAL " - "MUST ( olcModulePath $ olcModuleLoad ) " - "MAY cn )", Cft_Module, NULL, cfAddModule }, + "MAY ( cn $ olcModulePath $ olcModuleLoad ) )", + Cft_Module, NULL, cfAddModule }, #endif { NULL, 0, NULL } }; @@ -696,7 +711,8 @@ config_generic(ConfigArgs *c) { if ( !c->rvalue_vals ) rc = 1; break; case CFG_RO: - c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_OP_WRITES) != 0; + c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_OP_WRITES) == + SLAP_RESTRICT_OP_WRITES; break; case CFG_AZPOLICY: c->value_string = ch_strdup( slap_sasl_getpolicy()); @@ -765,9 +781,6 @@ config_generic(ConfigArgs *c) { } break; - case CFG_CHECK: - c->value_int = global_schemacheck; - break; case CFG_ACL: { AccessControl *a; char *src, *dst, ibuf[11]; @@ -840,7 +853,8 @@ config_generic(ConfigArgs *c) { break; case CFG_MODPATH: { ModPaths *mp = c->private; - value_add_one( &c->rvalue_vals, &mp->mp_path ); + if ( !BER_BVISNULL( &mp->mp_path )) + value_add_one( &c->rvalue_vals, &mp->mp_path ); rc = c->rvalue_vals ? 0 : 1; } @@ -885,7 +899,6 @@ config_generic(ConfigArgs *c) { case CFG_RO: case CFG_AZPOLICY: case CFG_DEPTH: - case CFG_CHECK: case CFG_LASTMOD: case CFG_SASLSECP: case CFG_SSTR_IF_MAX: @@ -976,11 +989,14 @@ config_generic(ConfigArgs *c) { c->be = LDAP_STAILQ_FIRST(&backendDB); } else if ( !strcasecmp( c->argv[1], "frontend" )) { c->be = frontendDB; - } else if(!(c->be = backend_db_init(c->argv[1]))) { - sprintf( c->msg, "<%s> failed init", c->argv[0] ); - Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", - c->log, c->msg, c->argv[1] ); - return(1); + } else { + c->be = backend_db_init(c->argv[1]); + if ( !c->be ) { + sprintf( c->msg, "<%s> failed init", c->argv[0] ); + Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", + c->log, c->msg, c->argv[1] ); + return(1); + } } break; @@ -1088,15 +1104,6 @@ config_generic(ConfigArgs *c) { return(1); break; - case CFG_CHECK: -#if 0 - global_schemacheck = c->value_int; - if(!global_schemacheck) Debug(LDAP_DEBUG_ANY, "%s: " - "schema checking disabled! your mileage may vary!\n", - c->log, 0, 0); -#endif - break; - case CFG_ACL: parse_acl(c->be, c->fname, c->lineno, c->argc, c->argv, c->valx); break; @@ -1171,21 +1178,35 @@ config_generic(ConfigArgs *c) { #ifdef SLAPD_MODULES case CFG_MODLOAD: + /* 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; + /* This should never fail */ + if ( module_path( modcur->mp_path.bv_val )) { + sprintf( c->msg, "<%s> module path no longer valid", + c->argv[0] ); + Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", + c->log, c->msg, modcur->mp_path.bv_val ); + return(1); + } + } if(module_load(c->argv[1], c->argc - 2, (c->argc > 2) ? c->argv + 2 : NULL)) return(1); /* Record this load on the current path */ { struct berval bv; - ModPaths *mp; - char *ptr = c->line + STRLENOF("moduleload"); - while (!isspace(*ptr)) ptr++; - while (isspace(*ptr)) ptr++; + char *ptr; + if ( c->op == SLAP_CONFIG_ADD ) { + ptr = c->line + STRLENOF("moduleload"); + while (!isspace(*ptr)) ptr++; + while (isspace(*ptr)) ptr++; + } else { + ptr = c->line; + } ber_str2bv(ptr, 0, 1, &bv); - if ( c->op == SLAP_CONFIG_ADD ) - mp = modcur; - else - mp = c->private; - ber_bvarray_add( &mp->mp_loads, &bv ); + ber_bvarray_add( &modcur->mp_loads, &bv ); } break; @@ -1206,8 +1227,7 @@ config_generic(ConfigArgs *c) { mp->mp_loads = NULL; modlast = mp; c->private = mp; - if ( c->op == SLAP_CONFIG_ADD ) - modcur = mp; + modcur = mp; } break; @@ -1224,9 +1244,27 @@ config_generic(ConfigArgs *c) { #ifdef SLAP_AUTH_REWRITE case CFG_REWRITE: { struct berval bv; + char *line; + if(slap_sasl_rewrite_config(c->fname, c->lineno, c->argc, c->argv)) return(1); - ber_str2bv( c->line, 0, 1, &bv ); + + if ( c->argc > 1 ) { + char *s; + + /* quote all args but the first */ + line = ldap_charray2str( c->argv, "\" \"" ); + ber_str2bv( line, 0, 0, &bv ); + s = strchr( bv.bv_val, '"' ); + assert( s != NULL ); + /* move the trailing quote of argv[0] to the end */ + AC_MEMCPY( s, s + 1, bv.bv_len - ( s - bv.bv_val ) ); + bv.bv_val[ bv.bv_len - 1 ] = '"'; + + } else { + ber_str2bv( c->argv[ 0 ], 0, 1, &bv ); + } + ber_bvarray_add( &authz_rewrites, &bv ); } break; @@ -1274,8 +1312,6 @@ config_cfdir(ConfigArgs *c) { static int config_search_base(ConfigArgs *c) { - struct berval dn; - if(c->op == SLAP_CONFIG_EMIT) { int rc = 1; if (!BER_BVISEMPTY(&default_search_base)) { @@ -1509,7 +1545,7 @@ config_overlay(ConfigArgs *c) { /* log error */ Debug( SLAPD_DEBUG_CONFIG_ERROR, "%s: (optional) %s overlay \"%s\" configuration failed" SLAPD_CONF_UNKNOWN_IGNORED ".\n", - c->log, c->be == frontendDB ? "global " : "", c->argv[1][1]); + c->log, c->be == frontendDB ? "global " : "", &c->argv[1][1]); #ifdef SLAPD_CONF_UNKNOWN_BAILOUT return 1; #endif /* SLAPD_CONF_UNKNOWN_BAILOUT */ @@ -1525,13 +1561,55 @@ config_overlay(ConfigArgs *c) { } static int -config_suffix(ConfigArgs *c) { +config_suffix(ConfigArgs *c) +{ Backend *tbe; struct berval pdn, ndn; - int rc; + char *notallowed = NULL; + + if ( c->be == frontendDB ) { + notallowed = "frontend"; + + } else if ( SLAP_MONITOR(c->be) ) { + notallowed = "monitor"; + + } else if ( SLAP_CONFIG(c->be) ) { + notallowed = "config"; + } + + if ( notallowed != NULL ) { + char buf[ SLAP_TEXT_BUFLEN ] = { '\0' }; + + switch ( c->op ) { + case LDAP_MOD_ADD: + case LDAP_MOD_DELETE: + case LDAP_MOD_REPLACE: + case LDAP_MOD_INCREMENT: + case SLAP_CONFIG_ADD: + if ( !BER_BVISNULL( &c->value_dn ) ) { + snprintf( buf, sizeof( buf ), "<%s> ", + c->value_dn.bv_val ); + } - if (c->be == frontendDB || SLAP_MONITOR(c->be) || - SLAP_CONFIG(c->be)) return 1; + Debug(LDAP_DEBUG_ANY, + "%s: suffix %snot allowed in %s database.\n", + c->log, buf, notallowed ); + break; + + case SLAP_CONFIG_EMIT: + /* don't complain when emitting... */ + break; + + default: + /* FIXME: don't know what values may be valid; + * please remove assertion, or add legal values + * to either block */ + assert( 0 ); + break; + } + + return 1; + } if (c->op == SLAP_CONFIG_EMIT) { if ( c->be->be_suffix == NULL @@ -1560,6 +1638,7 @@ config_suffix(ConfigArgs *c) { } return 0; } + #ifdef SLAPD_MONITOR_DN if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) { sprintf( c->msg, "<%s> DN is reserved for monitoring slapd", @@ -1630,16 +1709,12 @@ config_rootdn(ConfigArgs *c) { static int config_rootpw(ConfigArgs *c) { Backend *tbe; - /* config_add_internal sets c->be = frontendDB. While the cn=config - * rootpw is technically inside a backend, we expose it in the - * global entry, and need to point to it properly here. - */ - if (c->be == frontendDB) - c->be = LDAP_STAILQ_FIRST(&backendDB); if (c->op == SLAP_CONFIG_EMIT) { if (!BER_BVISEMPTY(&c->be->be_rootpw)) { - ber_dupbv( &c->value_bv, &c->be->be_rootpw); + /* don't copy, because "rootpw" is marked + * as CFG_BERVAL */ + c->value_bv = c->be->be_rootpw; return 0; } return 1; @@ -1812,11 +1887,13 @@ config_requires(ConfigArgs *c) { return(0); } +static slap_verbmasks *loglevel_ops; + static int -config_loglevel(ConfigArgs *c) { - int i; - char *next; - slap_verbmasks loglevel_ops[] = { +loglevel_init( void ) +{ + slap_verbmasks lo[] = { + { BER_BVC("Any"), -1 }, { BER_BVC("Trace"), LDAP_DEBUG_TRACE }, { BER_BVC("Packets"), LDAP_DEBUG_PACKETS }, { BER_BVC("Args"), LDAP_DEBUG_ARGS }, @@ -1832,10 +1909,71 @@ config_loglevel(ConfigArgs *c) { { BER_BVC("Cache"), LDAP_DEBUG_CACHE }, { BER_BVC("Index"), LDAP_DEBUG_INDEX }, { BER_BVC("Sync"), LDAP_DEBUG_SYNC }, - { BER_BVC("Any"), -1 }, { BER_BVNULL, 0 } }; + return slap_verbmasks_init( &loglevel_ops, lo ); +} + +static void +loglevel_destroy( void ) +{ + if ( loglevel_ops ) { + (void)slap_verbmasks_destroy( loglevel_ops ); + } + loglevel_ops = NULL; +} + +static slap_mask_t loglevel_ignore[] = { -1, 0 }; + +int +slap_loglevel_register( slap_mask_t m, struct berval *s ) +{ + int rc; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + rc = slap_verbmasks_append( &loglevel_ops, m, s, loglevel_ignore ); + + if ( rc != 0 ) { + Debug( LDAP_DEBUG_ANY, "slap_loglevel_register(%lu, \"%s\") failed\n", + m, s->bv_val, 0 ); + } + + return rc; +} + +int +str2loglevel( const char *s, int *l ) +{ + int i; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + + i = verb_to_mask( s, loglevel_ops ); + + if ( BER_BVISNULL( &loglevel_ops[ i ].word) ) { + return -1; + } + + *l = loglevel_ops[ i ].mask; + + return 0; +} + +static int +config_loglevel(ConfigArgs *c) { + int i; + char *next; + + if ( loglevel_ops == NULL ) { + loglevel_init(); + } + if (c->op == SLAP_CONFIG_EMIT) { return mask_to_verbs( loglevel_ops, ldap_syslog, &c->rvalue_vals ); } else if ( c->op == LDAP_MOD_DELETE ) { @@ -1853,7 +1991,7 @@ config_loglevel(ConfigArgs *c) { for( i=1; i < c->argc; i++ ) { int level; - if ( isdigit( c->argv[i][0] ) ) { + if ( isdigit( c->argv[i][0] ) || c->argv[i][0] == '-' ) { level = strtol( c->argv[i], &next, 10 ); if ( next == NULL || next[0] != '\0' ) { sprintf( c->msg, "<%s> unable to parse level", c->argv[0] ); @@ -1862,14 +2000,12 @@ config_loglevel(ConfigArgs *c) { return( 1 ); } } else { - int j = verb_to_mask(c->argv[i], loglevel_ops); - if(BER_BVISNULL(&loglevel_ops[j].word)) { + if ( str2loglevel( c->argv[i], &level ) ) { sprintf( c->msg, "<%s> unknown level", c->argv[0] ); Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", c->log, c->msg, c->argv[i]); return( 1 ); } - level = loglevel_ops[j].mask; } ldap_syslog |= level; } @@ -1997,7 +2133,7 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv ) { int len; char *ptr; - struct berval bc = {0}; + struct berval bc = BER_BVNULL; char numbuf[32]; len = sprintf(numbuf, IFMT, i ); @@ -2089,6 +2225,7 @@ config_replica(ConfigArgs *c) { return(1); } if(!ludp->lud_host) { + ldap_free_urldesc(ludp); sprintf( c->msg, "<%s> invalid uri - missing hostname", c->argv[0] ); Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 ); @@ -2162,8 +2299,6 @@ config_replica(ConfigArgs *c) { static int config_updatedn(ConfigArgs *c) { - struct berval dn; - int rc; if (c->op == SLAP_CONFIG_EMIT) { if (!BER_BVISEMPTY(&c->be->be_update_ndn)) { value_add_one(&c->rvalue_vals, &c->be->be_update_ndn); @@ -2173,7 +2308,7 @@ config_updatedn(ConfigArgs *c) { return 1; } else if ( c->op == LDAP_MOD_DELETE ) { ch_free( c->be->be_update_ndn.bv_val ); - c->be->be_update_ndn.bv_val = NULL; + BER_BVZERO( &c->be->be_update_ndn ); SLAP_DBFLAGS(c->be) ^= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SLURP_SHADOW); return 0; } @@ -2184,17 +2319,13 @@ config_updatedn(ConfigArgs *c) { return(1); } - ber_str2bv(c->argv[1], 0, 0, &dn); - - rc = dnNormalize(0, NULL, NULL, &dn, &c->be->be_update_ndn, NULL); - - if(rc != LDAP_SUCCESS) { - sprintf( c->msg, "<%s> invalid DN %d (%s)", c->argv[0], - rc, ldap_err2string(rc)); - Debug(LDAP_DEBUG_ANY, "%s: %s\n", - c->log, c->msg, 0 ); - return(1); + ber_memfree_x( c->value_dn.bv_val, NULL ); + if ( !BER_BVISNULL( &c->be->be_update_ndn ) ) { + ber_memfree_x( c->be->be_update_ndn.bv_val, NULL ); } + c->be->be_update_ndn = c->value_ndn; + BER_BVZERO( &c->value_dn ); + BER_BVZERO( &c->value_ndn ); SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SLURP_SHADOW); return(0); @@ -2243,7 +2374,7 @@ config_updateref(ConfigArgs *c) { static int config_include(ConfigArgs *c) { - unsigned long savelineno = c->lineno; + int savelineno = c->lineno; int rc; ConfigFile *cf; ConfigFile *cfsave = cfn; @@ -2391,14 +2522,19 @@ config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last ) return root; } +typedef struct setup_cookie { + CfBackInfo *cfb; + ConfigArgs *ca; +} setup_cookie; + static int config_ldif_resp( Operation *op, SlapReply *rs ) { if ( rs->sr_type == REP_SEARCH ) { - CfBackInfo *cfb = op->o_callback->sc_private; + setup_cookie *sc = op->o_callback->sc_private; - cfb->cb_got_ldif = 1; - rs->sr_err = config_add_internal( cfb, rs->sr_entry, NULL, NULL ); + sc->cfb->cb_got_ldif = 1; + rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL ); } return rs->sr_err; } @@ -2411,6 +2547,7 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) { ConfigTable *ct; char *argv[3]; int rc = 0; + setup_cookie sc; slap_callback cb = { NULL, config_ldif_resp, NULL, NULL }; Connection conn = {0}; char opbuf[OPERATION_BUFFER_SIZE]; @@ -2487,10 +2624,14 @@ config_setup_ldif( BackendDB *be, const char *dir, int readit ) { op->ors_attrsonly = 0; op->o_callback = &cb; - cb.sc_private = cfb; + sc.cfb = cfb; + sc.ca = &c; + cb.sc_private = ≻ op->o_bd = &cfb->cb_db; rc = op->o_bd->be_search( op, &rs ); + + slap_sl_mem_destroy( NULL, op->o_tmpmemctx ); } cfb->cb_use_ldif = 1; @@ -2566,8 +2707,10 @@ read_config(const char *fname, const char *dir) { return 1; /* If we read the config from back-ldif, nothing to do here */ - if ( cfb->cb_got_ldif ) - return 0; + if ( cfb->cb_got_ldif ) { + rc = 0; + goto done; + } } if ( fname ) @@ -2578,7 +2721,7 @@ read_config(const char *fname, const char *dir) { rc = read_config_file(cfname, 0, NULL, config_back_cf_table); if ( rc == 0 ) - ber_str2bv( cfname, 0, 1, &cf_prv.c_file ); + ber_str2bv( cfname, 0, 1, &cfb->cb_config->c_file ); /* If we got this far and failed, it may be a serious problem. In server * mode, we should never come to this. However, it may be alright if we're @@ -2598,6 +2741,20 @@ read_config(const char *fname, const char *dir) { } break; } + +done: + if ( rc == 0 && BER_BVISNULL( &frontendDB->be_schemadn ) ) { + ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1, + &frontendDB->be_schemadn ); + rc = dnNormalize( 0, NULL, NULL, &frontendDB->be_schemadn, &frontendDB->be_schemandn, NULL ); + if ( rc != LDAP_SUCCESS ) { + Debug(LDAP_DEBUG_ANY, "read_config: " + "unable to normalize default schema DN \"%s\"\n", + frontendDB->be_schemadn.bv_val, 0, 0 ); + /* must not happen */ + assert( 0 ); + } + } return rc; } @@ -2745,8 +2902,9 @@ check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr ) if ( idx ) ca->line = idx+1; } rc = config_parse_vals( ct, ca, i ); - if ( rc ) + if ( rc ) { break; + } } return rc; } @@ -2781,8 +2939,13 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e, return LDAP_NAMING_VIOLATION; gotindex = 1; index = atoi(ptr1+1); - if ( index < 0 ) - return LDAP_NAMING_VIOLATION; + if ( index < 0 ) { + /* Special case, we allow -1 for the frontendDB */ + if ( index != -1 || ce_type != Cft_Database || + strncmp( ptr2+1, "frontend,", STRLENOF("frontend,") )) + + return LDAP_NAMING_VIOLATION; + } } /* count related kids */ @@ -2913,10 +3076,7 @@ cfAddInclude( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) if ( ca->lineno ) return LDAP_COMPARE_TRUE; - if ( p->ce_type == Cft_Global ) - cfn = &cf_prv; - else - cfn = p->ce_private; + cfn = p->ce_private; ca->private = cfn; return LDAP_SUCCESS; } @@ -2928,7 +3088,7 @@ cfAddSchema( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) /* This entry is hardcoded, don't re-parse it */ if ( p->ce_type == Cft_Global ) { - cfn = &cf_prv; + cfn = p->ce_private; ca->private = cfn; return LDAP_COMPARE_TRUE; } @@ -2979,13 +3139,12 @@ cfAddOverlay( CfEntryInfo *p, Entry *e, struct config_args_s *ca ) /* Parse an LDAP entry into config directives */ static int -config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) +config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs, int *renum ) { CfEntryInfo *ce, *last; ConfigOCs **colst; Attribute *a, *oc_at; - int i, j, nocs, rc = 0; - ConfigArgs ca = {0}; + int i, nocs, rc = 0; struct berval pdn; ConfigTable *ct; char *ptr; @@ -3009,15 +3168,17 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass ); if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION; + memset( ca, 0, sizeof(ConfigArgs)); + /* Fake the coordinates based on whether we're part of an * LDAP Add or if reading the config dir */ if ( rs ) { - ca.fname = "slapd"; - ca.lineno = 0; + ca->fname = "slapd"; + ca->lineno = 0; } else { - ca.fname = cfdir.bv_val; - ca.lineno = 1; + ca->fname = cfdir.bv_val; + ca->lineno = 1; } colst = count_ocs( oc_at, &nocs ); @@ -3027,9 +3188,9 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) */ rc = LDAP_CONSTRAINT_VIOLATION; if ( colst[0]->co_type == Cft_Global && !last ) { - cfn = &cf_prv; - ca.private = cfn; - ca.be = frontendDB; /* just to get past check_vals */ + cfn = cfb->cb_config; + ca->private = cfn; + ca->be = frontendDB; /* just to get past check_vals */ rc = LDAP_SUCCESS; } @@ -3039,7 +3200,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) if ( last ) { for ( i=0; ico_ldadd && - ( rc = colst[i]->co_ldadd( last, e, &ca )) + ( rc = colst[i]->co_ldadd( last, e, ca )) != LDAP_CONSTRAINT_VIOLATION ) { break; } @@ -3075,7 +3236,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) if ( rc ) goto leave; - init_config_argv( &ca ); + init_config_argv( ca ); /* Make sure we process attrs in the required order */ sort_attrs( e, colst, nocs ); @@ -3084,7 +3245,7 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) if ( a == oc_at ) continue; ct = config_find_table( colst, nocs, a->a_desc ); if ( !ct ) continue; /* user data? */ - rc = check_vals( ct, &ca, a, 1 ); + rc = check_vals( ct, ca, a, 1 ); if ( rc ) goto leave; } @@ -3094,13 +3255,13 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) ct = config_find_table( colst, nocs, a->a_desc ); if ( !ct ) continue; /* user data? */ for (i=0; a->a_vals[i].bv_val; i++) { - ca.line = a->a_vals[i].bv_val; + ca->line = a->a_vals[i].bv_val; if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) { - ptr = strchr( ca.line, '}' ); - if ( ptr ) ca.line = ptr+1; + ptr = strchr( ca->line, '}' ); + if ( ptr ) ca->line = ptr+1; } - ca.valx = i; - rc = config_parse_add( ct, &ca ); + ca->valx = i; + rc = config_parse_add( ct, ca ); if ( rc ) { rc = LDAP_OTHER; goto leave; @@ -3108,14 +3269,36 @@ config_add_internal( CfBackInfo *cfb, Entry *e, SlapReply *rs, int *renum ) } } ok: + /* Newly added databases and overlays need to be started up */ + if ( CONFIG_ONLINE_ADD( ca )) { + if ( colst[0]->co_type == Cft_Database ) { + rc = backend_startup_one( ca->be ); + + } else if ( colst[0]->co_type == Cft_Overlay ) { + if ( ca->bi->bi_db_open ) { + BackendInfo *bi_orig = ca->be->bd_info; + ca->be->bd_info = ca->bi; + rc = ca->bi->bi_db_open( ca->be ); + ca->be->bd_info = bi_orig; + } + } + if ( rc ) { + sprintf( ca->msg, "<%s> failed startup", ca->argv[0] ); + Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n", + ca->log, ca->msg, ca->argv[1] ); + rc = LDAP_OTHER; + goto leave; + } + } + ce = ch_calloc( 1, sizeof(CfEntryInfo) ); ce->ce_parent = last; ce->ce_entry = entry_dup( e ); ce->ce_entry->e_private = ce; ce->ce_type = colst[0]->co_type; - ce->ce_be = ca.be; - ce->ce_bi = ca.bi; - ce->ce_private = ca.private; + ce->ce_be = ca->be; + ce->ce_bi = ca->bi; + ce->ce_private = ca->private; if ( !last ) { cfb->cb_root = ce; } else if ( last->ce_kids ) { @@ -3129,7 +3312,16 @@ ok: } leave: - ch_free( ca.argv ); + if ( rc ) { + if ( (colst[0]->co_type == Cft_Database) && ca->be ) { + if ( ca->be != frontendDB ) + backend_destroy_one( ca->be, 1 ); + } else if ( (colst[0]->co_type == Cft_Overlay) && ca->bi ) { + overlay_destroy_one( ca->be, (slap_overinst *)ca->bi ); + } + } + + ch_free( ca->argv ); if ( colst ) ch_free( colst ); return rc; } @@ -3141,8 +3333,8 @@ static int config_back_add( Operation *op, SlapReply *rs ) { CfBackInfo *cfb; - CfEntryInfo *ce, *last; int renumber; + ConfigArgs ca; if ( !be_isroot( op ) ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; @@ -3160,8 +3352,10 @@ config_back_add( Operation *op, SlapReply *rs ) * 4) store entry in underlying database * 5) perform any necessary renumbering */ - rs->sr_err = config_add_internal( cfb, op->ora_e, rs, &renumber ); - if ( rs->sr_err == LDAP_SUCCESS && cfb->cb_use_ldif ) { + rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber ); + if ( rs->sr_err != LDAP_SUCCESS ) { + 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 }; op->o_bd = &cfb->cb_db; @@ -3184,14 +3378,13 @@ out: typedef struct delrec { struct delrec *next; int nidx; - int idx[0]; + int idx[1]; } delrec; static int config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs, ConfigArgs *ca ) { - CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private; int rc = LDAP_UNWILLING_TO_PERFORM; Modifications *ml; Entry *e = ce->ce_entry; @@ -3225,8 +3418,6 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs, int *idx = NULL; if ( ct && ( ct->arg_type & ARG_NO_DELETE )) { rc = LDAP_OTHER; - snprintf( ca->msg, sizeof(ca->msg), - "<%s> cannot be deleted" ); snprintf(ca->msg, sizeof(ca->msg), "cannot delete %s", ml->sml_desc->ad_cname.bv_val ); goto out; @@ -3243,7 +3434,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++); - d = ch_malloc( sizeof(delrec) + i * sizeof(int)); + d = ch_malloc( sizeof(delrec) + (i - 1)* sizeof(int)); d->nidx = i; d->next = NULL; if ( dels ) { @@ -3322,8 +3513,8 @@ config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs, if(rc == LDAP_SUCCESS) { /* check that the entry still obeys the schema */ - rc = entry_schema_check(op->o_bd, e, NULL, - &rs->sr_text, ca->msg, sizeof(ca->msg) ); + rc = entry_schema_check(op, e, NULL, 0, + &rs->sr_text, ca->msg, sizeof(ca->msg) ); } if ( rc == LDAP_SUCCESS ) { /* Basic syntax checks are OK. Do the actual settings. */ @@ -3546,7 +3737,6 @@ config_back_search( Operation *op, SlapReply *rs ) { CfBackInfo *cfb; CfEntryInfo *ce, *last; - int rc; if ( !be_isroot( op ) ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; @@ -3781,12 +3971,10 @@ config_back_db_open( BackendDB *be ) CfBackInfo *cfb = be->be_private; struct berval rdn; Entry *e, *parent; - CfEntryInfo *ce, *ceparent, *ceprev; - int i, rc; + CfEntryInfo *ce, *ceparent; + int i; BackendInfo *bi; - BackendDB *bptr; ConfigArgs c; - ConfigTable *ct; Connection conn = {0}; char opbuf[OPERATION_BUFFER_SIZE]; Operation *op; @@ -3869,25 +4057,22 @@ config_back_db_open( BackendDB *be ) } /* Create database nodes... */ - i = -1; - LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { + frontendDB->be_cf_ocs = &CFOC_FRONTEND; + LDAP_STAILQ_NEXT(frontendDB, be_next) = LDAP_STAILQ_FIRST(&backendDB); + for ( i = -1, be = frontendDB ; be; + i++, be = LDAP_STAILQ_NEXT( be, be_next )) { slap_overinfo *oi = NULL; - i++; - if ( i == 0 ) { - bptr = frontendDB; - } else { - bptr = be; - } - if ( overlay_is_over( bptr )) { - oi = bptr->bd_info->bi_private; + + if ( overlay_is_over( be )) { + oi = be->bd_info->bi_private; bi = oi->oi_orig; } else { - bi = bptr->bd_info; + bi = be->bd_info; } rdn.bv_val = c.log; rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s", cfAd_database->ad_cname.bv_val, i, bi->bi_type); - c.be = bptr; + c.be = be; c.bi = bi; e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_DATABASE, be->be_cf_ocs ); @@ -3904,7 +4089,7 @@ config_back_db_open( BackendDB *be ) rdn.bv_val = c.log; rdn.bv_len = sprintf(rdn.bv_val, "%s=" IFMT "%s", cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type ); - c.be = bptr; + c.be = be; c.bi = &on->on_bi; oe = config_build_entry( op, &rs, ce, &c, &rdn, &CFOC_OVERLAY, c.bi->bi_cf_ocs ); @@ -3913,25 +4098,93 @@ config_back_db_open( BackendDB *be ) } } } + if ( op ) + slap_sl_mem_destroy( NULL, op->o_tmpmemctx ); return 0; } +static void +cfb_free_cffile( ConfigFile *cf ) +{ + ConfigFile *next; + + for (; cf; cf=next) { + next = cf->c_sibs; + if ( cf->c_kids ) + cfb_free_cffile( cf->c_kids ); + ch_free( cf->c_file.bv_val ); + ber_bvarray_free( cf->c_dseFiles ); + ch_free( cf ); + } +} + +static void +cfb_free_entries( CfEntryInfo *ce ) +{ + CfEntryInfo *next; + + for (; ce; ce=next) { + next = ce->ce_sibs; + if ( ce->ce_kids ) + cfb_free_entries( ce->ce_kids ); + ce->ce_entry->e_private = NULL; + entry_free( ce->ce_entry ); + ch_free( ce ); + } +} + static int -config_back_db_destroy( Backend *be ) +config_back_db_close( BackendDB *be ) { + CfBackInfo *cfb = be->be_private; + + cfb_free_entries( cfb->cb_root ); + cfb->cb_root = NULL; + + if ( cfb->cb_db.bd_info ) { + backend_shutdown( &cfb->cb_db ); + } + + return 0; +} + +static int +config_back_db_destroy( BackendDB *be ) +{ + CfBackInfo *cfb = be->be_private; + + cfb_free_cffile( cfb->cb_config ); + + ch_free( cfdir.bv_val ); + + avl_free( CfOcTree, NULL ); + + if ( cfb->cb_db.bd_info ) { + cfb->cb_db.be_suffix = NULL; + cfb->cb_db.be_nsuffix = NULL; + BER_BVZERO( &cfb->cb_db.be_rootdn ); + BER_BVZERO( &cfb->cb_db.be_rootndn ); + + backend_destroy_one( &cfb->cb_db, 0 ); + } + free( be->be_private ); + + loglevel_destroy(); + return 0; } static int -config_back_db_init( Backend *be ) +config_back_db_init( BackendDB *be ) { struct berval dn; CfBackInfo *cfb; cfb = ch_calloc( 1, sizeof(CfBackInfo)); - cfb->cb_config = &cf_prv; + cfb->cb_config = ch_calloc( 1, sizeof(ConfigFile)); + cfn = cfb->cb_config; be->be_private = cfb; ber_dupbv( &be->be_rootdn, &config_rdn ); @@ -4020,9 +4273,10 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text ) { CfBackInfo *cfb = be->be_private; BackendInfo *bi = cfb->cb_db.bd_info; + ConfigArgs ca; if ( bi && bi->bi_tool_entry_put && - config_add_internal( cfb, e, NULL, NULL ) == 0 ) + config_add_internal( cfb, e, &ca, NULL, NULL ) == 0 ) return bi->bi_tool_entry_put( &cfb->cb_db, e, text ); else return NOID; @@ -4085,7 +4339,7 @@ config_back_initialize( BackendInfo *bi ) bi->bi_db_init = config_back_db_init; bi->bi_db_config = 0; bi->bi_db_open = config_back_db_open; - bi->bi_db_close = 0; + bi->bi_db_close = config_back_db_close; bi->bi_db_destroy = config_back_db_destroy; bi->bi_op_bind = config_back_bind; @@ -4116,6 +4370,9 @@ config_back_initialize( BackendInfo *bi ) bi->bi_tool_entry_get = config_tool_entry_get; bi->bi_tool_entry_put = config_tool_entry_put; + /* Make sure we don't exceed the bits reserved for userland */ + assert( ( ( CFG_LAST - 1 ) & ARGS_USERLAND ) == ( CFG_LAST - 1 ) ); + argv[3] = NULL; for (i=0; OidMacros[i].name; i++ ) { argv[1] = OidMacros[i].name;