X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fbconfig.c;h=ded66131b45b1d218114d15684c41e9da0495458;hb=01f698bce979660270207ce052f3bdbbd79365a5;hp=a5e28d9258ea71fdb1d3e69aa77d373e62aab138;hpb=a8f6deee03fc563903130103a2765d4134ce9b1f;p=openldap diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c index a5e28d9258..ded66131b4 100644 --- a/servers/slapd/bconfig.c +++ b/servers/slapd/bconfig.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2012 The OpenLDAP Foundation. + * Copyright 2005-2014 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -196,6 +196,10 @@ enum { CFG_ACL_ADD, CFG_SYNC_SUBENTRY, CFG_LTHREADS, + CFG_IX_HASH64, + CFG_DISABLED, + CFG_THREADQS, + CFG_TLS_ECNAME, CFG_LAST }; @@ -242,7 +246,7 @@ static OidRec OidMacros[] = { * OLcfg{Bk|Db}{Oc|At}:0 -> common * OLcfg{Bk|Db}{Oc|At}:1 -> back-bdb(/back-hdb) * OLcfg{Bk|Db}{Oc|At}:2 -> back-ldif - * OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap + * OLcfg{Bk|Db}{Oc|At}:3 -> back-ldap/meta * OLcfg{Bk|Db}{Oc|At}:4 -> back-monitor * OLcfg{Bk|Db}{Oc|At}:5 -> back-relay * OLcfg{Bk|Db}{Oc|At}:6 -> back-sql(/back-ndb) @@ -363,6 +367,9 @@ static ConfigTable config_back_cf_table[] = { { "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 }, + { "disabled", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_DISABLED, + &config_generic, "( OLcfgDbAt:0.21 NAME 'olcDisabled' " + "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, { "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC, &config_disallows, "( OLcfgGlAt:15 NAME 'olcDisallows' " "EQUALITY caseIgnoreMatch " @@ -395,19 +402,22 @@ static ConfigTable config_back_cf_table[] = { { "include", "file", 2, 2, 0, ARG_MAGIC, &config_include, "( OLcfgGlAt:19 NAME 'olcInclude' " "SUP labeledURI )", NULL, NULL }, + { "index_hash64", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_IX_HASH64, + &config_generic, "( OLcfgGlAt:94 NAME 'olcIndexHash64' " + "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, { "index_substr_if_minlen", "min", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN, &config_generic, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' " "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, { "index_substr_if_maxlen", "max", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MAX, &config_generic, "( OLcfgGlAt:21 NAME 'olcIndexSubstrIfMaxLen' " "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, - { "index_substr_any_len", "len", 2, 2, 0, ARG_INT|ARG_NONZERO, + { "index_substr_any_len", "len", 2, 2, 0, ARG_UINT|ARG_NONZERO, &index_substr_any_len, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' " "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, - { "index_substr_any_step", "step", 2, 2, 0, ARG_INT|ARG_NONZERO, + { "index_substr_any_step", "step", 2, 2, 0, ARG_UINT|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, + { "index_intlen", "len", 2, 2, 0, ARG_UINT|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, @@ -675,6 +685,14 @@ static ConfigTable config_back_cf_table[] = { #endif "( OLcfgGlAt:66 NAME 'olcThreads' " "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, + { "threadqueues", "count", 2, 2, 0, +#ifdef NO_THREADS + ARG_IGNORED, NULL, +#else + ARG_INT|ARG_MAGIC|CFG_THREADQS, &config_generic, +#endif + "( OLcfgGlAt:95 NAME 'olcThreadQueues' " + "SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL }, { "timelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC, &config_timelimit, "( OLcfgGlAt:67 NAME 'olcTimeLimit' " "SYNTAX OMsDirectoryString )", NULL, NULL }, @@ -758,6 +776,14 @@ static ConfigTable config_back_cf_table[] = { #endif "( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' " "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, + { "TLSECName", NULL, 2, 2, 0, +#ifdef HAVE_TLS + CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC, &config_tls_option, +#else + ARG_IGNORED, NULL, +#endif + "( OLcfgGlAt:96 NAME 'olcTLSECName' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, { "TLSProtocolMin", NULL, 2, 2, 0, #ifdef HAVE_TLS CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config, @@ -826,8 +852,9 @@ static ConfigOCs cf_ocs[] = { "olcConnMaxPending $ olcConnMaxPendingAuth $ " "olcDisallows $ olcGentleHUP $ olcIdleTimeout $ " "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ " - "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexIntLen $ " - "olcLocalSSF $ olcLogFile $ olcLogLevel $ " + "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexHash64 $ " + "olcIndexIntLen $ " + "olcListenerThreads $ olcLocalSSF $ olcLogFile $ olcLogLevel $ " "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ " "olcPluginLogFile $ olcReadOnly $ olcReferral $ " "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ " @@ -837,11 +864,12 @@ static ConfigOCs cf_ocs[] = { "olcSecurity $ olcServerID $ olcSizeLimit $ " "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ " "olcTCPBuffer $ " - "olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ " + "olcThreads $ olcThreadQueues $ " + "olcTimeLimit $ olcTLSCACertificateFile $ " "olcTLSCACertificatePath $ olcTLSCertificateFile $ " "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ " - "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ " - "olcTLSCRLFile $ olcToolThreads $ olcWriteTimeout $ " + "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ olcTLSECName $ " + "olcTLSCRLFile $ olcTLSProtocolMin $ olcToolThreads $ olcWriteTimeout $ " "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ " "olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global }, { "( OLcfgGlOc:2 " @@ -861,7 +889,7 @@ static ConfigOCs cf_ocs[] = { "DESC 'OpenLDAP Database-specific options' " "SUP olcConfig STRUCTURAL " "MUST olcDatabase " - "MAY ( olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ " + "MAY ( olcDisabled $ olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ " "olcAddContentAcl $ olcLastMod $ olcLimits $ " "olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ " "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ " @@ -874,7 +902,8 @@ static ConfigOCs cf_ocs[] = { "NAME 'olcOverlayConfig' " "DESC 'OpenLDAP Overlay-specific options' " "SUP olcConfig STRUCTURAL " - "MUST olcOverlay )", Cft_Overlay, NULL, cfAddOverlay }, + "MUST olcOverlay " + "MAY olcDisabled )", Cft_Overlay, NULL, cfAddOverlay }, { "( OLcfgGlOc:6 " "NAME 'olcIncludeFile' " "DESC 'OpenLDAP configuration include file' " @@ -911,6 +940,7 @@ typedef struct ServerID { } ServerID; static ServerID *sid_list; +static ServerID *sid_set; typedef struct voidList { struct voidList *vl_next; @@ -937,6 +967,9 @@ config_generic(ConfigArgs *c) { case CFG_THREADS: c->value_int = connection_pool_max; break; + case CFG_THREADQS: + c->value_int = connection_pool_queues; + break; case CFG_TTHREADS: c->value_int = slap_tool_thread_max; break; @@ -1038,6 +1071,23 @@ config_generic(ConfigArgs *c) { case CFG_DEPTH: c->value_int = c->be->be_max_deref_depth; break; + case CFG_DISABLED: + if ( c->bi ) { + /* overlay */ + if ( c->bi->bi_flags & SLAPO_BFLAG_DISABLED ) { + c->value_int = 1; + } else { + rc = 1; + } + } else { + /* database */ + if ( SLAP_DBDISABLED( c->be )) { + c->value_int = 1; + } else { + rc = 1; + } + } + break; case CFG_HIDDEN: if ( SLAP_DBHIDDEN( c->be )) { c->value_int = 1; @@ -1198,6 +1248,9 @@ config_generic(ConfigArgs *c) { case CFG_SSTR_IF_MIN: c->value_uint = index_substr_if_minlen; break; + case CFG_IX_HASH64: + c->value_int = slap_hash64( -1 ); + break; case CFG_IX_INTLEN: c->value_int = index_intlen; break; @@ -1284,6 +1337,7 @@ config_generic(ConfigArgs *c) { /* single-valued attrs, no-ops */ case CFG_CONCUR: case CFG_THREADS: + case CFG_THREADQS: case CFG_TTHREADS: case CFG_LTHREADS: case CFG_RO: @@ -1362,6 +1416,8 @@ config_generic(ConfigArgs *c) { si; si = *sip, i++ ) { if ( c->valx == -1 || i == c->valx ) { *sip = si->si_next; + if ( sid_set == si ) + sid_set = NULL; ch_free( si ); if ( c->valx >= 0 ) break; @@ -1375,6 +1431,25 @@ config_generic(ConfigArgs *c) { c->be->be_flags &= ~SLAP_DBFLAG_HIDDEN; break; + case CFG_DISABLED: + if ( c->bi ) { + c->bi->bi_flags &= ~SLAP_DBFLAG_DISABLED; + if ( c->bi->bi_db_open ) { + BackendInfo *bi_orig = c->be->bd_info; + c->be->bd_info = c->bi; + rc = c->bi->bi_db_open( c->be, &c->reply ); + c->be->bd_info = bi_orig; + } + } else { + c->be->be_flags &= ~SLAP_DBFLAG_DISABLED; + rc = backend_startup_one( c->be, &c->reply ); + } + break; + + case CFG_IX_HASH64: + slap_hash64( 0 ); + break; + case CFG_IX_INTLEN: index_intlen = SLAP_INDEX_INTLEN_DEFAULT; index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN( @@ -1642,6 +1717,20 @@ config_generic(ConfigArgs *c) { connection_pool_max = c->value_int; /* save for reference */ break; + case CFG_THREADQS: + if ( c->value_int < 1 ) { + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "threadqueuess=%d smaller than minimum value 1", + c->value_int ); + Debug(LDAP_DEBUG_ANY, "%s: %s.\n", + c->log, c->cr_msg, 0 ); + return 1; + } + if ( slapMode & SLAP_SERVER_MODE ) + ldap_pvt_thread_pool_queues(&connection_pool, c->value_int); + connection_pool_queues = c->value_int; /* save for reference */ + break; + case CFG_TTHREADS: if ( slapMode & SLAP_TOOL_MODE ) ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int); @@ -1882,6 +1971,11 @@ config_generic(ConfigArgs *c) { return(1); break; + case CFG_IX_HASH64: + if ( slap_hash64( c->value_int != 0 )) + return 1; + break; + case CFG_IX_INTLEN: if ( c->value_int < SLAP_INDEX_INTLEN_DEFAULT ) c->value_int = SLAP_INDEX_INTLEN_DEFAULT; @@ -1891,7 +1985,7 @@ config_generic(ConfigArgs *c) { index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN( index_intlen ); break; - + case CFG_SORTVALS: { ADlist *svnew = NULL, *svtail, *sv; @@ -2035,6 +2129,7 @@ sortval_reject: Debug( LDAP_DEBUG_CONFIG, "%s: SID=0x%03x\n", c->log, slap_serverID, 0 ); + sid_set = si; } si->si_next = NULL; si->si_num = num; @@ -2044,11 +2139,20 @@ sortval_reject: if (( slapMode & SLAP_SERVER_MODE ) && c->argc > 2 ) { Listener *l = config_check_my_url( c->argv[2], lud ); if ( l ) { + if ( sid_set ) { + ldap_free_urldesc( lud ); + snprintf( c->cr_msg, sizeof( c->cr_msg ), + "<%s> multiple server ID URLs matched, only one is allowed", c->argv[0] ); + Debug(LDAP_DEBUG_ANY, "%s: %s %s\n", + c->log, c->cr_msg, c->argv[1] ); + return 1; + } slap_serverID = si->si_num; Debug( LDAP_DEBUG_CONFIG, "%s: SID=0x%03x (listener=%s)\n", c->log, slap_serverID, l->sl_url.bv_val ); + sid_set = si; } } if ( c->argc > 2 ) @@ -2100,6 +2204,29 @@ sortval_reject: SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MONITORING; break; + case CFG_DISABLED: + if ( c->bi ) { + if (c->value_int) { + if ( c->bi->bi_db_close ) { + BackendInfo *bi_orig = c->be->bd_info; + c->be->bd_info = c->bi; + c->bi->bi_db_close( c->be, &c->reply ); + c->be->bd_info = bi_orig; + } + c->bi->bi_flags |= SLAPO_BFLAG_DISABLED; + } else { + c->bi->bi_flags &= ~SLAPO_BFLAG_DISABLED; + } + } else { + if (c->value_int) { + backend_shutdown( c->be ); + SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_DISABLED; + } else { + SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_DISABLED; + } + } + break; + case CFG_HIDDEN: if (c->value_int) SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_HIDDEN; @@ -3057,7 +3184,8 @@ config_suffix(ConfigArgs *c) } #endif - if (SLAP_DB_ONE_SUFFIX( c->be ) && c->be->be_suffix ) { + if (SLAP_DB_ONE_SUFFIX( c->be ) && c->be->be_suffix && + !BER_BVISNULL( &c->be->be_suffix[0] )) { 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", @@ -3532,6 +3660,11 @@ loglevel2bvarray( int l, BerVarray *bva ) loglevel_init(); } + if ( l == 0 ) { + struct berval bv = BER_BVC("0"); + return value_add_one( bva, &bv ); + } + return mask_to_verbs( loglevel_ops, l, bva ); } @@ -3906,6 +4039,7 @@ config_tls_cleanup(ConfigArgs *c) { int opt = 1; ldap_pvt_tls_ctx_free( slap_tls_ctx ); + slap_tls_ctx = NULL; /* Force new ctx to be created */ rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt ); @@ -3914,6 +4048,11 @@ config_tls_cleanup(ConfigArgs *c) { ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx ); /* This is a no-op if it's already loaded */ load_extop( &slap_EXOP_START_TLS, 0, starttls_extop ); + } else { + if ( rc == LDAP_NOT_SUPPORTED ) + rc = LDAP_UNWILLING_TO_PERFORM; + else + rc = LDAP_OTHER; } } return rc; @@ -3931,6 +4070,7 @@ config_tls_option(ConfigArgs *c) { case CFG_TLS_CA_PATH: flag = LDAP_OPT_X_TLS_CACERTDIR; break; case CFG_TLS_CA_FILE: flag = LDAP_OPT_X_TLS_CACERTFILE; break; case CFG_TLS_DH_FILE: flag = LDAP_OPT_X_TLS_DHFILE; break; + case CFG_TLS_ECNAME: flag = LDAP_OPT_X_TLS_ECNAME; break; #ifdef HAVE_GNUTLS case CFG_TLS_CRL_FILE: flag = LDAP_OPT_X_TLS_CRLFILE; break; #endif @@ -3973,7 +4113,7 @@ config_tls_config(ConfigArgs *c) { } ch_free( c->value_string ); c->cleanup = config_tls_cleanup; - if ( isdigit( (unsigned char)c->argv[1][0] ) ) { + if ( isdigit( (unsigned char)c->argv[1][0] ) && c->type != CFG_TLS_PROTOCOL_MIN ) { if ( lutil_atoi( &i, c->argv[1] ) != 0 ) { Debug(LDAP_DEBUG_ANY, "%s: " "unable to parse %s \"%s\"\n", @@ -4360,6 +4500,13 @@ done: assert( 0 ); } } + if ( rc == 0 && ( slapMode & SLAP_SERVER_MODE ) && sid_list ) { + if ( !BER_BVISEMPTY( &sid_list->si_url ) && !sid_set ) { + Debug(LDAP_DEBUG_ANY, "read_config: no serverID / URL match found. " + "Check slapd -h arguments.\n", 0,0,0 ); + rc = LDAP_OTHER; + } + } return rc; } @@ -4745,9 +4892,34 @@ check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e, } } - /* count related kids */ - for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) { - if ( ce->ce_type == ce_type ) nsibs++; + /* count related kids. + * For entries of type Cft_Misc, only count siblings with same RDN type + */ + if ( ce_type == Cft_Misc ) { + rdn.bv_val = e->e_nname.bv_val; + ptr1 = strchr( rdn.bv_val, '=' ); + assert( ptr1 != NULL ); + + rdn.bv_len = ptr1 - rdn.bv_val; + + for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) { + struct berval rdn2; + if ( ce->ce_type != ce_type ) + continue; + + dnRdn( &ce->ce_entry->e_nname, &rdn2 ); + + ptr1 = strchr( rdn2.bv_val, '=' ); + assert( ptr1 != NULL ); + + rdn2.bv_len = ptr1 - rdn2.bv_val; + if ( bvmatch( &rdn, &rdn2 )) + nsibs++; + } + } else { + for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) { + if ( ce->ce_type == ce_type ) nsibs++; + } } /* account for -1 frontend */ @@ -5887,8 +6059,11 @@ out: ca->reply = msg; } - if ( ca->cleanup ) - ca->cleanup( ca ); + if ( ca->cleanup ) { + i = ca->cleanup( ca ); + if (rc == LDAP_SUCCESS) + rc = i; + } out_noop: if ( rc == LDAP_SUCCESS ) { attrs_free( save_attrs ); @@ -6629,7 +6804,7 @@ config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent, for (; cf; cf=cf->c_sibs, c->depth++) { if ( !cf->c_at_head && !cf->c_cr_head && !cf->c_oc_head && - !cf->c_om_head && !cf->c_syn_head ) continue; + !cf->c_om_head && !cf->c_syn_head && !cf->c_kids ) continue; c->value_dn.bv_val = c->log; LUTIL_SLASHPATH( cf->c_file.bv_val ); bv.bv_val = strrchr(cf->c_file.bv_val, LDAP_DIRSEP[0]); @@ -7210,6 +7385,18 @@ config_tool_entry_next( BackendDB *be ) return NOID; } +static ID +config_tool_dn2id_get( Backend *be, struct berval *dn ) +{ + CfBackInfo *cfb = be->be_private; + BackendInfo *bi = cfb->cb_db.bd_info; + + if ( bi && bi->bi_tool_dn2id_get ) + return bi->bi_tool_dn2id_get( &cfb->cb_db, dn ); + + return NOID; +} + static Entry * config_tool_entry_get( BackendDB *be, ID id ) { @@ -7392,6 +7579,22 @@ config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text ) return NOID; } +static ID +config_tool_entry_modify( BackendDB *be, Entry *e, struct berval *text ) +{ + CfBackInfo *cfb = be->be_private; + BackendInfo *bi = cfb->cb_db.bd_info; + CfEntryInfo *ce, *last; + ConfigArgs ca = {0}; + + ce = config_find_base( cfb->cb_root, &e->e_nname, &last ); + + if ( ce && bi && bi->bi_tool_entry_modify ) + return bi->bi_tool_entry_modify( &cfb->cb_db, e, text ); + + return NOID; +} + static struct { char *name; AttributeDescription **desc; @@ -7487,8 +7690,10 @@ config_back_initialize( BackendInfo *bi ) bi->bi_tool_entry_first = config_tool_entry_first; bi->bi_tool_entry_first_x = config_tool_entry_first_x; bi->bi_tool_entry_next = config_tool_entry_next; + bi->bi_tool_dn2id_get = config_tool_dn2id_get; bi->bi_tool_entry_get = config_tool_entry_get; bi->bi_tool_entry_put = config_tool_entry_put; + bi->bi_tool_entry_modify = config_tool_entry_modify; ca.argv = argv; argv[ 0 ] = "slapd";