Home | History | Annotate | Line # | Download | only in slapd
      1  1.3  christos /*	$NetBSD: bconfig.c,v 1.4 2025/09/05 21:16:25 christos Exp $	*/
      2  1.2  christos 
      3  1.1     lukem /* bconfig.c - the config backend */
      4  1.2  christos /* $OpenLDAP$ */
      5  1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  1.1     lukem  *
      7  1.4  christos  * Copyright 2005-2024 The OpenLDAP Foundation.
      8  1.1     lukem  * All rights reserved.
      9  1.1     lukem  *
     10  1.1     lukem  * Redistribution and use in source and binary forms, with or without
     11  1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     12  1.1     lukem  * Public License.
     13  1.1     lukem  *
     14  1.1     lukem  * A copy of this license is available in the file LICENSE in the
     15  1.1     lukem  * top-level directory of the distribution or, alternatively, at
     16  1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     17  1.1     lukem  */
     18  1.1     lukem /* ACKNOWLEDGEMENTS:
     19  1.1     lukem  * This work was originally developed by Howard Chu for inclusion
     20  1.1     lukem  * in OpenLDAP Software.
     21  1.1     lukem  */
     22  1.1     lukem 
     23  1.2  christos #include <sys/cdefs.h>
     24  1.3  christos __RCSID("$NetBSD: bconfig.c,v 1.4 2025/09/05 21:16:25 christos Exp $");
     25  1.2  christos 
     26  1.1     lukem #include "portable.h"
     27  1.1     lukem 
     28  1.1     lukem #include <stdio.h>
     29  1.1     lukem #include <ac/string.h>
     30  1.1     lukem #include <ac/ctype.h>
     31  1.3  christos #include <ac/dirent.h>
     32  1.1     lukem #include <ac/errno.h>
     33  1.1     lukem #include <sys/stat.h>
     34  1.2  christos #include <ac/unistd.h>
     35  1.1     lukem 
     36  1.1     lukem #include "slap.h"
     37  1.1     lukem 
     38  1.1     lukem #ifdef LDAP_SLAPI
     39  1.1     lukem #include "slapi/slapi.h"
     40  1.1     lukem #endif
     41  1.1     lukem 
     42  1.1     lukem #include <ldif.h>
     43  1.1     lukem #include <lutil.h>
     44  1.1     lukem 
     45  1.3  christos #include "slap-config.h"
     46  1.4  christos #include "slap-cfglog.h"
     47  1.1     lukem 
     48  1.1     lukem #define	CONFIG_RDN	"cn=config"
     49  1.1     lukem #define	SCHEMA_RDN	"cn=schema"
     50  1.1     lukem 
     51  1.1     lukem static struct berval config_rdn = BER_BVC(CONFIG_RDN);
     52  1.1     lukem static struct berval schema_rdn = BER_BVC(SCHEMA_RDN);
     53  1.1     lukem 
     54  1.1     lukem extern int slap_DN_strict;	/* dn.c */
     55  1.1     lukem 
     56  1.1     lukem #ifdef SLAPD_MODULES
     57  1.1     lukem typedef struct modpath_s {
     58  1.1     lukem 	struct modpath_s *mp_next;
     59  1.1     lukem 	struct berval mp_path;
     60  1.1     lukem 	BerVarray mp_loads;
     61  1.1     lukem } ModPaths;
     62  1.1     lukem 
     63  1.1     lukem static ModPaths modpaths, *modlast = &modpaths, *modcur = &modpaths;
     64  1.1     lukem #endif
     65  1.1     lukem 
     66  1.1     lukem typedef struct ConfigFile {
     67  1.1     lukem 	struct ConfigFile *c_sibs;
     68  1.1     lukem 	struct ConfigFile *c_kids;
     69  1.1     lukem 	struct berval c_file;
     70  1.1     lukem 	AttributeType *c_at_head, *c_at_tail;
     71  1.1     lukem 	ContentRule *c_cr_head, *c_cr_tail;
     72  1.1     lukem 	ObjectClass *c_oc_head, *c_oc_tail;
     73  1.1     lukem 	OidMacro *c_om_head, *c_om_tail;
     74  1.2  christos 	Syntax *c_syn_head, *c_syn_tail;
     75  1.1     lukem 	BerVarray c_dseFiles;
     76  1.1     lukem } ConfigFile;
     77  1.1     lukem 
     78  1.1     lukem typedef struct {
     79  1.1     lukem 	ConfigFile *cb_config;
     80  1.1     lukem 	CfEntryInfo *cb_root;
     81  1.1     lukem 	BackendDB	cb_db;	/* underlying database */
     82  1.1     lukem 	int		cb_got_ldif;
     83  1.1     lukem 	int		cb_use_ldif;
     84  1.4  christos 	ldap_pvt_thread_rdwr_t cb_rwlock;
     85  1.1     lukem } CfBackInfo;
     86  1.1     lukem 
     87  1.1     lukem static CfBackInfo cfBackInfo;
     88  1.1     lukem 
     89  1.1     lukem static char	*passwd_salt;
     90  1.2  christos static AccessControl *defacl_parsed = NULL;
     91  1.1     lukem 
     92  1.1     lukem static struct berval cfdir;
     93  1.1     lukem 
     94  1.1     lukem /* Private state */
     95  1.1     lukem static AttributeDescription *cfAd_backend, *cfAd_database, *cfAd_overlay,
     96  1.2  christos 	*cfAd_include, *cfAd_attr, *cfAd_oc, *cfAd_om, *cfAd_syntax;
     97  1.1     lukem 
     98  1.1     lukem static ConfigFile *cfn;
     99  1.1     lukem 
    100  1.1     lukem static Avlnode *CfOcTree;
    101  1.1     lukem 
    102  1.1     lukem /* System schema state */
    103  1.1     lukem extern AttributeType *at_sys_tail;	/* at.c */
    104  1.1     lukem extern ObjectClass *oc_sys_tail;	/* oc.c */
    105  1.1     lukem extern OidMacro *om_sys_tail;	/* oidm.c */
    106  1.2  christos extern Syntax *syn_sys_tail;	/* syntax.c */
    107  1.1     lukem static AttributeType *cf_at_tail;
    108  1.1     lukem static ObjectClass *cf_oc_tail;
    109  1.1     lukem static OidMacro *cf_om_tail;
    110  1.2  christos static Syntax *cf_syn_tail;
    111  1.1     lukem 
    112  1.1     lukem static int config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca,
    113  1.1     lukem 	SlapReply *rs, int *renumber, Operation *op );
    114  1.1     lukem 
    115  1.1     lukem static int config_check_schema( Operation *op, CfBackInfo *cfb );
    116  1.1     lukem 
    117  1.1     lukem static ConfigDriver config_fname;
    118  1.1     lukem static ConfigDriver config_cfdir;
    119  1.1     lukem static ConfigDriver config_generic;
    120  1.1     lukem static ConfigDriver config_search_base;
    121  1.1     lukem static ConfigDriver config_passwd_hash;
    122  1.1     lukem static ConfigDriver config_schema_dn;
    123  1.1     lukem static ConfigDriver config_sizelimit;
    124  1.1     lukem static ConfigDriver config_timelimit;
    125  1.1     lukem static ConfigDriver config_overlay;
    126  1.1     lukem static ConfigDriver config_subordinate;
    127  1.1     lukem static ConfigDriver config_suffix;
    128  1.2  christos #ifdef LDAP_TCP_BUFFER
    129  1.2  christos static ConfigDriver config_tcp_buffer;
    130  1.2  christos #endif /* LDAP_TCP_BUFFER */
    131  1.1     lukem static ConfigDriver config_rootdn;
    132  1.1     lukem static ConfigDriver config_rootpw;
    133  1.1     lukem static ConfigDriver config_restrict;
    134  1.1     lukem static ConfigDriver config_allows;
    135  1.1     lukem static ConfigDriver config_disallows;
    136  1.1     lukem static ConfigDriver config_requires;
    137  1.1     lukem static ConfigDriver config_security;
    138  1.1     lukem static ConfigDriver config_referral;
    139  1.1     lukem static ConfigDriver config_updatedn;
    140  1.1     lukem static ConfigDriver config_updateref;
    141  1.2  christos static ConfigDriver config_extra_attrs;
    142  1.1     lukem static ConfigDriver config_include;
    143  1.1     lukem static ConfigDriver config_obsolete;
    144  1.1     lukem #ifdef HAVE_TLS
    145  1.1     lukem static ConfigDriver config_tls_option;
    146  1.1     lukem static ConfigDriver config_tls_config;
    147  1.1     lukem #endif
    148  1.1     lukem extern ConfigDriver syncrepl_config;
    149  1.1     lukem 
    150  1.1     lukem enum {
    151  1.1     lukem 	CFG_ACL = 1,
    152  1.1     lukem 	CFG_BACKEND,
    153  1.1     lukem 	CFG_DATABASE,
    154  1.1     lukem 	CFG_TLS_RAND,
    155  1.1     lukem 	CFG_TLS_CIPHER,
    156  1.2  christos 	CFG_TLS_PROTOCOL_MIN,
    157  1.1     lukem 	CFG_TLS_CERT_FILE,
    158  1.1     lukem 	CFG_TLS_CERT_KEY,
    159  1.1     lukem 	CFG_TLS_CA_PATH,
    160  1.1     lukem 	CFG_TLS_CA_FILE,
    161  1.1     lukem 	CFG_TLS_DH_FILE,
    162  1.1     lukem 	CFG_TLS_VERIFY,
    163  1.1     lukem 	CFG_TLS_CRLCHECK,
    164  1.1     lukem 	CFG_TLS_CRL_FILE,
    165  1.1     lukem 	CFG_CONCUR,
    166  1.1     lukem 	CFG_THREADS,
    167  1.1     lukem 	CFG_SALT,
    168  1.1     lukem 	CFG_LIMITS,
    169  1.1     lukem 	CFG_RO,
    170  1.1     lukem 	CFG_REWRITE,
    171  1.1     lukem 	CFG_DEPTH,
    172  1.1     lukem 	CFG_OID,
    173  1.1     lukem 	CFG_OC,
    174  1.1     lukem 	CFG_DIT,
    175  1.1     lukem 	CFG_ATTR,
    176  1.1     lukem 	CFG_ATOPT,
    177  1.1     lukem 	CFG_ROOTDSE,
    178  1.1     lukem 	CFG_PLUGIN,
    179  1.1     lukem 	CFG_MODLOAD,
    180  1.1     lukem 	CFG_MODPATH,
    181  1.1     lukem 	CFG_LASTMOD,
    182  1.3  christos 	CFG_LASTBIND,
    183  1.4  christos 	CFG_LASTBIND_PRECISION,
    184  1.1     lukem 	CFG_AZPOLICY,
    185  1.1     lukem 	CFG_AZREGEXP,
    186  1.3  christos 	CFG_AZDUC,
    187  1.3  christos 	CFG_AZDUC_IGNORE,
    188  1.1     lukem 	CFG_SASLSECP,
    189  1.1     lukem 	CFG_SSTR_IF_MAX,
    190  1.1     lukem 	CFG_SSTR_IF_MIN,
    191  1.1     lukem 	CFG_TTHREADS,
    192  1.3  christos 	CFG_MULTIPROVIDER,
    193  1.1     lukem 	CFG_HIDDEN,
    194  1.1     lukem 	CFG_MONITORING,
    195  1.1     lukem 	CFG_SERVERID,
    196  1.1     lukem 	CFG_SORTVALS,
    197  1.1     lukem 	CFG_IX_INTLEN,
    198  1.2  christos 	CFG_SYNTAX,
    199  1.2  christos 	CFG_ACL_ADD,
    200  1.2  christos 	CFG_SYNC_SUBENTRY,
    201  1.2  christos 	CFG_LTHREADS,
    202  1.3  christos 	CFG_IX_HASH64,
    203  1.3  christos 	CFG_DISABLED,
    204  1.3  christos 	CFG_THREADQS,
    205  1.2  christos 	CFG_TLS_ECNAME,
    206  1.3  christos 	CFG_TLS_CACERT,
    207  1.3  christos 	CFG_TLS_CERT,
    208  1.3  christos 	CFG_TLS_KEY,
    209  1.3  christos 
    210  1.1     lukem 	CFG_LAST
    211  1.1     lukem };
    212  1.1     lukem 
    213  1.1     lukem typedef struct {
    214  1.1     lukem 	char *name, *oid;
    215  1.1     lukem } OidRec;
    216  1.1     lukem 
    217  1.1     lukem static OidRec OidMacros[] = {
    218  1.1     lukem 	/* OpenLDAProot:1.12.2 */
    219  1.1     lukem 	{ "OLcfg", "1.3.6.1.4.1.4203.1.12.2" },
    220  1.1     lukem 	{ "OLcfgAt", "OLcfg:3" },
    221  1.1     lukem 	{ "OLcfgGlAt", "OLcfgAt:0" },
    222  1.1     lukem 	{ "OLcfgBkAt", "OLcfgAt:1" },
    223  1.1     lukem 	{ "OLcfgDbAt", "OLcfgAt:2" },
    224  1.1     lukem 	{ "OLcfgOvAt", "OLcfgAt:3" },
    225  1.1     lukem 	{ "OLcfgCtAt", "OLcfgAt:4" },	/* contrib modules */
    226  1.1     lukem 	{ "OLcfgOc", "OLcfg:4" },
    227  1.1     lukem 	{ "OLcfgGlOc", "OLcfgOc:0" },
    228  1.1     lukem 	{ "OLcfgBkOc", "OLcfgOc:1" },
    229  1.1     lukem 	{ "OLcfgDbOc", "OLcfgOc:2" },
    230  1.1     lukem 	{ "OLcfgOvOc", "OLcfgOc:3" },
    231  1.1     lukem 	{ "OLcfgCtOc", "OLcfgOc:4" },	/* contrib modules */
    232  1.1     lukem 
    233  1.1     lukem 	/* Syntaxes. We should just start using the standard names and
    234  1.1     lukem 	 * document that they are predefined and available for users
    235  1.1     lukem 	 * to reference in their own schema. Defining schema without
    236  1.1     lukem 	 * OID macros is for masochists...
    237  1.1     lukem 	 */
    238  1.1     lukem 	{ "OMsyn", "1.3.6.1.4.1.1466.115.121.1" },
    239  1.1     lukem 	{ "OMsBoolean", "OMsyn:7" },
    240  1.1     lukem 	{ "OMsDN", "OMsyn:12" },
    241  1.1     lukem 	{ "OMsDirectoryString", "OMsyn:15" },
    242  1.1     lukem 	{ "OMsIA5String", "OMsyn:26" },
    243  1.1     lukem 	{ "OMsInteger", "OMsyn:27" },
    244  1.1     lukem 	{ "OMsOID", "OMsyn:38" },
    245  1.1     lukem 	{ "OMsOctetString", "OMsyn:40" },
    246  1.1     lukem 	{ NULL, NULL }
    247  1.1     lukem };
    248  1.1     lukem 
    249  1.1     lukem /*
    250  1.1     lukem  * Backend/Database registry
    251  1.1     lukem  *
    252  1.1     lukem  * OLcfg{Bk|Db}{Oc|At}:0		-> common
    253  1.3  christos  * OLcfg{Bk|Db}{Oc|At}:1		-> back-bdb(/back-hdb) (removed)
    254  1.1     lukem  * OLcfg{Bk|Db}{Oc|At}:2		-> back-ldif
    255  1.2  christos  * OLcfg{Bk|Db}{Oc|At}:3		-> back-ldap/meta
    256  1.1     lukem  * OLcfg{Bk|Db}{Oc|At}:4		-> back-monitor
    257  1.1     lukem  * OLcfg{Bk|Db}{Oc|At}:5		-> back-relay
    258  1.4  christos  * OLcfg{Bk|Db}{Oc|At}:6		-> back-sql
    259  1.1     lukem  * OLcfg{Bk|Db}{Oc|At}:7		-> back-sock
    260  1.2  christos  * OLcfg{Bk|Db}{Oc|At}:8		-> back-null
    261  1.2  christos  * OLcfg{Bk|Db}{Oc|At}:9		-> back-passwd
    262  1.4  christos  * OLcfg{Bk|Db}{Oc|At}:10		-> back-shell
    263  1.2  christos  * OLcfg{Bk|Db}{Oc|At}:11		-> back-perl
    264  1.2  christos  * OLcfg{Bk|Db}{Oc|At}:12		-> back-mdb
    265  1.3  christos  * OLcfg{Bk|Db}{Oc|At}:13		-> lloadd
    266  1.1     lukem  */
    267  1.1     lukem 
    268  1.1     lukem /*
    269  1.1     lukem  * Overlay registry
    270  1.1     lukem  *
    271  1.1     lukem  * OLcfgOv{Oc|At}:1			-> syncprov
    272  1.1     lukem  * OLcfgOv{Oc|At}:2			-> pcache
    273  1.1     lukem  * OLcfgOv{Oc|At}:3			-> chain
    274  1.1     lukem  * OLcfgOv{Oc|At}:4			-> accesslog
    275  1.1     lukem  * OLcfgOv{Oc|At}:5			-> valsort
    276  1.1     lukem  * OLcfgOv{Oc|At}:7			-> distproc
    277  1.1     lukem  * OLcfgOv{Oc|At}:8			-> dynlist
    278  1.1     lukem  * OLcfgOv{Oc|At}:9			-> dds
    279  1.1     lukem  * OLcfgOv{Oc|At}:10			-> unique
    280  1.1     lukem  * OLcfgOv{Oc|At}:11			-> refint
    281  1.1     lukem  * OLcfgOv{Oc|At}:12 			-> ppolicy
    282  1.1     lukem  * OLcfgOv{Oc|At}:13			-> constraint
    283  1.1     lukem  * OLcfgOv{Oc|At}:14			-> translucent
    284  1.1     lukem  * OLcfgOv{Oc|At}:15			-> auditlog
    285  1.1     lukem  * OLcfgOv{Oc|At}:16			-> rwm
    286  1.1     lukem  * OLcfgOv{Oc|At}:17			-> dyngroup
    287  1.1     lukem  * OLcfgOv{Oc|At}:18			-> memberof
    288  1.1     lukem  * OLcfgOv{Oc|At}:19			-> collect
    289  1.2  christos  * OLcfgOv{Oc|At}:20			-> retcode
    290  1.2  christos  * OLcfgOv{Oc|At}:21			-> sssvlv
    291  1.3  christos  * OLcfgOv{Oc|At}:22			-> autoca
    292  1.3  christos  * OLcfgOv{Oc|At}:24			-> remoteauth
    293  1.4  christos  * OLcfgOv{Oc|At}:25			-> nestgroup
    294  1.1     lukem  */
    295  1.1     lukem 
    296  1.1     lukem /* alphabetical ordering */
    297  1.1     lukem 
    298  1.1     lukem static ConfigTable config_back_cf_table[] = {
    299  1.1     lukem 	/* This attr is read-only */
    300  1.1     lukem 	{ "", "", 0, 0, 0, ARG_MAGIC,
    301  1.1     lukem 		&config_fname, "( OLcfgGlAt:78 NAME 'olcConfigFile' "
    302  1.1     lukem 			"DESC 'File for slapd configuration directives' "
    303  1.3  christos 			"EQUALITY caseExactMatch "
    304  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    305  1.1     lukem 	{ "", "", 0, 0, 0, ARG_MAGIC,
    306  1.1     lukem 		&config_cfdir, "( OLcfgGlAt:79 NAME 'olcConfigDir' "
    307  1.1     lukem 			"DESC 'Directory for slapd configuration backend' "
    308  1.3  christos 			"EQUALITY caseExactMatch "
    309  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    310  1.1     lukem 	{ "access",	NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC|CFG_ACL,
    311  1.1     lukem 		&config_generic, "( OLcfgGlAt:1 NAME 'olcAccess' "
    312  1.1     lukem 			"DESC 'Access Control List' "
    313  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    314  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    315  1.2  christos 	{ "add_content_acl",	NULL, 0, 0, 0, ARG_MAY_DB|ARG_ON_OFF|ARG_MAGIC|CFG_ACL_ADD,
    316  1.2  christos 		&config_generic, "( OLcfgGlAt:86 NAME 'olcAddContentAcl' "
    317  1.2  christos 			"DESC 'Check ACLs against content of Add ops' "
    318  1.3  christos 			"EQUALITY booleanMatch "
    319  1.2  christos 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    320  1.1     lukem 	{ "allows",	"features", 2, 0, 5, ARG_PRE_DB|ARG_MAGIC,
    321  1.1     lukem 		&config_allows, "( OLcfgGlAt:2 NAME 'olcAllows' "
    322  1.1     lukem 			"DESC 'Allowed set of deprecated features' "
    323  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    324  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    325  1.1     lukem 	{ "argsfile", "file", 2, 2, 0, ARG_STRING,
    326  1.1     lukem 		&slapd_args_file, "( OLcfgGlAt:3 NAME 'olcArgsFile' "
    327  1.1     lukem 			"DESC 'File for slapd command line options' "
    328  1.3  christos 			"EQUALITY caseExactMatch "
    329  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    330  1.1     lukem 	{ "attributeoptions", NULL, 0, 0, 0, ARG_MAGIC|CFG_ATOPT,
    331  1.1     lukem 		&config_generic, "( OLcfgGlAt:5 NAME 'olcAttributeOptions' "
    332  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    333  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    334  1.1     lukem 	{ "attribute",	"attribute", 2, 0, STRLENOF( "attribute" ),
    335  1.1     lukem 		ARG_PAREN|ARG_MAGIC|CFG_ATTR,
    336  1.1     lukem 		&config_generic, "( OLcfgGlAt:4 NAME 'olcAttributeTypes' "
    337  1.1     lukem 			"DESC 'OpenLDAP attributeTypes' "
    338  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    339  1.2  christos 			"SUBSTR caseIgnoreSubstringsMatch "
    340  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
    341  1.1     lukem 				NULL, NULL },
    342  1.3  christos 	{ "authid-rewrite", "rewrite", 2, 0, STRLENOF( "authid-rewrite" ),
    343  1.3  christos 		ARG_MAGIC|CFG_REWRITE, &config_generic,
    344  1.1     lukem 		 "( OLcfgGlAt:6 NAME 'olcAuthIDRewrite' "
    345  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    346  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    347  1.1     lukem 	{ "authz-policy", "policy", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_AZPOLICY,
    348  1.1     lukem 		&config_generic, "( OLcfgGlAt:7 NAME 'olcAuthzPolicy' "
    349  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    350  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    351  1.3  christos 	{ "authz-regexp", "regexp> <DN", 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
    352  1.1     lukem 		&config_generic, "( OLcfgGlAt:8 NAME 'olcAuthzRegexp' "
    353  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    354  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    355  1.1     lukem 	{ "backend", "type", 2, 2, 0, ARG_PRE_DB|ARG_MAGIC|CFG_BACKEND,
    356  1.1     lukem 		&config_generic, "( OLcfgGlAt:9 NAME 'olcBackend' "
    357  1.1     lukem 			"DESC 'A type of backend' "
    358  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    359  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE X-ORDERED 'SIBLINGS' )",
    360  1.1     lukem 				NULL, NULL },
    361  1.1     lukem 	{ "concurrency", "level", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_CONCUR,
    362  1.1     lukem 		&config_generic, "( OLcfgGlAt:10 NAME 'olcConcurrency' "
    363  1.3  christos 			"EQUALITY integerMatch "
    364  1.1     lukem 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    365  1.1     lukem 	{ "conn_max_pending", "max", 2, 2, 0, ARG_INT,
    366  1.1     lukem 		&slap_conn_max_pending, "( OLcfgGlAt:11 NAME 'olcConnMaxPending' "
    367  1.3  christos 			"EQUALITY integerMatch "
    368  1.1     lukem 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    369  1.1     lukem 	{ "conn_max_pending_auth", "max", 2, 2, 0, ARG_INT,
    370  1.1     lukem 		&slap_conn_max_pending_auth, "( OLcfgGlAt:12 NAME 'olcConnMaxPendingAuth' "
    371  1.3  christos 			"EQUALITY integerMatch "
    372  1.1     lukem 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    373  1.1     lukem 	{ "database", "type", 2, 2, 0, ARG_MAGIC|CFG_DATABASE,
    374  1.1     lukem 		&config_generic, "( OLcfgGlAt:13 NAME 'olcDatabase' "
    375  1.1     lukem 			"DESC 'The backend type for a database instance' "
    376  1.1     lukem 			"SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
    377  1.1     lukem 	{ "defaultSearchBase", "dn", 2, 2, 0, ARG_PRE_BI|ARG_PRE_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
    378  1.1     lukem 		&config_search_base, "( OLcfgGlAt:14 NAME 'olcDefaultSearchBase' "
    379  1.3  christos 			"EQUALITY distinguishedNameMatch "
    380  1.1     lukem 			"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
    381  1.3  christos 	{ "disabled", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_DISABLED,
    382  1.3  christos 		&config_generic, "( OLcfgDbAt:0.21 NAME 'olcDisabled' "
    383  1.3  christos 			"EQUALITY booleanMatch "
    384  1.3  christos 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    385  1.1     lukem 	{ "disallows", "features", 2, 0, 8, ARG_PRE_DB|ARG_MAGIC,
    386  1.1     lukem 		&config_disallows, "( OLcfgGlAt:15 NAME 'olcDisallows' "
    387  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    388  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    389  1.1     lukem 	{ "ditcontentrule",	NULL, 0, 0, 0, ARG_MAGIC|CFG_DIT|ARG_NO_DELETE|ARG_NO_INSERT,
    390  1.1     lukem 		&config_generic, "( OLcfgGlAt:16 NAME 'olcDitContentRules' "
    391  1.1     lukem 			"DESC 'OpenLDAP DIT content rules' "
    392  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    393  1.2  christos 			"SUBSTR caseIgnoreSubstringsMatch "
    394  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
    395  1.1     lukem 			NULL, NULL },
    396  1.2  christos 	{ "extra_attrs", "attrlist", 2, 2, 0, ARG_DB|ARG_MAGIC,
    397  1.2  christos 		&config_extra_attrs, "( OLcfgDbAt:0.20 NAME 'olcExtraAttrs' "
    398  1.2  christos 			"EQUALITY caseIgnoreMatch "
    399  1.2  christos 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    400  1.1     lukem 	{ "gentlehup", "on|off", 2, 2, 0,
    401  1.1     lukem #ifdef SIGHUP
    402  1.1     lukem 		ARG_ON_OFF, &global_gentlehup,
    403  1.1     lukem #else
    404  1.1     lukem 		ARG_IGNORED, NULL,
    405  1.1     lukem #endif
    406  1.1     lukem 		"( OLcfgGlAt:17 NAME 'olcGentleHUP' "
    407  1.3  christos 			"EQUALITY booleanMatch "
    408  1.1     lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    409  1.1     lukem 	{ "hidden", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_HIDDEN,
    410  1.1     lukem 		&config_generic, "( OLcfgDbAt:0.17 NAME 'olcHidden' "
    411  1.3  christos 			"EQUALITY booleanMatch "
    412  1.1     lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    413  1.1     lukem 	{ "idletimeout", "timeout", 2, 2, 0, ARG_INT,
    414  1.1     lukem 		&global_idletimeout, "( OLcfgGlAt:18 NAME 'olcIdleTimeout' "
    415  1.3  christos 			"EQUALITY integerMatch "
    416  1.1     lukem 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    417  1.1     lukem 	{ "include", "file", 2, 2, 0, ARG_MAGIC,
    418  1.1     lukem 		&config_include, "( OLcfgGlAt:19 NAME 'olcInclude' "
    419  1.1     lukem 			"SUP labeledURI )", NULL, NULL },
    420  1.3  christos 	{ "index_hash64", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_IX_HASH64,
    421  1.3  christos 		&config_generic, "( OLcfgGlAt:94 NAME 'olcIndexHash64' "
    422  1.3  christos 			"EQUALITY booleanMatch "
    423  1.3  christos 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    424  1.2  christos 	{ "index_substr_if_minlen", "min", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN,
    425  1.1     lukem 		&config_generic, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' "
    426  1.3  christos 			"EQUALITY integerMatch "
    427  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    428  1.3  christos 			{ .v_uint = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT }
    429  1.3  christos 	},
    430  1.2  christos 	{ "index_substr_if_maxlen", "max", 2, 2, 0, ARG_UINT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MAX,
    431  1.1     lukem 		&config_generic, "( OLcfgGlAt:21 NAME 'olcIndexSubstrIfMaxLen' "
    432  1.3  christos 			"EQUALITY integerMatch "
    433  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    434  1.3  christos 			{ .v_uint = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT }
    435  1.3  christos 	},
    436  1.2  christos 	{ "index_substr_any_len", "len", 2, 2, 0, ARG_UINT|ARG_NONZERO,
    437  1.1     lukem 		&index_substr_any_len, "( OLcfgGlAt:22 NAME 'olcIndexSubstrAnyLen' "
    438  1.3  christos 			"EQUALITY integerMatch "
    439  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    440  1.3  christos 			{ .v_uint = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT } },
    441  1.2  christos 	{ "index_substr_any_step", "step", 2, 2, 0, ARG_UINT|ARG_NONZERO,
    442  1.1     lukem 		&index_substr_any_step, "( OLcfgGlAt:23 NAME 'olcIndexSubstrAnyStep' "
    443  1.3  christos 			"EQUALITY integerMatch "
    444  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    445  1.3  christos 			{ .v_uint = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT } },
    446  1.2  christos 	{ "index_intlen", "len", 2, 2, 0, ARG_UINT|ARG_MAGIC|CFG_IX_INTLEN,
    447  1.1     lukem 		&config_generic, "( OLcfgGlAt:84 NAME 'olcIndexIntLen' "
    448  1.3  christos 			"EQUALITY integerMatch "
    449  1.1     lukem 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    450  1.1     lukem 	{ "lastmod", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTMOD,
    451  1.1     lukem 		&config_generic, "( OLcfgDbAt:0.4 NAME 'olcLastMod' "
    452  1.3  christos 			"EQUALITY booleanMatch "
    453  1.3  christos 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    454  1.3  christos 	{ "lastbind", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_LASTBIND,
    455  1.3  christos 		&config_generic, "( OLcfgDbAt:0.22 NAME 'olcLastBind' "
    456  1.3  christos 			"EQUALITY booleanMatch "
    457  1.1     lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    458  1.4  christos 	{ "lastbind-precision", "seconds difference", 2, 2, 0,
    459  1.4  christos 		ARG_DB|ARG_MAGIC|ARG_UINT|CFG_LASTBIND_PRECISION,
    460  1.4  christos 		&config_generic, "( OLcfgDbAt:0.23 NAME 'olcLastBindPrecision' "
    461  1.4  christos 			"EQUALITY integerMatch "
    462  1.4  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    463  1.4  christos 			{ .v_uint = 0 }
    464  1.4  christos 	},
    465  1.2  christos 	{ "ldapsyntax",	"syntax", 2, 0, 0,
    466  1.2  christos 		ARG_PAREN|ARG_MAGIC|CFG_SYNTAX,
    467  1.2  christos 		&config_generic, "( OLcfgGlAt:85 NAME 'olcLdapSyntaxes' "
    468  1.2  christos 			"DESC 'OpenLDAP ldapSyntax' "
    469  1.2  christos 			"EQUALITY caseIgnoreMatch "
    470  1.2  christos 			"SUBSTR caseIgnoreSubstringsMatch "
    471  1.2  christos 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
    472  1.2  christos 				NULL, NULL },
    473  1.1     lukem 	{ "limits", "limits", 2, 0, 0, ARG_DB|ARG_MAGIC|CFG_LIMITS,
    474  1.1     lukem 		&config_generic, "( OLcfgDbAt:0.5 NAME 'olcLimits' "
    475  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    476  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    477  1.2  christos 	{ "listener-threads", "count", 2, 0, 0,
    478  1.2  christos 		ARG_UINT|ARG_MAGIC|CFG_LTHREADS, &config_generic,
    479  1.2  christos 		"( OLcfgGlAt:93 NAME 'olcListenerThreads' "
    480  1.3  christos 			"EQUALITY integerMatch "
    481  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    482  1.3  christos 			{ .v_uint = 1 }
    483  1.3  christos 	},
    484  1.1     lukem 	{ "localSSF", "ssf", 2, 2, 0, ARG_INT,
    485  1.1     lukem 		&local_ssf, "( OLcfgGlAt:26 NAME 'olcLocalSSF' "
    486  1.3  christos 			"EQUALITY integerMatch "
    487  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    488  1.3  christos 			{ .v_int = LDAP_PVT_SASL_LOCAL_SSF } },
    489  1.1     lukem 	{ "logfile", "file", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_LOGFILE,
    490  1.4  christos 		&config_logging, "( OLcfgGlAt:27 NAME 'olcLogFile' "
    491  1.3  christos 			"EQUALITY caseExactMatch "
    492  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    493  1.4  christos 	{ "logfile-format", "debug|syslog-utc|syslog-localtime", 2, 2, 0, ARG_MAGIC|CFG_LOGFILE_FORMAT,
    494  1.4  christos 		&config_logging, "( OLcfgGlAt:104 NAME 'olcLogFileFormat' "
    495  1.4  christos 			"EQUALITY caseIgnoreMatch "
    496  1.4  christos 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    497  1.4  christos 	{ "logfile-only", "on|off", 2, 2, 0, ARG_ON_OFF|ARG_MAGIC|CFG_LOGFILE_ONLY,
    498  1.4  christos 		&config_logging, "( OLcfgGlAt:102 NAME 'olcLogFileOnly' "
    499  1.4  christos 			"EQUALITY booleanMatch "
    500  1.4  christos 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    501  1.4  christos 	{ "logfile-rotate", "max> <Mbyte> <hours", 4, 4, 0, ARG_MAGIC|CFG_LOGFILE_ROTATE,
    502  1.4  christos 		&config_logging, "( OLcfgGlAt:103 NAME 'olcLogFileRotate' "
    503  1.4  christos 			"EQUALITY caseIgnoreMatch "
    504  1.4  christos 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    505  1.4  christos 	{ "loglevel", "level", 2, 0, 0, ARG_MAGIC|CFG_LOGLEVEL,
    506  1.4  christos 		&config_logging, "( OLcfgGlAt:28 NAME 'olcLogLevel' "
    507  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    508  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    509  1.1     lukem 	{ "maxDerefDepth", "depth", 2, 2, 0, ARG_DB|ARG_INT|ARG_MAGIC|CFG_DEPTH,
    510  1.1     lukem 		&config_generic, "( OLcfgDbAt:0.6 NAME 'olcMaxDerefDepth' "
    511  1.3  christos 			"EQUALITY integerMatch "
    512  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    513  1.3  christos 			{ .v_int = SLAPD_DEFAULT_MAXDEREFDEPTH }
    514  1.3  christos 	},
    515  1.3  christos 	{ "maxFilterDepth", "depth", 2, 2, 0, ARG_INT,
    516  1.3  christos 		&slap_max_filter_depth, "( OLcfgGlAt:101 NAME 'olcMaxFilterDepth' "
    517  1.3  christos 			"EQUALITY integerMatch "
    518  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    519  1.3  christos 			{ .v_int = SLAP_MAX_FILTER_DEPTH_DEFAULT }
    520  1.3  christos 	},
    521  1.3  christos 	{ "multiprovider", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_MULTIPROVIDER,
    522  1.3  christos 		&config_generic, "( OLcfgDbAt:0.16 NAME ( 'olcMultiProvider' 'olcMirrorMode' ) "
    523  1.3  christos 			"EQUALITY booleanMatch "
    524  1.1     lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    525  1.1     lukem 	{ "moduleload",	"file", 2, 0, 0,
    526  1.1     lukem #ifdef SLAPD_MODULES
    527  1.1     lukem 		ARG_MAGIC|CFG_MODLOAD|ARG_NO_DELETE, &config_generic,
    528  1.1     lukem #else
    529  1.1     lukem 		ARG_IGNORED, NULL,
    530  1.1     lukem #endif
    531  1.1     lukem 		"( OLcfgGlAt:30 NAME 'olcModuleLoad' "
    532  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    533  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    534  1.1     lukem 	{ "modulepath", "path", 2, 2, 0,
    535  1.1     lukem #ifdef SLAPD_MODULES
    536  1.1     lukem 		ARG_MAGIC|CFG_MODPATH|ARG_NO_DELETE|ARG_NO_INSERT, &config_generic,
    537  1.1     lukem #else
    538  1.1     lukem 		ARG_IGNORED, NULL,
    539  1.1     lukem #endif
    540  1.1     lukem 		"( OLcfgGlAt:31 NAME 'olcModulePath' "
    541  1.3  christos 			"EQUALITY caseExactMatch "
    542  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    543  1.1     lukem 	{ "monitoring", "TRUE|FALSE", 2, 2, 0,
    544  1.1     lukem 		ARG_MAGIC|CFG_MONITORING|ARG_DB|ARG_ON_OFF, &config_generic,
    545  1.1     lukem 		"( OLcfgDbAt:0.18 NAME 'olcMonitoring' "
    546  1.3  christos 			"EQUALITY booleanMatch "
    547  1.1     lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    548  1.1     lukem 	{ "objectclass", "objectclass", 2, 0, 0, ARG_PAREN|ARG_MAGIC|CFG_OC,
    549  1.1     lukem 		&config_generic, "( OLcfgGlAt:32 NAME 'olcObjectClasses' "
    550  1.1     lukem 		"DESC 'OpenLDAP object classes' "
    551  1.1     lukem 		"EQUALITY caseIgnoreMatch "
    552  1.2  christos 		"SUBSTR caseIgnoreSubstringsMatch "
    553  1.1     lukem 		"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )",
    554  1.1     lukem 			NULL, NULL },
    555  1.1     lukem 	{ "objectidentifier", "name> <oid",	3, 3, 0, ARG_MAGIC|CFG_OID,
    556  1.1     lukem 		&config_generic, "( OLcfgGlAt:33 NAME 'olcObjectIdentifier' "
    557  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    558  1.2  christos 			"SUBSTR caseIgnoreSubstringsMatch "
    559  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    560  1.1     lukem 	{ "overlay", "overlay", 2, 2, 0, ARG_MAGIC,
    561  1.1     lukem 		&config_overlay, "( OLcfgGlAt:34 NAME 'olcOverlay' "
    562  1.1     lukem 			"SUP olcDatabase SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
    563  1.1     lukem 	{ "password-crypt-salt-format", "salt", 2, 2, 0, ARG_STRING|ARG_MAGIC|CFG_SALT,
    564  1.1     lukem 		&config_generic, "( OLcfgGlAt:35 NAME 'olcPasswordCryptSaltFormat' "
    565  1.3  christos 			"EQUALITY caseIgnoreMatch "
    566  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    567  1.2  christos 	{ "password-hash", "hash", 2, 0, 0, ARG_MAGIC,
    568  1.1     lukem 		&config_passwd_hash, "( OLcfgGlAt:36 NAME 'olcPasswordHash' "
    569  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    570  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    571  1.1     lukem 	{ "pidfile", "file", 2, 2, 0, ARG_STRING,
    572  1.1     lukem 		&slapd_pid_file, "( OLcfgGlAt:37 NAME 'olcPidFile' "
    573  1.3  christos 			"EQUALITY caseExactMatch "
    574  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    575  1.1     lukem 	{ "plugin", NULL, 0, 0, 0,
    576  1.1     lukem #ifdef LDAP_SLAPI
    577  1.1     lukem 		ARG_MAGIC|CFG_PLUGIN, &config_generic,
    578  1.1     lukem #else
    579  1.1     lukem 		ARG_IGNORED, NULL,
    580  1.1     lukem #endif
    581  1.1     lukem 		"( OLcfgGlAt:38 NAME 'olcPlugin' "
    582  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    583  1.3  christos 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    584  1.1     lukem 	{ "pluginlog", "filename", 2, 2, 0,
    585  1.1     lukem #ifdef LDAP_SLAPI
    586  1.1     lukem 		ARG_STRING, &slapi_log_file,
    587  1.1     lukem #else
    588  1.1     lukem 		ARG_IGNORED, NULL,
    589  1.1     lukem #endif
    590  1.1     lukem 		"( OLcfgGlAt:39 NAME 'olcPluginLogFile' "
    591  1.3  christos 			"EQUALITY caseExactMatch "
    592  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    593  1.1     lukem 	{ "readonly", "on|off", 2, 2, 0, ARG_MAY_DB|ARG_ON_OFF|ARG_MAGIC|CFG_RO,
    594  1.1     lukem 		&config_generic, "( OLcfgGlAt:40 NAME 'olcReadOnly' "
    595  1.3  christos 			"EQUALITY booleanMatch "
    596  1.1     lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    597  1.1     lukem 	{ "referral", "url", 2, 2, 0, ARG_MAGIC,
    598  1.1     lukem 		&config_referral, "( OLcfgGlAt:41 NAME 'olcReferral' "
    599  1.1     lukem 			"SUP labeledURI SINGLE-VALUE )", NULL, NULL },
    600  1.1     lukem 	{ "replica", "host or uri", 2, 0, 0, ARG_DB|ARG_MAGIC,
    601  1.1     lukem 		&config_obsolete, "( OLcfgDbAt:0.7 NAME 'olcReplica' "
    602  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    603  1.1     lukem 			"SUP labeledURI X-ORDERED 'VALUES' )", NULL, NULL },
    604  1.1     lukem 	{ "replica-argsfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
    605  1.1     lukem 		&config_obsolete, "( OLcfgGlAt:43 NAME 'olcReplicaArgsFile' "
    606  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    607  1.1     lukem 	{ "replica-pidfile", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
    608  1.1     lukem 		&config_obsolete, "( OLcfgGlAt:44 NAME 'olcReplicaPidFile' "
    609  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    610  1.1     lukem 	{ "replicationInterval", NULL, 0, 0, 0, ARG_MAY_DB|ARG_MAGIC,
    611  1.1     lukem 		&config_obsolete, "( OLcfgGlAt:45 NAME 'olcReplicationInterval' "
    612  1.1     lukem 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    613  1.1     lukem 	{ "replogfile", "filename", 2, 2, 0, ARG_MAY_DB|ARG_MAGIC,
    614  1.1     lukem 		&config_obsolete, "( OLcfgGlAt:46 NAME 'olcReplogFile' "
    615  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    616  1.1     lukem 	{ "require", "features", 2, 0, 7, ARG_MAY_DB|ARG_MAGIC,
    617  1.1     lukem 		&config_requires, "( OLcfgGlAt:47 NAME 'olcRequires' "
    618  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    619  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    620  1.1     lukem 	{ "restrict", "op_list", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
    621  1.1     lukem 		&config_restrict, "( OLcfgGlAt:48 NAME 'olcRestrict' "
    622  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    623  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    624  1.1     lukem 	{ "reverse-lookup", "on|off", 2, 2, 0,
    625  1.1     lukem #ifdef SLAPD_RLOOKUPS
    626  1.1     lukem 		ARG_ON_OFF, &use_reverse_lookup,
    627  1.1     lukem #else
    628  1.1     lukem 		ARG_IGNORED, NULL,
    629  1.1     lukem #endif
    630  1.1     lukem 		"( OLcfgGlAt:49 NAME 'olcReverseLookup' "
    631  1.3  christos 			"EQUALITY booleanMatch "
    632  1.1     lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    633  1.1     lukem 	{ "rootdn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
    634  1.1     lukem 		&config_rootdn, "( OLcfgDbAt:0.8 NAME 'olcRootDN' "
    635  1.2  christos 			"EQUALITY distinguishedNameMatch "
    636  1.1     lukem 			"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
    637  1.1     lukem 	{ "rootDSE", "file", 2, 2, 0, ARG_MAGIC|CFG_ROOTDSE,
    638  1.1     lukem 		&config_generic, "( OLcfgGlAt:51 NAME 'olcRootDSE' "
    639  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    640  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    641  1.1     lukem 	{ "rootpw", "password", 2, 2, 0, ARG_BERVAL|ARG_DB|ARG_MAGIC,
    642  1.1     lukem 		&config_rootpw, "( OLcfgDbAt:0.9 NAME 'olcRootPW' "
    643  1.3  christos 			"EQUALITY octetStringMatch "
    644  1.3  christos 			"SYNTAX OMsOctetString SINGLE-VALUE )", NULL, NULL },
    645  1.1     lukem 	{ "sasl-authz-policy", NULL, 2, 2, 0, ARG_MAGIC|CFG_AZPOLICY,
    646  1.1     lukem 		&config_generic, NULL, NULL, NULL },
    647  1.2  christos 	{ "sasl-auxprops", NULL, 2, 0, 0,
    648  1.2  christos #ifdef HAVE_CYRUS_SASL
    649  1.2  christos 		ARG_STRING|ARG_UNIQUE, &slap_sasl_auxprops,
    650  1.2  christos #else
    651  1.2  christos 		ARG_IGNORED, NULL,
    652  1.2  christos #endif
    653  1.2  christos 		"( OLcfgGlAt:89 NAME 'olcSaslAuxprops' "
    654  1.3  christos 			"EQUALITY caseIgnoreMatch "
    655  1.3  christos 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    656  1.3  christos 	{ "sasl-auxprops-dontusecopy", NULL, 2, 0, 0,
    657  1.3  christos #if defined(HAVE_CYRUS_SASL) && defined(SLAP_AUXPROP_DONTUSECOPY)
    658  1.3  christos 		ARG_MAGIC|CFG_AZDUC, &config_generic,
    659  1.3  christos #else
    660  1.3  christos 		ARG_IGNORED, NULL,
    661  1.3  christos #endif
    662  1.3  christos 		"( OLcfgGlAt:91 NAME 'olcSaslAuxpropsDontUseCopy' "
    663  1.3  christos 			"EQUALITY caseIgnoreMatch "
    664  1.3  christos 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    665  1.3  christos 	{ "sasl-auxprops-dontusecopy-ignore", "true|FALSE", 2, 0, 0,
    666  1.3  christos #if defined(HAVE_CYRUS_SASL) && defined(SLAP_AUXPROP_DONTUSECOPY)
    667  1.3  christos 		ARG_ON_OFF|CFG_AZDUC_IGNORE, &slap_dontUseCopy_ignore,
    668  1.3  christos #else
    669  1.3  christos 		ARG_IGNORED, NULL,
    670  1.3  christos #endif
    671  1.3  christos 		"( OLcfgGlAt:92 NAME 'olcSaslAuxpropsDontUseCopyIgnore' "
    672  1.3  christos 			"EQUALITY booleanMatch "
    673  1.3  christos 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    674  1.3  christos 	{ "sasl-cbinding", NULL, 2, 2, 0,
    675  1.3  christos #ifdef HAVE_CYRUS_SASL
    676  1.3  christos 		ARG_STRING, &sasl_cbinding,
    677  1.3  christos #else
    678  1.3  christos 		ARG_IGNORED, NULL,
    679  1.3  christos #endif
    680  1.3  christos 		"( OLcfgGlAt:100 NAME 'olcSaslCBinding' "
    681  1.3  christos 			"EQUALITY caseIgnoreMatch "
    682  1.2  christos 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    683  1.1     lukem 	{ "sasl-host", "host", 2, 2, 0,
    684  1.1     lukem #ifdef HAVE_CYRUS_SASL
    685  1.1     lukem 		ARG_STRING|ARG_UNIQUE, &sasl_host,
    686  1.1     lukem #else
    687  1.1     lukem 		ARG_IGNORED, NULL,
    688  1.1     lukem #endif
    689  1.1     lukem 		"( OLcfgGlAt:53 NAME 'olcSaslHost' "
    690  1.3  christos 			"EQUALITY caseIgnoreMatch "
    691  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    692  1.1     lukem 	{ "sasl-realm", "realm", 2, 2, 0,
    693  1.1     lukem #ifdef HAVE_CYRUS_SASL
    694  1.1     lukem 		ARG_STRING|ARG_UNIQUE, &global_realm,
    695  1.1     lukem #else
    696  1.1     lukem 		ARG_IGNORED, NULL,
    697  1.1     lukem #endif
    698  1.1     lukem 		"( OLcfgGlAt:54 NAME 'olcSaslRealm' "
    699  1.3  christos 			"EQUALITY caseExactMatch "
    700  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    701  1.1     lukem 	{ "sasl-regexp", NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
    702  1.1     lukem 		&config_generic, NULL, NULL, NULL },
    703  1.1     lukem 	{ "sasl-secprops", "properties", 2, 2, 0,
    704  1.1     lukem #ifdef HAVE_CYRUS_SASL
    705  1.1     lukem 		ARG_MAGIC|CFG_SASLSECP, &config_generic,
    706  1.1     lukem #else
    707  1.1     lukem 		ARG_IGNORED, NULL,
    708  1.1     lukem #endif
    709  1.1     lukem 		"( OLcfgGlAt:56 NAME 'olcSaslSecProps' "
    710  1.3  christos 			"EQUALITY caseExactMatch "
    711  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    712  1.1     lukem 	{ "saslRegexp",	NULL, 3, 3, 0, ARG_MAGIC|CFG_AZREGEXP,
    713  1.1     lukem 		&config_generic, NULL, NULL, NULL },
    714  1.1     lukem 	{ "schemadn", "dn", 2, 2, 0, ARG_MAY_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
    715  1.1     lukem 		&config_schema_dn, "( OLcfgGlAt:58 NAME 'olcSchemaDN' "
    716  1.2  christos 			"EQUALITY distinguishedNameMatch "
    717  1.1     lukem 			"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
    718  1.1     lukem 	{ "security", "factors", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
    719  1.1     lukem 		&config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' "
    720  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    721  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    722  1.1     lukem 	{ "serverID", "number> <[URI]", 2, 3, 0, ARG_MAGIC|CFG_SERVERID,
    723  1.1     lukem 		&config_generic, "( OLcfgGlAt:81 NAME 'olcServerID' "
    724  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    725  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    726  1.1     lukem 	{ "sizelimit", "limit",	2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
    727  1.1     lukem 		&config_sizelimit, "( OLcfgGlAt:60 NAME 'olcSizeLimit' "
    728  1.3  christos 			"EQUALITY caseExactMatch "
    729  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    730  1.1     lukem 	{ "sockbuf_max_incoming", "max", 2, 2, 0, ARG_BER_LEN_T,
    731  1.1     lukem 		&sockbuf_max_incoming, "( OLcfgGlAt:61 NAME 'olcSockbufMaxIncoming' "
    732  1.3  christos 			"EQUALITY integerMatch "
    733  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    734  1.3  christos 			{ .v_ber_t = SLAP_SB_MAX_INCOMING_DEFAULT } },
    735  1.1     lukem 	{ "sockbuf_max_incoming_auth", "max", 2, 2, 0, ARG_BER_LEN_T,
    736  1.1     lukem 		&sockbuf_max_incoming_auth, "( OLcfgGlAt:62 NAME 'olcSockbufMaxIncomingAuth' "
    737  1.3  christos 			"EQUALITY integerMatch "
    738  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    739  1.3  christos 			{ .v_ber_t = SLAP_SB_MAX_INCOMING_AUTH } },
    740  1.1     lukem 	{ "sortvals", "attr", 2, 0, 0, ARG_MAGIC|CFG_SORTVALS,
    741  1.1     lukem 		&config_generic, "( OLcfgGlAt:83 NAME 'olcSortVals' "
    742  1.1     lukem 			"DESC 'Attributes whose values will always be sorted' "
    743  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    744  1.1     lukem 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    745  1.1     lukem 	{ "subordinate", "[advertise]", 1, 2, 0, ARG_DB|ARG_MAGIC,
    746  1.1     lukem 		&config_subordinate, "( OLcfgDbAt:0.15 NAME 'olcSubordinate' "
    747  1.3  christos 			"EQUALITY caseExactMatch "
    748  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    749  1.1     lukem 	{ "suffix",	"suffix", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
    750  1.1     lukem 		&config_suffix, "( OLcfgDbAt:0.10 NAME 'olcSuffix' "
    751  1.1     lukem 			"EQUALITY distinguishedNameMatch "
    752  1.1     lukem 			"SYNTAX OMsDN )", NULL, NULL },
    753  1.2  christos 	{ "sync_use_subentry", NULL, 0, 0, 0, ARG_ON_OFF|ARG_DB|ARG_MAGIC|CFG_SYNC_SUBENTRY,
    754  1.2  christos 		&config_generic, "( OLcfgDbAt:0.19 NAME 'olcSyncUseSubentry' "
    755  1.2  christos 			"DESC 'Store sync context in a subentry' "
    756  1.3  christos 			"EQUALITY booleanMatch "
    757  1.2  christos 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    758  1.1     lukem 	{ "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
    759  1.1     lukem 		&syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
    760  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    761  1.1     lukem 			"SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
    762  1.2  christos 	{ "tcp-buffer", "[listener=<listener>] [{read|write}=]size", 0, 0, 0,
    763  1.2  christos #ifndef LDAP_TCP_BUFFER
    764  1.2  christos 		ARG_IGNORED, NULL,
    765  1.2  christos #else /* LDAP_TCP_BUFFER */
    766  1.2  christos 		ARG_MAGIC, &config_tcp_buffer,
    767  1.2  christos #endif /* LDAP_TCP_BUFFER */
    768  1.2  christos 			"( OLcfgGlAt:90 NAME 'olcTCPBuffer' "
    769  1.3  christos 			"EQUALITY caseExactMatch "
    770  1.2  christos 			"DESC 'Custom TCP buffer size' "
    771  1.2  christos 			"SYNTAX OMsDirectoryString )", NULL, NULL },
    772  1.1     lukem 	{ "threads", "count", 2, 2, 0,
    773  1.1     lukem 		ARG_INT|ARG_MAGIC|CFG_THREADS, &config_generic,
    774  1.1     lukem 		"( OLcfgGlAt:66 NAME 'olcThreads' "
    775  1.3  christos 			"EQUALITY integerMatch "
    776  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    777  1.3  christos 			{ .v_int = SLAP_MAX_WORKER_THREADS }
    778  1.3  christos 	},
    779  1.3  christos 	{ "threadqueues", "count", 2, 2, 0,
    780  1.3  christos 		ARG_INT|ARG_MAGIC|CFG_THREADQS, &config_generic,
    781  1.3  christos 		"( OLcfgGlAt:95 NAME 'olcThreadQueues' "
    782  1.3  christos 			"EQUALITY integerMatch "
    783  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    784  1.3  christos 			{ .v_int = 1 }
    785  1.3  christos 	},
    786  1.1     lukem 	{ "timelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
    787  1.1     lukem 		&config_timelimit, "( OLcfgGlAt:67 NAME 'olcTimeLimit' "
    788  1.3  christos 			"EQUALITY caseExactMatch "
    789  1.3  christos 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    790  1.3  christos 	{ "TLSCACertificate", NULL, 2, 2, 0,
    791  1.3  christos #ifdef HAVE_TLS
    792  1.3  christos 		CFG_TLS_CACERT|ARG_BINARY|ARG_MAGIC, &config_tls_option,
    793  1.3  christos #else
    794  1.3  christos 		ARG_IGNORED, NULL,
    795  1.3  christos #endif
    796  1.3  christos 		"( OLcfgGlAt:97 NAME 'olcTLSCACertificate' "
    797  1.3  christos 			"DESC 'X.509 certificate, must use ;binary' "
    798  1.3  christos 			"EQUALITY certificateExactMatch "
    799  1.3  christos 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 SINGLE-VALUE )", NULL, NULL },
    800  1.2  christos 	{ "TLSCACertificateFile", NULL, 2, 2, 0,
    801  1.1     lukem #ifdef HAVE_TLS
    802  1.1     lukem 		CFG_TLS_CA_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
    803  1.1     lukem #else
    804  1.1     lukem 		ARG_IGNORED, NULL,
    805  1.1     lukem #endif
    806  1.1     lukem 		"( OLcfgGlAt:68 NAME 'olcTLSCACertificateFile' "
    807  1.3  christos 			"EQUALITY caseExactMatch "
    808  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    809  1.2  christos 	{ "TLSCACertificatePath", NULL,	2, 2, 0,
    810  1.1     lukem #ifdef HAVE_TLS
    811  1.1     lukem 		CFG_TLS_CA_PATH|ARG_STRING|ARG_MAGIC, &config_tls_option,
    812  1.1     lukem #else
    813  1.1     lukem 		ARG_IGNORED, NULL,
    814  1.1     lukem #endif
    815  1.1     lukem 		"( OLcfgGlAt:69 NAME 'olcTLSCACertificatePath' "
    816  1.3  christos 			"EQUALITY caseExactMatch "
    817  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    818  1.3  christos 	{ "TLSCertificate", NULL, 2, 2, 0,
    819  1.3  christos #ifdef HAVE_TLS
    820  1.3  christos 		CFG_TLS_CERT|ARG_BINARY|ARG_MAGIC, &config_tls_option,
    821  1.3  christos #else
    822  1.3  christos 		ARG_IGNORED, NULL,
    823  1.3  christos #endif
    824  1.3  christos 		"( OLcfgGlAt:98 NAME 'olcTLSCertificate' "
    825  1.3  christos 			"DESC 'X.509 certificate, must use ;binary' "
    826  1.3  christos 			"EQUALITY certificateExactMatch "
    827  1.3  christos 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 SINGLE-VALUE )", NULL, NULL },
    828  1.2  christos 	{ "TLSCertificateFile", NULL, 2, 2, 0,
    829  1.1     lukem #ifdef HAVE_TLS
    830  1.1     lukem 		CFG_TLS_CERT_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
    831  1.1     lukem #else
    832  1.1     lukem 		ARG_IGNORED, NULL,
    833  1.1     lukem #endif
    834  1.1     lukem 		"( OLcfgGlAt:70 NAME 'olcTLSCertificateFile' "
    835  1.3  christos 			"EQUALITY caseExactMatch "
    836  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    837  1.3  christos 	{ "TLSCertificateKey", NULL, 2, 2, 0,
    838  1.3  christos #ifdef HAVE_TLS
    839  1.3  christos 		CFG_TLS_KEY|ARG_BINARY|ARG_MAGIC, &config_tls_option,
    840  1.3  christos #else
    841  1.3  christos 		ARG_IGNORED, NULL,
    842  1.3  christos #endif
    843  1.3  christos 		"( OLcfgGlAt:99 NAME 'olcTLSCertificateKey' "
    844  1.3  christos 			"DESC 'X.509 privateKey, must use ;binary' "
    845  1.3  christos 			"EQUALITY privateKeyMatch "
    846  1.3  christos 			"SYNTAX 1.2.840.113549.1.8.1.1 SINGLE-VALUE )", NULL, NULL },
    847  1.2  christos 	{ "TLSCertificateKeyFile", NULL, 2, 2, 0,
    848  1.1     lukem #ifdef HAVE_TLS
    849  1.1     lukem 		CFG_TLS_CERT_KEY|ARG_STRING|ARG_MAGIC, &config_tls_option,
    850  1.1     lukem #else
    851  1.1     lukem 		ARG_IGNORED, NULL,
    852  1.1     lukem #endif
    853  1.1     lukem 		"( OLcfgGlAt:71 NAME 'olcTLSCertificateKeyFile' "
    854  1.3  christos 			"EQUALITY caseExactMatch "
    855  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    856  1.2  christos 	{ "TLSCipherSuite",	NULL, 2, 2, 0,
    857  1.1     lukem #ifdef HAVE_TLS
    858  1.1     lukem 		CFG_TLS_CIPHER|ARG_STRING|ARG_MAGIC, &config_tls_option,
    859  1.1     lukem #else
    860  1.1     lukem 		ARG_IGNORED, NULL,
    861  1.1     lukem #endif
    862  1.1     lukem 		"( OLcfgGlAt:72 NAME 'olcTLSCipherSuite' "
    863  1.3  christos 			"EQUALITY caseExactMatch "
    864  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    865  1.2  christos 	{ "TLSCRLCheck", NULL, 2, 2, 0,
    866  1.3  christos #if defined(HAVE_TLS) && defined(HAVE_OPENSSL)
    867  1.1     lukem 		CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC, &config_tls_config,
    868  1.1     lukem #else
    869  1.1     lukem 		ARG_IGNORED, NULL,
    870  1.1     lukem #endif
    871  1.1     lukem 		"( OLcfgGlAt:73 NAME 'olcTLSCRLCheck' "
    872  1.3  christos 			"EQUALITY caseExactMatch "
    873  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    874  1.2  christos 	{ "TLSCRLFile", NULL, 2, 2, 0,
    875  1.1     lukem #if defined(HAVE_GNUTLS)
    876  1.1     lukem 		CFG_TLS_CRL_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
    877  1.1     lukem #else
    878  1.1     lukem 		ARG_IGNORED, NULL,
    879  1.1     lukem #endif
    880  1.1     lukem 		"( OLcfgGlAt:82 NAME 'olcTLSCRLFile' "
    881  1.3  christos 			"EQUALITY caseExactMatch "
    882  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    883  1.2  christos 	{ "TLSRandFile", NULL, 2, 2, 0,
    884  1.1     lukem #ifdef HAVE_TLS
    885  1.1     lukem 		CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, &config_tls_option,
    886  1.1     lukem #else
    887  1.1     lukem 		ARG_IGNORED, NULL,
    888  1.1     lukem #endif
    889  1.1     lukem 		"( OLcfgGlAt:74 NAME 'olcTLSRandFile' "
    890  1.3  christos 			"EQUALITY caseExactMatch "
    891  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    892  1.2  christos 	{ "TLSVerifyClient", NULL, 2, 2, 0,
    893  1.1     lukem #ifdef HAVE_TLS
    894  1.1     lukem 		CFG_TLS_VERIFY|ARG_STRING|ARG_MAGIC, &config_tls_config,
    895  1.1     lukem #else
    896  1.1     lukem 		ARG_IGNORED, NULL,
    897  1.1     lukem #endif
    898  1.1     lukem 		"( OLcfgGlAt:75 NAME 'olcTLSVerifyClient' "
    899  1.3  christos 			"EQUALITY caseExactMatch "
    900  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    901  1.2  christos 	{ "TLSDHParamFile", NULL, 2, 2, 0,
    902  1.1     lukem #ifdef HAVE_TLS
    903  1.1     lukem 		CFG_TLS_DH_FILE|ARG_STRING|ARG_MAGIC, &config_tls_option,
    904  1.1     lukem #else
    905  1.1     lukem 		ARG_IGNORED, NULL,
    906  1.1     lukem #endif
    907  1.1     lukem 		"( OLcfgGlAt:77 NAME 'olcTLSDHParamFile' "
    908  1.3  christos 			"EQUALITY caseExactMatch "
    909  1.1     lukem 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    910  1.2  christos 	{ "TLSECName", NULL, 2, 2, 0,
    911  1.2  christos #ifdef HAVE_TLS
    912  1.2  christos 		CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC, &config_tls_option,
    913  1.2  christos #else
    914  1.2  christos 		ARG_IGNORED, NULL,
    915  1.2  christos #endif
    916  1.2  christos 		"( OLcfgGlAt:96 NAME 'olcTLSECName' "
    917  1.3  christos 			"EQUALITY caseExactMatch "
    918  1.2  christos 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    919  1.2  christos 	{ "TLSProtocolMin",	NULL, 2, 2, 0,
    920  1.2  christos #ifdef HAVE_TLS
    921  1.2  christos 		CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, &config_tls_config,
    922  1.2  christos #else
    923  1.2  christos 		ARG_IGNORED, NULL,
    924  1.2  christos #endif
    925  1.2  christos 		"( OLcfgGlAt:87 NAME 'olcTLSProtocolMin' "
    926  1.3  christos 			"EQUALITY caseExactMatch "
    927  1.2  christos 			"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
    928  1.1     lukem 	{ "tool-threads", "count", 2, 2, 0, ARG_INT|ARG_MAGIC|CFG_TTHREADS,
    929  1.1     lukem 		&config_generic, "( OLcfgGlAt:80 NAME 'olcToolThreads' "
    930  1.3  christos 			"EQUALITY integerMatch "
    931  1.3  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL,
    932  1.3  christos 			{ .v_int = 1 }
    933  1.3  christos 	},
    934  1.1     lukem 	{ "ucdata-path", "path", 2, 2, 0, ARG_IGNORED,
    935  1.1     lukem 		NULL, NULL, NULL, NULL },
    936  1.1     lukem 	{ "updatedn", "dn", 2, 2, 0, ARG_DB|ARG_DN|ARG_QUOTE|ARG_MAGIC,
    937  1.1     lukem 		&config_updatedn, "( OLcfgDbAt:0.12 NAME 'olcUpdateDN' "
    938  1.3  christos 			"EQUALITY distinguishedNameMatch "
    939  1.1     lukem 			"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
    940  1.1     lukem 	{ "updateref", "url", 2, 2, 0, ARG_DB|ARG_MAGIC,
    941  1.1     lukem 		&config_updateref, "( OLcfgDbAt:0.13 NAME 'olcUpdateRef' "
    942  1.1     lukem 			"EQUALITY caseIgnoreMatch "
    943  1.1     lukem 			"SUP labeledURI )", NULL, NULL },
    944  1.2  christos 	{ "writetimeout", "timeout", 2, 2, 0, ARG_INT,
    945  1.2  christos 		&global_writetimeout, "( OLcfgGlAt:88 NAME 'olcWriteTimeout' "
    946  1.3  christos 			"EQUALITY integerMatch "
    947  1.2  christos 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    948  1.3  christos 	/* Legacy keywords */
    949  1.3  christos 	{ "mirrormode", "on|off", 2, 2, 0, ARG_DB|ARG_ON_OFF|ARG_MAGIC|CFG_MULTIPROVIDER,
    950  1.3  christos 		&config_generic, NULL, NULL, NULL },
    951  1.1     lukem 	{ NULL,	NULL, 0, 0, 0, ARG_IGNORED,
    952  1.1     lukem 		NULL, NULL, NULL, NULL }
    953  1.1     lukem };
    954  1.1     lukem 
    955  1.2  christos /* Need to no-op this keyword for dynamic config */
    956  1.2  christos ConfigTable olcDatabaseDummy[] = {
    957  1.2  christos 	{ "", "", 0, 0, 0, ARG_IGNORED,
    958  1.2  christos 		NULL, "( OLcfgGlAt:13 NAME 'olcDatabase' "
    959  1.2  christos 			"DESC 'The backend type for a database instance' "
    960  1.2  christos 			"SUP olcBackend SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
    961  1.2  christos 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
    962  1.2  christos };
    963  1.2  christos 
    964  1.1     lukem /* Routines to check if a child can be added to this type */
    965  1.1     lukem static ConfigLDAPadd cfAddSchema, cfAddInclude, cfAddDatabase,
    966  1.1     lukem 	cfAddBackend, cfAddModule, cfAddOverlay;
    967  1.1     lukem 
    968  1.1     lukem /* NOTE: be careful when defining array members
    969  1.1     lukem  * that can be conditionally compiled */
    970  1.1     lukem #define CFOC_GLOBAL	cf_ocs[1]
    971  1.1     lukem #define CFOC_SCHEMA	cf_ocs[2]
    972  1.1     lukem #define CFOC_BACKEND	cf_ocs[3]
    973  1.1     lukem #define CFOC_DATABASE	cf_ocs[4]
    974  1.1     lukem #define CFOC_OVERLAY	cf_ocs[5]
    975  1.1     lukem #define CFOC_INCLUDE	cf_ocs[6]
    976  1.1     lukem #define CFOC_FRONTEND	cf_ocs[7]
    977  1.1     lukem #ifdef SLAPD_MODULES
    978  1.1     lukem #define CFOC_MODULE	cf_ocs[8]
    979  1.1     lukem #endif /* SLAPD_MODULES */
    980  1.1     lukem 
    981  1.1     lukem static ConfigOCs cf_ocs[] = {
    982  1.1     lukem 	{ "( OLcfgGlOc:0 "
    983  1.1     lukem 		"NAME 'olcConfig' "
    984  1.1     lukem 		"DESC 'OpenLDAP configuration object' "
    985  1.1     lukem 		"ABSTRACT SUP top )", Cft_Abstract, NULL },
    986  1.1     lukem 	{ "( OLcfgGlOc:1 "
    987  1.1     lukem 		"NAME 'olcGlobal' "
    988  1.1     lukem 		"DESC 'OpenLDAP Global configuration options' "
    989  1.1     lukem 		"SUP olcConfig STRUCTURAL "
    990  1.1     lukem 		"MAY ( cn $ olcConfigFile $ olcConfigDir $ olcAllows $ olcArgsFile $ "
    991  1.1     lukem 		 "olcAttributeOptions $ olcAuthIDRewrite $ "
    992  1.1     lukem 		 "olcAuthzPolicy $ olcAuthzRegexp $ olcConcurrency $ "
    993  1.1     lukem 		 "olcConnMaxPending $ olcConnMaxPendingAuth $ "
    994  1.1     lukem 		 "olcDisallows $ olcGentleHUP $ olcIdleTimeout $ "
    995  1.1     lukem 		 "olcIndexSubstrIfMaxLen $ olcIndexSubstrIfMinLen $ "
    996  1.3  christos 		 "olcIndexSubstrAnyLen $ olcIndexSubstrAnyStep $ olcIndexHash64 $ "
    997  1.3  christos 		 "olcIndexIntLen $ "
    998  1.4  christos 		 "olcListenerThreads $ olcLocalSSF $ olcLogFile $ olcLogFileFormat $ olcLogLevel $ "
    999  1.4  christos 		 "olcLogFileOnly $ olcLogFileRotate $ olcMaxFilterDepth $ "
   1000  1.1     lukem 		 "olcPasswordCryptSaltFormat $ olcPasswordHash $ olcPidFile $ "
   1001  1.1     lukem 		 "olcPluginLogFile $ olcReadOnly $ olcReferral $ "
   1002  1.1     lukem 		 "olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
   1003  1.1     lukem 		 "olcRootDSE $ "
   1004  1.3  christos 		 "olcSaslAuxprops $ olcSaslAuxpropsDontUseCopy $ olcSaslAuxpropsDontUseCopyIgnore $ "
   1005  1.3  christos 		 "olcSaslCBinding $ olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
   1006  1.1     lukem 		 "olcSecurity $ olcServerID $ olcSizeLimit $ "
   1007  1.1     lukem 		 "olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
   1008  1.2  christos 		 "olcTCPBuffer $ "
   1009  1.3  christos 		 "olcThreads $ olcThreadQueues $ "
   1010  1.3  christos 		 "olcTimeLimit $ olcTLSCACertificateFile $ "
   1011  1.1     lukem 		 "olcTLSCACertificatePath $ olcTLSCertificateFile $ "
   1012  1.1     lukem 		 "olcTLSCertificateKeyFile $ olcTLSCipherSuite $ olcTLSCRLCheck $ "
   1013  1.3  christos 		 "olcTLSCACertificate $ olcTLSCertificate $ olcTLSCertificateKey $ "
   1014  1.2  christos 		 "olcTLSRandFile $ olcTLSVerifyClient $ olcTLSDHParamFile $ olcTLSECName $ "
   1015  1.2  christos 		 "olcTLSCRLFile $ olcTLSProtocolMin $ olcToolThreads $ olcWriteTimeout $ "
   1016  1.1     lukem 		 "olcObjectIdentifier $ olcAttributeTypes $ olcObjectClasses $ "
   1017  1.2  christos 		 "olcDitContentRules $ olcLdapSyntaxes ) )", Cft_Global },
   1018  1.1     lukem 	{ "( OLcfgGlOc:2 "
   1019  1.1     lukem 		"NAME 'olcSchemaConfig' "
   1020  1.1     lukem 		"DESC 'OpenLDAP schema object' "
   1021  1.1     lukem 		"SUP olcConfig STRUCTURAL "
   1022  1.2  christos 		"MAY ( cn $ olcObjectIdentifier $ olcLdapSyntaxes $ "
   1023  1.2  christos 		 "olcAttributeTypes $ olcObjectClasses $ olcDitContentRules ) )",
   1024  1.1     lukem 		 	Cft_Schema, NULL, cfAddSchema },
   1025  1.1     lukem 	{ "( OLcfgGlOc:3 "
   1026  1.1     lukem 		"NAME 'olcBackendConfig' "
   1027  1.1     lukem 		"DESC 'OpenLDAP Backend-specific options' "
   1028  1.1     lukem 		"SUP olcConfig STRUCTURAL "
   1029  1.1     lukem 		"MUST olcBackend )", Cft_Backend, NULL, cfAddBackend },
   1030  1.1     lukem 	{ "( OLcfgGlOc:4 "
   1031  1.1     lukem 		"NAME 'olcDatabaseConfig' "
   1032  1.1     lukem 		"DESC 'OpenLDAP Database-specific options' "
   1033  1.1     lukem 		"SUP olcConfig STRUCTURAL "
   1034  1.1     lukem 		"MUST olcDatabase "
   1035  1.3  christos 		"MAY ( olcDisabled $ olcHidden $ olcSuffix $ olcSubordinate $ olcAccess $ "
   1036  1.4  christos 		 "olcAddContentAcl $ olcLastMod $ olcLastBind $ olcLastBindPrecision $ "
   1037  1.4  christos 		 "olcLimits $ olcMaxDerefDepth $ olcPlugin $ olcReadOnly $ olcReplica $ "
   1038  1.1     lukem 		 "olcReplicaArgsFile $ olcReplicaPidFile $ olcReplicationInterval $ "
   1039  1.1     lukem 		 "olcReplogFile $ olcRequires $ olcRestrict $ olcRootDN $ olcRootPW $ "
   1040  1.2  christos 		 "olcSchemaDN $ olcSecurity $ olcSizeLimit $ olcSyncUseSubentry $ olcSyncrepl $ "
   1041  1.3  christos 		 "olcTimeLimit $ olcUpdateDN $ olcUpdateRef $ olcMultiProvider $ "
   1042  1.2  christos 		 "olcMonitoring $ olcExtraAttrs ) )",
   1043  1.1     lukem 		 	Cft_Database, NULL, cfAddDatabase },
   1044  1.1     lukem 	{ "( OLcfgGlOc:5 "
   1045  1.1     lukem 		"NAME 'olcOverlayConfig' "
   1046  1.1     lukem 		"DESC 'OpenLDAP Overlay-specific options' "
   1047  1.1     lukem 		"SUP olcConfig STRUCTURAL "
   1048  1.3  christos 		"MUST olcOverlay "
   1049  1.3  christos 		"MAY olcDisabled )", Cft_Overlay, NULL, cfAddOverlay },
   1050  1.1     lukem 	{ "( OLcfgGlOc:6 "
   1051  1.1     lukem 		"NAME 'olcIncludeFile' "
   1052  1.1     lukem 		"DESC 'OpenLDAP configuration include file' "
   1053  1.1     lukem 		"SUP olcConfig STRUCTURAL "
   1054  1.1     lukem 		"MUST olcInclude "
   1055  1.1     lukem 		"MAY ( cn $ olcRootDSE ) )",
   1056  1.1     lukem 		/* Used to be Cft_Include, that def has been removed */
   1057  1.1     lukem 		Cft_Abstract, NULL, cfAddInclude },
   1058  1.1     lukem 	/* This should be STRUCTURAL like all the other database classes, but
   1059  1.1     lukem 	 * that would mean inheriting all of the olcDatabaseConfig attributes,
   1060  1.1     lukem 	 * which causes them to be merged twice in config_build_entry.
   1061  1.1     lukem 	 */
   1062  1.1     lukem 	{ "( OLcfgGlOc:7 "
   1063  1.1     lukem 		"NAME 'olcFrontendConfig' "
   1064  1.1     lukem 		"DESC 'OpenLDAP frontend configuration' "
   1065  1.1     lukem 		"AUXILIARY "
   1066  1.1     lukem 		"MAY ( olcDefaultSearchBase $ olcPasswordHash $ olcSortVals ) )",
   1067  1.1     lukem 		Cft_Database, NULL, NULL },
   1068  1.1     lukem 	{ "( OLcfgGlOc:8 "
   1069  1.1     lukem 		"NAME 'olcModuleList' "
   1070  1.1     lukem 		"DESC 'OpenLDAP dynamic module info' "
   1071  1.1     lukem 		"SUP olcConfig STRUCTURAL "
   1072  1.1     lukem 		"MAY ( cn $ olcModulePath $ olcModuleLoad ) )",
   1073  1.1     lukem 		Cft_Module, NULL, cfAddModule },
   1074  1.1     lukem 	{ NULL, 0, NULL }
   1075  1.1     lukem };
   1076  1.1     lukem 
   1077  1.1     lukem typedef struct ServerID {
   1078  1.1     lukem 	struct ServerID *si_next;
   1079  1.1     lukem 	struct berval si_url;
   1080  1.1     lukem 	int si_num;
   1081  1.1     lukem } ServerID;
   1082  1.1     lukem 
   1083  1.1     lukem static ServerID *sid_list;
   1084  1.2  christos static ServerID *sid_set;
   1085  1.1     lukem 
   1086  1.1     lukem typedef struct voidList {
   1087  1.1     lukem 	struct voidList *vl_next;
   1088  1.1     lukem 	void *vl_ptr;
   1089  1.1     lukem } voidList;
   1090  1.1     lukem 
   1091  1.1     lukem typedef struct ADlist {
   1092  1.1     lukem 	struct ADlist *al_next;
   1093  1.1     lukem 	AttributeDescription *al_desc;
   1094  1.1     lukem } ADlist;
   1095  1.1     lukem 
   1096  1.1     lukem static ADlist *sortVals;
   1097  1.1     lukem 
   1098  1.3  christos static int new_daemon_threads;
   1099  1.3  christos 
   1100  1.3  christos static int
   1101  1.3  christos config_resize_lthreads(ConfigArgs *c)
   1102  1.3  christos {
   1103  1.3  christos 	return slapd_daemon_resize( new_daemon_threads );
   1104  1.3  christos }
   1105  1.3  christos 
   1106  1.4  christos static int
   1107  1.4  christos config_substr_if_check( ConfigArgs *c )
   1108  1.4  christos {
   1109  1.4  christos 	if ( index_substr_if_maxlen < index_substr_if_minlen ) {
   1110  1.4  christos 		snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1111  1.4  christos 				"attempted to set olcIndexSubstrIfMaxLen shorter than "
   1112  1.4  christos 				"olcIndexSubstrIfMinLen: %u < %u",
   1113  1.4  christos 				index_substr_if_maxlen, index_substr_if_minlen );
   1114  1.4  christos 		Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
   1115  1.4  christos 		return 1;
   1116  1.4  christos 	}
   1117  1.4  christos 	return LDAP_SUCCESS;
   1118  1.4  christos }
   1119  1.4  christos 
   1120  1.4  christos static int
   1121  1.4  christos config_copy_controls( Operation *op, SlapReply *rs )
   1122  1.4  christos {
   1123  1.4  christos 	/* Accumulate response controls so we can return them to client */
   1124  1.4  christos 	if ( rs->sr_ctrls ) {
   1125  1.4  christos 		LDAPControl **prepared = op->o_callback->sc_private,
   1126  1.4  christos 					**received = rs->sr_ctrls;
   1127  1.4  christos 		slap_mask_t oldflags = rs->sr_flags;
   1128  1.4  christos 
   1129  1.4  christos 		rs->sr_ctrls = prepared;
   1130  1.4  christos 		rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
   1131  1.4  christos 		slap_add_ctrls( op, rs, received );
   1132  1.4  christos 		op->o_callback->sc_private = rs->sr_ctrls;
   1133  1.4  christos 
   1134  1.4  christos 		rs->sr_ctrls = received;
   1135  1.4  christos 		rs->sr_flags = oldflags;
   1136  1.4  christos 	}
   1137  1.4  christos 	return 0;
   1138  1.4  christos }
   1139  1.4  christos 
   1140  1.3  christos #define	GOT_CONFIG	1
   1141  1.3  christos #define	GOT_FRONTEND	2
   1142  1.3  christos static int
   1143  1.3  christos config_unique_db;
   1144  1.3  christos 
   1145  1.1     lukem static int
   1146  1.1     lukem config_generic(ConfigArgs *c) {
   1147  1.1     lukem 	int i;
   1148  1.1     lukem 
   1149  1.1     lukem 	if ( c->op == SLAP_CONFIG_EMIT ) {
   1150  1.1     lukem 		int rc = 0;
   1151  1.1     lukem 		switch(c->type) {
   1152  1.1     lukem 		case CFG_CONCUR:
   1153  1.1     lukem 			c->value_int = ldap_pvt_thread_get_concurrency();
   1154  1.1     lukem 			break;
   1155  1.1     lukem 		case CFG_THREADS:
   1156  1.1     lukem 			c->value_int = connection_pool_max;
   1157  1.1     lukem 			break;
   1158  1.3  christos 		case CFG_THREADQS:
   1159  1.3  christos 			c->value_int = connection_pool_queues;
   1160  1.3  christos 			break;
   1161  1.1     lukem 		case CFG_TTHREADS:
   1162  1.1     lukem 			c->value_int = slap_tool_thread_max;
   1163  1.1     lukem 			break;
   1164  1.2  christos 		case CFG_LTHREADS:
   1165  1.2  christos 			c->value_uint = slapd_daemon_threads;
   1166  1.2  christos 			break;
   1167  1.1     lukem 		case CFG_SALT:
   1168  1.1     lukem 			if ( passwd_salt )
   1169  1.1     lukem 				c->value_string = ch_strdup( passwd_salt );
   1170  1.1     lukem 			else
   1171  1.1     lukem 				rc = 1;
   1172  1.1     lukem 			break;
   1173  1.1     lukem 		case CFG_LIMITS:
   1174  1.1     lukem 			if ( c->be->be_limits ) {
   1175  1.1     lukem 				char buf[4096*3];
   1176  1.1     lukem 				struct berval bv;
   1177  1.1     lukem 
   1178  1.1     lukem 				for ( i=0; c->be->be_limits[i]; i++ ) {
   1179  1.1     lukem 					bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
   1180  1.1     lukem 					if ( bv.bv_len >= sizeof( buf ) ) {
   1181  1.1     lukem 						ber_bvarray_free_x( c->rvalue_vals, NULL );
   1182  1.1     lukem 						c->rvalue_vals = NULL;
   1183  1.1     lukem 						rc = 1;
   1184  1.1     lukem 						break;
   1185  1.1     lukem 					}
   1186  1.1     lukem 					bv.bv_val = buf + bv.bv_len;
   1187  1.1     lukem 					limits_unparse( c->be->be_limits[i], &bv,
   1188  1.1     lukem 							sizeof( buf ) - ( bv.bv_val - buf ) );
   1189  1.1     lukem 					bv.bv_len += bv.bv_val - buf;
   1190  1.1     lukem 					bv.bv_val = buf;
   1191  1.1     lukem 					value_add_one( &c->rvalue_vals, &bv );
   1192  1.1     lukem 				}
   1193  1.1     lukem 			}
   1194  1.1     lukem 			if ( !c->rvalue_vals ) rc = 1;
   1195  1.1     lukem 			break;
   1196  1.1     lukem 		case CFG_RO:
   1197  1.2  christos 			c->value_int = (c->be->be_restrictops & SLAP_RESTRICT_READONLY);
   1198  1.1     lukem 			break;
   1199  1.1     lukem 		case CFG_AZPOLICY:
   1200  1.1     lukem 			c->value_string = ch_strdup( slap_sasl_getpolicy());
   1201  1.1     lukem 			break;
   1202  1.1     lukem 		case CFG_AZREGEXP:
   1203  1.1     lukem 			slap_sasl_regexp_unparse( &c->rvalue_vals );
   1204  1.1     lukem 			if ( !c->rvalue_vals ) rc = 1;
   1205  1.1     lukem 			break;
   1206  1.1     lukem #ifdef HAVE_CYRUS_SASL
   1207  1.3  christos #ifdef SLAP_AUXPROP_DONTUSECOPY
   1208  1.3  christos 		case CFG_AZDUC: {
   1209  1.3  christos 			static int duc_done = 0;
   1210  1.3  christos 
   1211  1.3  christos 			/* take the opportunity to initialize with known values */
   1212  1.3  christos 			if ( !duc_done ) {
   1213  1.3  christos 				struct berval duc[] = { BER_BVC("cmusaslsecretOTP"), BER_BVNULL };
   1214  1.3  christos 				int i;
   1215  1.3  christos 
   1216  1.3  christos 				for ( i = 0; !BER_BVISNULL( &duc[ i ] ); i++ ) {
   1217  1.3  christos 					const char *text = NULL;
   1218  1.3  christos 					AttributeDescription *ad = NULL;
   1219  1.3  christos 
   1220  1.3  christos 					if ( slap_bv2ad( &duc[ i ], &ad, &text ) == LDAP_SUCCESS ) {
   1221  1.3  christos 						int gotit = 0;
   1222  1.3  christos 						if ( slap_dontUseCopy_propnames ) {
   1223  1.3  christos 							int j;
   1224  1.3  christos 
   1225  1.3  christos 							for ( j = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ j ] ); j++ ) {
   1226  1.3  christos 								if ( bvmatch( &slap_dontUseCopy_propnames[ j ], &ad->ad_cname ) ) {
   1227  1.3  christos 									gotit = 1;
   1228  1.3  christos 								}
   1229  1.3  christos 							}
   1230  1.3  christos 						}
   1231  1.3  christos 
   1232  1.3  christos 						if ( !gotit ) {
   1233  1.3  christos 							value_add_one( &slap_dontUseCopy_propnames, &ad->ad_cname );
   1234  1.3  christos 						}
   1235  1.3  christos 					}
   1236  1.3  christos 				}
   1237  1.3  christos 
   1238  1.3  christos 				duc_done = 1;
   1239  1.3  christos 			}
   1240  1.3  christos 
   1241  1.3  christos 			if ( slap_dontUseCopy_propnames != NULL ) {
   1242  1.3  christos 				ber_bvarray_dup_x( &c->rvalue_vals, slap_dontUseCopy_propnames, NULL );
   1243  1.3  christos 			} else {
   1244  1.3  christos 				rc = 1;
   1245  1.3  christos 			}
   1246  1.3  christos 			} break;
   1247  1.3  christos #endif /* SLAP_AUXPROP_DONTUSECOPY */
   1248  1.1     lukem 		case CFG_SASLSECP: {
   1249  1.1     lukem 			struct berval bv = BER_BVNULL;
   1250  1.1     lukem 			slap_sasl_secprops_unparse( &bv );
   1251  1.1     lukem 			if ( !BER_BVISNULL( &bv )) {
   1252  1.1     lukem 				ber_bvarray_add( &c->rvalue_vals, &bv );
   1253  1.1     lukem 			} else {
   1254  1.1     lukem 				rc = 1;
   1255  1.1     lukem 			}
   1256  1.1     lukem 			}
   1257  1.1     lukem 			break;
   1258  1.1     lukem #endif
   1259  1.1     lukem 		case CFG_DEPTH:
   1260  1.1     lukem 			c->value_int = c->be->be_max_deref_depth;
   1261  1.1     lukem 			break;
   1262  1.3  christos 		case CFG_DISABLED:
   1263  1.3  christos 			if ( c->bi ) {
   1264  1.3  christos 				/* overlay */
   1265  1.3  christos 				if ( c->bi->bi_flags & SLAPO_BFLAG_DISABLED ) {
   1266  1.3  christos 					c->value_int = 1;
   1267  1.3  christos 				} else {
   1268  1.3  christos 					rc = 1;
   1269  1.3  christos 				}
   1270  1.3  christos 			} else {
   1271  1.3  christos 				/* database */
   1272  1.3  christos 				if ( SLAP_DBDISABLED( c->be )) {
   1273  1.3  christos 					c->value_int = 1;
   1274  1.3  christos 				} else {
   1275  1.3  christos 					rc = 1;
   1276  1.3  christos 				}
   1277  1.3  christos 			}
   1278  1.3  christos 			break;
   1279  1.1     lukem 		case CFG_HIDDEN:
   1280  1.1     lukem 			if ( SLAP_DBHIDDEN( c->be )) {
   1281  1.1     lukem 				c->value_int = 1;
   1282  1.1     lukem 			} else {
   1283  1.1     lukem 				rc = 1;
   1284  1.1     lukem 			}
   1285  1.1     lukem 			break;
   1286  1.1     lukem 		case CFG_OID: {
   1287  1.1     lukem 			ConfigFile *cf = c->ca_private;
   1288  1.1     lukem 			if ( !cf )
   1289  1.1     lukem 				oidm_unparse( &c->rvalue_vals, NULL, NULL, 1 );
   1290  1.1     lukem 			else if ( cf->c_om_head )
   1291  1.1     lukem 				oidm_unparse( &c->rvalue_vals, cf->c_om_head,
   1292  1.1     lukem 					cf->c_om_tail, 0 );
   1293  1.1     lukem 			if ( !c->rvalue_vals )
   1294  1.1     lukem 				rc = 1;
   1295  1.1     lukem 			}
   1296  1.1     lukem 			break;
   1297  1.1     lukem 		case CFG_ATOPT:
   1298  1.1     lukem 			ad_unparse_options( &c->rvalue_vals );
   1299  1.1     lukem 			break;
   1300  1.1     lukem 		case CFG_OC: {
   1301  1.1     lukem 			ConfigFile *cf = c->ca_private;
   1302  1.1     lukem 			if ( !cf )
   1303  1.1     lukem 				oc_unparse( &c->rvalue_vals, NULL, NULL, 1 );
   1304  1.1     lukem 			else if ( cf->c_oc_head )
   1305  1.1     lukem 				oc_unparse( &c->rvalue_vals, cf->c_oc_head,
   1306  1.1     lukem 					cf->c_oc_tail, 0 );
   1307  1.1     lukem 			if ( !c->rvalue_vals )
   1308  1.1     lukem 				rc = 1;
   1309  1.1     lukem 			}
   1310  1.1     lukem 			break;
   1311  1.1     lukem 		case CFG_ATTR: {
   1312  1.1     lukem 			ConfigFile *cf = c->ca_private;
   1313  1.1     lukem 			if ( !cf )
   1314  1.1     lukem 				at_unparse( &c->rvalue_vals, NULL, NULL, 1 );
   1315  1.1     lukem 			else if ( cf->c_at_head )
   1316  1.1     lukem 				at_unparse( &c->rvalue_vals, cf->c_at_head,
   1317  1.1     lukem 					cf->c_at_tail, 0 );
   1318  1.1     lukem 			if ( !c->rvalue_vals )
   1319  1.1     lukem 				rc = 1;
   1320  1.1     lukem 			}
   1321  1.1     lukem 			break;
   1322  1.2  christos 		case CFG_SYNTAX: {
   1323  1.2  christos 			ConfigFile *cf = c->ca_private;
   1324  1.2  christos 			if ( !cf )
   1325  1.2  christos 				syn_unparse( &c->rvalue_vals, NULL, NULL, 1 );
   1326  1.2  christos 			else if ( cf->c_syn_head )
   1327  1.2  christos 				syn_unparse( &c->rvalue_vals, cf->c_syn_head,
   1328  1.2  christos 					cf->c_syn_tail, 0 );
   1329  1.2  christos 			if ( !c->rvalue_vals )
   1330  1.2  christos 				rc = 1;
   1331  1.2  christos 			}
   1332  1.2  christos 			break;
   1333  1.1     lukem 		case CFG_DIT: {
   1334  1.1     lukem 			ConfigFile *cf = c->ca_private;
   1335  1.1     lukem 			if ( !cf )
   1336  1.1     lukem 				cr_unparse( &c->rvalue_vals, NULL, NULL, 1 );
   1337  1.1     lukem 			else if ( cf->c_cr_head )
   1338  1.1     lukem 				cr_unparse( &c->rvalue_vals, cf->c_cr_head,
   1339  1.1     lukem 					cf->c_cr_tail, 0 );
   1340  1.1     lukem 			if ( !c->rvalue_vals )
   1341  1.1     lukem 				rc = 1;
   1342  1.1     lukem 			}
   1343  1.1     lukem 			break;
   1344  1.1     lukem 
   1345  1.1     lukem 		case CFG_ACL: {
   1346  1.1     lukem 			AccessControl *a;
   1347  1.1     lukem 			char *src, *dst, ibuf[11];
   1348  1.1     lukem 			struct berval bv, abv;
   1349  1.2  christos 			for (i=0, a=c->be->be_acl; a; i++,a=a->acl_next) {
   1350  1.1     lukem 				abv.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i );
   1351  1.1     lukem 				if ( abv.bv_len >= sizeof( ibuf ) ) {
   1352  1.1     lukem 					ber_bvarray_free_x( c->rvalue_vals, NULL );
   1353  1.1     lukem 					c->rvalue_vals = NULL;
   1354  1.1     lukem 					i = 0;
   1355  1.1     lukem 					break;
   1356  1.1     lukem 				}
   1357  1.1     lukem 				acl_unparse( a, &bv );
   1358  1.1     lukem 				abv.bv_val = ch_malloc( abv.bv_len + bv.bv_len + 1 );
   1359  1.1     lukem 				AC_MEMCPY( abv.bv_val, ibuf, abv.bv_len );
   1360  1.1     lukem 				/* Turn TAB / EOL into plain space */
   1361  1.1     lukem 				for (src=bv.bv_val,dst=abv.bv_val+abv.bv_len; *src; src++) {
   1362  1.1     lukem 					if (isspace((unsigned char)*src)) *dst++ = ' ';
   1363  1.1     lukem 					else *dst++ = *src;
   1364  1.1     lukem 				}
   1365  1.1     lukem 				*dst = '\0';
   1366  1.1     lukem 				if (dst[-1] == ' ') {
   1367  1.1     lukem 					dst--;
   1368  1.1     lukem 					*dst = '\0';
   1369  1.1     lukem 				}
   1370  1.1     lukem 				abv.bv_len = dst - abv.bv_val;
   1371  1.1     lukem 				ber_bvarray_add( &c->rvalue_vals, &abv );
   1372  1.1     lukem 			}
   1373  1.1     lukem 			rc = (!i);
   1374  1.1     lukem 			break;
   1375  1.1     lukem 		}
   1376  1.2  christos 		case CFG_ACL_ADD:
   1377  1.2  christos 			c->value_int = (SLAP_DBACL_ADD(c->be) != 0);
   1378  1.2  christos 			break;
   1379  1.1     lukem 		case CFG_ROOTDSE: {
   1380  1.1     lukem 			ConfigFile *cf = c->ca_private;
   1381  1.1     lukem 			if ( cf->c_dseFiles ) {
   1382  1.1     lukem 				value_add( &c->rvalue_vals, cf->c_dseFiles );
   1383  1.1     lukem 			} else {
   1384  1.1     lukem 				rc = 1;
   1385  1.1     lukem 			}
   1386  1.1     lukem 			}
   1387  1.1     lukem 			break;
   1388  1.1     lukem 		case CFG_SERVERID:
   1389  1.1     lukem 			if ( sid_list ) {
   1390  1.1     lukem 				ServerID *si;
   1391  1.1     lukem 				struct berval bv;
   1392  1.1     lukem 
   1393  1.1     lukem 				for ( si = sid_list; si; si=si->si_next ) {
   1394  1.1     lukem 					assert( si->si_num >= 0 && si->si_num <= SLAP_SYNC_SID_MAX );
   1395  1.1     lukem 					if ( !BER_BVISEMPTY( &si->si_url )) {
   1396  1.1     lukem 						bv.bv_len = si->si_url.bv_len + 6;
   1397  1.1     lukem 						bv.bv_val = ch_malloc( bv.bv_len );
   1398  1.2  christos 						bv.bv_len = sprintf( bv.bv_val, "%d %s", si->si_num,
   1399  1.1     lukem 							si->si_url.bv_val );
   1400  1.1     lukem 						ber_bvarray_add( &c->rvalue_vals, &bv );
   1401  1.1     lukem 					} else {
   1402  1.1     lukem 						char buf[5];
   1403  1.1     lukem 						bv.bv_val = buf;
   1404  1.1     lukem 						bv.bv_len = sprintf( buf, "%d", si->si_num );
   1405  1.1     lukem 						value_add_one( &c->rvalue_vals, &bv );
   1406  1.1     lukem 					}
   1407  1.1     lukem 				}
   1408  1.1     lukem 			} else {
   1409  1.1     lukem 				rc = 1;
   1410  1.1     lukem 			}
   1411  1.1     lukem 			break;
   1412  1.1     lukem 		case CFG_LASTMOD:
   1413  1.1     lukem 			c->value_int = (SLAP_NOLASTMOD(c->be) == 0);
   1414  1.1     lukem 			break;
   1415  1.3  christos 		case CFG_LASTBIND:
   1416  1.4  christos 			c->value_int = (SLAP_LASTBIND(c->be) != 0);
   1417  1.4  christos 			break;
   1418  1.4  christos 		case CFG_LASTBIND_PRECISION:
   1419  1.4  christos 			c->value_uint = c->be->be_lastbind_precision;
   1420  1.3  christos 			break;
   1421  1.2  christos 		case CFG_SYNC_SUBENTRY:
   1422  1.2  christos 			c->value_int = (SLAP_SYNC_SUBENTRY(c->be) != 0);
   1423  1.2  christos 			break;
   1424  1.3  christos 		case CFG_MULTIPROVIDER:
   1425  1.1     lukem 			if ( SLAP_SHADOW(c->be))
   1426  1.3  christos 				c->value_int = (SLAP_MULTIPROVIDER(c->be) != 0);
   1427  1.1     lukem 			else
   1428  1.1     lukem 				rc = 1;
   1429  1.1     lukem 			break;
   1430  1.1     lukem 		case CFG_MONITORING:
   1431  1.1     lukem 			c->value_int = (SLAP_DBMONITORING(c->be) != 0);
   1432  1.1     lukem 			break;
   1433  1.1     lukem 		case CFG_SSTR_IF_MAX:
   1434  1.2  christos 			c->value_uint = index_substr_if_maxlen;
   1435  1.1     lukem 			break;
   1436  1.1     lukem 		case CFG_SSTR_IF_MIN:
   1437  1.2  christos 			c->value_uint = index_substr_if_minlen;
   1438  1.1     lukem 			break;
   1439  1.3  christos 		case CFG_IX_HASH64:
   1440  1.3  christos 			c->value_int = slap_hash64( -1 );
   1441  1.3  christos 			break;
   1442  1.1     lukem 		case CFG_IX_INTLEN:
   1443  1.1     lukem 			c->value_int = index_intlen;
   1444  1.1     lukem 			break;
   1445  1.1     lukem 		case CFG_SORTVALS: {
   1446  1.1     lukem 			ADlist *sv;
   1447  1.1     lukem 			rc = 1;
   1448  1.1     lukem 			for ( sv = sortVals; sv; sv = sv->al_next ) {
   1449  1.1     lukem 				value_add_one( &c->rvalue_vals, &sv->al_desc->ad_cname );
   1450  1.1     lukem 				rc = 0;
   1451  1.1     lukem 			}
   1452  1.1     lukem 			} break;
   1453  1.1     lukem #ifdef SLAPD_MODULES
   1454  1.1     lukem 		case CFG_MODLOAD: {
   1455  1.1     lukem 			ModPaths *mp = c->ca_private;
   1456  1.1     lukem 			if (mp->mp_loads) {
   1457  1.1     lukem 				int i;
   1458  1.1     lukem 				for (i=0; !BER_BVISNULL(&mp->mp_loads[i]); i++) {
   1459  1.1     lukem 					struct berval bv;
   1460  1.1     lukem 					bv.bv_val = c->log;
   1461  1.1     lukem 					bv.bv_len = snprintf( bv.bv_val, sizeof( c->log ),
   1462  1.1     lukem 						SLAP_X_ORDERED_FMT "%s", i,
   1463  1.1     lukem 						mp->mp_loads[i].bv_val );
   1464  1.1     lukem 					if ( bv.bv_len >= sizeof( c->log ) ) {
   1465  1.1     lukem 						ber_bvarray_free_x( c->rvalue_vals, NULL );
   1466  1.1     lukem 						c->rvalue_vals = NULL;
   1467  1.1     lukem 						break;
   1468  1.1     lukem 					}
   1469  1.1     lukem 					value_add_one( &c->rvalue_vals, &bv );
   1470  1.1     lukem 				}
   1471  1.1     lukem 			}
   1472  1.1     lukem 
   1473  1.1     lukem 			rc = c->rvalue_vals ? 0 : 1;
   1474  1.1     lukem 			}
   1475  1.1     lukem 			break;
   1476  1.1     lukem 		case CFG_MODPATH: {
   1477  1.1     lukem 			ModPaths *mp = c->ca_private;
   1478  1.1     lukem 			if ( !BER_BVISNULL( &mp->mp_path ))
   1479  1.1     lukem 				value_add_one( &c->rvalue_vals, &mp->mp_path );
   1480  1.1     lukem 
   1481  1.1     lukem 			rc = c->rvalue_vals ? 0 : 1;
   1482  1.1     lukem 			}
   1483  1.1     lukem 			break;
   1484  1.1     lukem #endif
   1485  1.1     lukem #ifdef LDAP_SLAPI
   1486  1.1     lukem 		case CFG_PLUGIN:
   1487  1.1     lukem 			slapi_int_plugin_unparse( c->be, &c->rvalue_vals );
   1488  1.1     lukem 			if ( !c->rvalue_vals ) rc = 1;
   1489  1.1     lukem 			break;
   1490  1.1     lukem #endif
   1491  1.1     lukem 		case CFG_REWRITE:
   1492  1.3  christos 			rc = slap_sasl_rewrite_unparse( &c->rvalue_vals );
   1493  1.1     lukem 			break;
   1494  1.1     lukem 		default:
   1495  1.1     lukem 			rc = 1;
   1496  1.1     lukem 		}
   1497  1.1     lukem 		return rc;
   1498  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   1499  1.1     lukem 		int rc = 0;
   1500  1.1     lukem 		switch(c->type) {
   1501  1.3  christos 		/* single-valued attrs */
   1502  1.1     lukem 		case CFG_CONCUR:
   1503  1.3  christos 			/* FIXME: There is currently no way to retrieve the default? */
   1504  1.3  christos 			break;
   1505  1.3  christos 
   1506  1.1     lukem 		case CFG_THREADS:
   1507  1.3  christos 			if ( slapMode & SLAP_SERVER_MODE )
   1508  1.3  christos 				ldap_pvt_thread_pool_maxthreads(&connection_pool,
   1509  1.3  christos 						SLAP_MAX_WORKER_THREADS);
   1510  1.3  christos 			connection_pool_max = SLAP_MAX_WORKER_THREADS;	/* save for reference */
   1511  1.3  christos 			break;
   1512  1.3  christos 
   1513  1.3  christos 		case CFG_THREADQS:
   1514  1.3  christos 			if ( slapMode & SLAP_SERVER_MODE )
   1515  1.3  christos 				ldap_pvt_thread_pool_queues(&connection_pool, 1);
   1516  1.3  christos 			connection_pool_queues = 1;	/* save for reference */
   1517  1.3  christos 			break;
   1518  1.3  christos 
   1519  1.1     lukem 		case CFG_TTHREADS:
   1520  1.3  christos 			slap_tool_thread_max = 1;
   1521  1.3  christos 			break;
   1522  1.3  christos 
   1523  1.2  christos 		case CFG_LTHREADS:
   1524  1.3  christos 			new_daemon_threads = 1;
   1525  1.3  christos 			config_push_cleanup( c, config_resize_lthreads );
   1526  1.3  christos 			break;
   1527  1.3  christos 
   1528  1.1     lukem 		case CFG_AZPOLICY:
   1529  1.3  christos 			slap_sasl_setpolicy( "none" );
   1530  1.3  christos 			break;
   1531  1.3  christos 
   1532  1.1     lukem 		case CFG_DEPTH:
   1533  1.4  christos 			c->be->be_max_deref_depth = c->ca_desc->arg_default.v_int;
   1534  1.3  christos 			break;
   1535  1.3  christos 
   1536  1.1     lukem 		case CFG_LASTMOD:
   1537  1.3  christos 			SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_NOLASTMOD;
   1538  1.3  christos 			break;
   1539  1.3  christos 
   1540  1.3  christos 		case CFG_LASTBIND:
   1541  1.3  christos 			SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_LASTBIND;
   1542  1.3  christos 			break;
   1543  1.3  christos 
   1544  1.1     lukem 		case CFG_MONITORING:
   1545  1.3  christos 			SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MONITORING;
   1546  1.3  christos 			break;
   1547  1.3  christos 
   1548  1.1     lukem 		case CFG_SASLSECP:
   1549  1.3  christos #ifdef HAVE_CYRUS_SASL
   1550  1.3  christos 			slap_sasl_secprops( "" );
   1551  1.3  christos #endif
   1552  1.3  christos 			break;
   1553  1.3  christos 
   1554  1.1     lukem 		case CFG_SSTR_IF_MAX:
   1555  1.4  christos 			index_substr_if_maxlen = c->ca_desc->arg_default.v_uint;
   1556  1.4  christos 			/* ITS#7215 Postpone range check until the entire modify is finished */
   1557  1.4  christos 			config_push_cleanup( c, config_substr_if_check );
   1558  1.3  christos 			break;
   1559  1.3  christos 
   1560  1.1     lukem 		case CFG_SSTR_IF_MIN:
   1561  1.4  christos 			index_substr_if_minlen = c->ca_desc->arg_default.v_uint;
   1562  1.4  christos 			/* ITS#7215 Postpone range check until the entire modify is finished */
   1563  1.4  christos 			config_push_cleanup( c, config_substr_if_check );
   1564  1.3  christos 			break;
   1565  1.3  christos 
   1566  1.2  christos 		case CFG_ACL_ADD:
   1567  1.3  christos 			SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_ACL_ADD;
   1568  1.3  christos 			break;
   1569  1.3  christos 
   1570  1.2  christos 		case CFG_SYNC_SUBENTRY:
   1571  1.3  christos 			SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SYNC_SUBENTRY;
   1572  1.3  christos 			break;
   1573  1.3  christos 
   1574  1.4  christos 		case CFG_LASTBIND_PRECISION:
   1575  1.4  christos 			c->be->be_lastbind_precision = 0;
   1576  1.4  christos 			break;
   1577  1.4  christos 
   1578  1.3  christos 		case CFG_RO:
   1579  1.3  christos 			c->be->be_restrictops &= ~SLAP_RESTRICT_READONLY;
   1580  1.1     lukem 			break;
   1581  1.1     lukem 
   1582  1.3  christos #ifdef LDAP_SLAPI
   1583  1.1     lukem 		case CFG_PLUGIN:
   1584  1.3  christos 			slapi_int_unregister_plugins(c->be, c->valx);
   1585  1.3  christos 			break;
   1586  1.3  christos #endif
   1587  1.3  christos 
   1588  1.3  christos 		/* no-op, requires slapd restart */
   1589  1.1     lukem 		case CFG_MODLOAD:
   1590  1.1     lukem 			snprintf(c->log, sizeof( c->log ), "change requires slapd restart");
   1591  1.1     lukem 			break;
   1592  1.1     lukem 
   1593  1.3  christos 		case CFG_MULTIPROVIDER:
   1594  1.2  christos 			SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW;
   1595  1.2  christos 			if(SLAP_SHADOW(c->be))
   1596  1.2  christos 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
   1597  1.2  christos 			break;
   1598  1.2  christos 
   1599  1.3  christos #if defined(HAVE_CYRUS_SASL) && defined(SLAP_AUXPROP_DONTUSECOPY)
   1600  1.3  christos 		case CFG_AZDUC:
   1601  1.3  christos 			if ( c->valx < 0 ) {
   1602  1.3  christos 				if ( slap_dontUseCopy_propnames != NULL ) {
   1603  1.3  christos 					ber_bvarray_free( slap_dontUseCopy_propnames );
   1604  1.3  christos 					slap_dontUseCopy_propnames = NULL;
   1605  1.3  christos 				}
   1606  1.3  christos 
   1607  1.3  christos 			} else {
   1608  1.3  christos 				int i;
   1609  1.3  christos 
   1610  1.3  christos 				if ( slap_dontUseCopy_propnames == NULL ) {
   1611  1.3  christos 					rc = 1;
   1612  1.3  christos 					break;
   1613  1.3  christos 				}
   1614  1.3  christos 
   1615  1.3  christos 				for ( i = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ i ] ) && i < c->valx; i++ );
   1616  1.3  christos 				if ( i < c->valx ) {
   1617  1.3  christos 					rc = 1;
   1618  1.3  christos 					break;
   1619  1.3  christos 				}
   1620  1.3  christos 				ber_memfree( slap_dontUseCopy_propnames[ i ].bv_val );
   1621  1.3  christos 				for ( ; !BER_BVISNULL( &slap_dontUseCopy_propnames[ i + 1 ] ); i++ ) {
   1622  1.3  christos 					slap_dontUseCopy_propnames[ i ] = slap_dontUseCopy_propnames[ i + 1 ];
   1623  1.3  christos 				}
   1624  1.3  christos 				BER_BVZERO( &slap_dontUseCopy_propnames[ i ] );
   1625  1.3  christos 			}
   1626  1.3  christos 			break;
   1627  1.3  christos #endif /* SLAP_AUXPROP_DONTUSECOPY */
   1628  1.3  christos 
   1629  1.3  christos 		case CFG_AZREGEXP:
   1630  1.3  christos 			rc = slap_sasl_regexp_delete( c->valx );
   1631  1.3  christos 			break;
   1632  1.3  christos 
   1633  1.3  christos 		case CFG_REWRITE:
   1634  1.3  christos 			rc = slap_sasl_rewrite_delete( c->valx );
   1635  1.3  christos 			break;
   1636  1.3  christos 
   1637  1.1     lukem 		case CFG_SALT:
   1638  1.1     lukem 			ch_free( passwd_salt );
   1639  1.1     lukem 			passwd_salt = NULL;
   1640  1.1     lukem 			break;
   1641  1.1     lukem 
   1642  1.1     lukem 		case CFG_SERVERID: {
   1643  1.1     lukem 			ServerID *si, **sip;
   1644  1.1     lukem 
   1645  1.1     lukem 			for ( i=0, si = sid_list, sip = &sid_list;
   1646  1.1     lukem 				si; si = *sip, i++ ) {
   1647  1.1     lukem 				if ( c->valx == -1 || i == c->valx ) {
   1648  1.1     lukem 					*sip = si->si_next;
   1649  1.2  christos 					if ( sid_set == si )
   1650  1.2  christos 						sid_set = NULL;
   1651  1.1     lukem 					ch_free( si );
   1652  1.1     lukem 					if ( c->valx >= 0 )
   1653  1.1     lukem 						break;
   1654  1.1     lukem 				} else {
   1655  1.1     lukem 					sip = &si->si_next;
   1656  1.1     lukem 				}
   1657  1.1     lukem 			}
   1658  1.1     lukem 			}
   1659  1.1     lukem 			break;
   1660  1.1     lukem 		case CFG_HIDDEN:
   1661  1.1     lukem 			c->be->be_flags &= ~SLAP_DBFLAG_HIDDEN;
   1662  1.1     lukem 			break;
   1663  1.1     lukem 
   1664  1.3  christos 		case CFG_DISABLED:
   1665  1.3  christos 			if ( c->bi ) {
   1666  1.4  christos 				if ( c->bi->bi_flags & SLAP_DBFLAG_DISABLED ) {
   1667  1.4  christos 					c->bi->bi_flags &= ~SLAP_DBFLAG_DISABLED;
   1668  1.4  christos 					if ( c->bi->bi_db_open ) {
   1669  1.4  christos 						BackendInfo *bi_orig = c->be->bd_info;
   1670  1.4  christos 						c->be->bd_info = c->bi;
   1671  1.4  christos 						rc = c->bi->bi_db_open( c->be, &c->reply );
   1672  1.4  christos 						c->be->bd_info = bi_orig;
   1673  1.4  christos 					}
   1674  1.3  christos 				}
   1675  1.4  christos 			} else if ( c->be->be_flags & SLAP_DBFLAG_DISABLED ){
   1676  1.3  christos 				c->be->be_flags &= ~SLAP_DBFLAG_DISABLED;
   1677  1.3  christos 				rc = backend_startup_one( c->be, &c->reply );
   1678  1.3  christos 			}
   1679  1.3  christos 			break;
   1680  1.3  christos 
   1681  1.3  christos 		case CFG_IX_HASH64:
   1682  1.3  christos 			slap_hash64( 0 );
   1683  1.3  christos 			break;
   1684  1.3  christos 
   1685  1.1     lukem 		case CFG_IX_INTLEN:
   1686  1.1     lukem 			index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
   1687  1.1     lukem 			index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
   1688  1.1     lukem 				SLAP_INDEX_INTLEN_DEFAULT );
   1689  1.1     lukem 			break;
   1690  1.1     lukem 
   1691  1.1     lukem 		case CFG_ACL:
   1692  1.1     lukem 			if ( c->valx < 0 ) {
   1693  1.2  christos 				acl_destroy( c->be->be_acl );
   1694  1.2  christos 				c->be->be_acl = NULL;
   1695  1.1     lukem 
   1696  1.1     lukem 			} else {
   1697  1.1     lukem 				AccessControl **prev, *a;
   1698  1.1     lukem 				int i;
   1699  1.1     lukem 				for (i=0, prev = &c->be->be_acl; i < c->valx;
   1700  1.1     lukem 					i++ ) {
   1701  1.1     lukem 					a = *prev;
   1702  1.1     lukem 					prev = &a->acl_next;
   1703  1.1     lukem 				}
   1704  1.1     lukem 				a = *prev;
   1705  1.1     lukem 				*prev = a->acl_next;
   1706  1.1     lukem 				acl_free( a );
   1707  1.1     lukem 			}
   1708  1.2  christos 			if ( SLAP_CONFIG( c->be ) && !c->be->be_acl ) {
   1709  1.2  christos 				Debug( LDAP_DEBUG_CONFIG, "config_generic (CFG_ACL): "
   1710  1.2  christos 						"Last explicit ACL for back-config removed. "
   1711  1.3  christos 						"Using hardcoded default\n" );
   1712  1.2  christos 				c->be->be_acl = defacl_parsed;
   1713  1.2  christos 			}
   1714  1.1     lukem 			break;
   1715  1.1     lukem 
   1716  1.1     lukem 		case CFG_OC: {
   1717  1.1     lukem 			CfEntryInfo *ce;
   1718  1.1     lukem 			/* Can be NULL when undoing a failed add */
   1719  1.1     lukem 			if ( c->ca_entry ) {
   1720  1.1     lukem 				ce = c->ca_entry->e_private;
   1721  1.1     lukem 				/* can't modify the hardcoded schema */
   1722  1.1     lukem 				if ( ce->ce_parent->ce_type == Cft_Global )
   1723  1.1     lukem 					return 1;
   1724  1.1     lukem 				}
   1725  1.1     lukem 			}
   1726  1.1     lukem 			cfn = c->ca_private;
   1727  1.1     lukem 			if ( c->valx < 0 ) {
   1728  1.1     lukem 				ObjectClass *oc;
   1729  1.1     lukem 
   1730  1.1     lukem 				for( oc = cfn->c_oc_head; oc; oc_next( &oc )) {
   1731  1.1     lukem 					oc_delete( oc );
   1732  1.1     lukem 					if ( oc  == cfn->c_oc_tail )
   1733  1.1     lukem 						break;
   1734  1.1     lukem 				}
   1735  1.1     lukem 				cfn->c_oc_head = cfn->c_oc_tail = NULL;
   1736  1.1     lukem 			} else {
   1737  1.1     lukem 				ObjectClass *oc, *prev = NULL;
   1738  1.1     lukem 
   1739  1.1     lukem 				for ( i=0, oc=cfn->c_oc_head; i<c->valx; i++) {
   1740  1.1     lukem 					prev = oc;
   1741  1.1     lukem 					oc_next( &oc );
   1742  1.1     lukem 				}
   1743  1.1     lukem 				oc_delete( oc );
   1744  1.1     lukem 				if ( cfn->c_oc_tail == oc ) {
   1745  1.1     lukem 					cfn->c_oc_tail = prev;
   1746  1.1     lukem 				}
   1747  1.1     lukem 				if ( cfn->c_oc_head == oc ) {
   1748  1.1     lukem 					oc_next( &oc );
   1749  1.1     lukem 					cfn->c_oc_head = oc;
   1750  1.1     lukem 				}
   1751  1.1     lukem 			}
   1752  1.1     lukem 			break;
   1753  1.1     lukem 
   1754  1.1     lukem 		case CFG_ATTR: {
   1755  1.1     lukem 			CfEntryInfo *ce;
   1756  1.1     lukem 			/* Can be NULL when undoing a failed add */
   1757  1.1     lukem 			if ( c->ca_entry ) {
   1758  1.1     lukem 				ce = c->ca_entry->e_private;
   1759  1.1     lukem 				/* can't modify the hardcoded schema */
   1760  1.1     lukem 				if ( ce->ce_parent->ce_type == Cft_Global )
   1761  1.1     lukem 					return 1;
   1762  1.1     lukem 				}
   1763  1.1     lukem 			}
   1764  1.1     lukem 			cfn = c->ca_private;
   1765  1.1     lukem 			if ( c->valx < 0 ) {
   1766  1.1     lukem 				AttributeType *at;
   1767  1.1     lukem 
   1768  1.1     lukem 				for( at = cfn->c_at_head; at; at_next( &at )) {
   1769  1.1     lukem 					at_delete( at );
   1770  1.1     lukem 					if ( at  == cfn->c_at_tail )
   1771  1.1     lukem 						break;
   1772  1.1     lukem 				}
   1773  1.1     lukem 				cfn->c_at_head = cfn->c_at_tail = NULL;
   1774  1.1     lukem 			} else {
   1775  1.1     lukem 				AttributeType *at, *prev = NULL;
   1776  1.1     lukem 
   1777  1.1     lukem 				for ( i=0, at=cfn->c_at_head; i<c->valx; i++) {
   1778  1.1     lukem 					prev = at;
   1779  1.1     lukem 					at_next( &at );
   1780  1.1     lukem 				}
   1781  1.1     lukem 				at_delete( at );
   1782  1.1     lukem 				if ( cfn->c_at_tail == at ) {
   1783  1.1     lukem 					cfn->c_at_tail = prev;
   1784  1.1     lukem 				}
   1785  1.1     lukem 				if ( cfn->c_at_head == at ) {
   1786  1.1     lukem 					at_next( &at );
   1787  1.1     lukem 					cfn->c_at_head = at;
   1788  1.1     lukem 				}
   1789  1.1     lukem 			}
   1790  1.1     lukem 			break;
   1791  1.2  christos 
   1792  1.2  christos 		case CFG_SYNTAX: {
   1793  1.2  christos 			CfEntryInfo *ce;
   1794  1.2  christos 			/* Can be NULL when undoing a failed add */
   1795  1.2  christos 			if ( c->ca_entry ) {
   1796  1.2  christos 				ce = c->ca_entry->e_private;
   1797  1.2  christos 				/* can't modify the hardcoded schema */
   1798  1.2  christos 				if ( ce->ce_parent->ce_type == Cft_Global )
   1799  1.2  christos 					return 1;
   1800  1.2  christos 				}
   1801  1.2  christos 			}
   1802  1.2  christos 			cfn = c->ca_private;
   1803  1.2  christos 			if ( c->valx < 0 ) {
   1804  1.2  christos 				Syntax *syn;
   1805  1.2  christos 
   1806  1.2  christos 				for( syn = cfn->c_syn_head; syn; syn_next( &syn )) {
   1807  1.2  christos 					syn_delete( syn );
   1808  1.2  christos 					if ( syn == cfn->c_syn_tail )
   1809  1.2  christos 						break;
   1810  1.2  christos 				}
   1811  1.2  christos 				cfn->c_syn_head = cfn->c_syn_tail = NULL;
   1812  1.2  christos 			} else {
   1813  1.2  christos 				Syntax *syn, *prev = NULL;
   1814  1.2  christos 
   1815  1.2  christos 				for ( i = 0, syn = cfn->c_syn_head; i < c->valx; i++) {
   1816  1.2  christos 					prev = syn;
   1817  1.2  christos 					syn_next( &syn );
   1818  1.2  christos 				}
   1819  1.2  christos 				syn_delete( syn );
   1820  1.2  christos 				if ( cfn->c_syn_tail == syn ) {
   1821  1.2  christos 					cfn->c_syn_tail = prev;
   1822  1.2  christos 				}
   1823  1.2  christos 				if ( cfn->c_syn_head == syn ) {
   1824  1.2  christos 					syn_next( &syn );
   1825  1.2  christos 					cfn->c_syn_head = syn;
   1826  1.2  christos 				}
   1827  1.2  christos 			}
   1828  1.2  christos 			break;
   1829  1.1     lukem 		case CFG_SORTVALS:
   1830  1.1     lukem 			if ( c->valx < 0 ) {
   1831  1.1     lukem 				ADlist *sv;
   1832  1.1     lukem 				for ( sv = sortVals; sv; sv = sortVals ) {
   1833  1.1     lukem 					sortVals = sv->al_next;
   1834  1.1     lukem 					sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
   1835  1.1     lukem 					ch_free( sv );
   1836  1.1     lukem 				}
   1837  1.1     lukem 			} else {
   1838  1.1     lukem 				ADlist *sv, **prev;
   1839  1.1     lukem 				int i = 0;
   1840  1.1     lukem 
   1841  1.1     lukem 				for ( prev = &sortVals, sv = sortVals; i < c->valx; i++ ) {
   1842  1.1     lukem 					prev = &sv->al_next;
   1843  1.1     lukem 					sv = sv->al_next;
   1844  1.1     lukem 				}
   1845  1.1     lukem 				sv->al_desc->ad_type->sat_flags &= ~SLAP_AT_SORTED_VAL;
   1846  1.1     lukem 				*prev = sv->al_next;
   1847  1.1     lukem 				ch_free( sv );
   1848  1.1     lukem 			}
   1849  1.1     lukem 			break;
   1850  1.1     lukem 
   1851  1.1     lukem 		case CFG_LIMITS:
   1852  1.1     lukem 			/* FIXME: there is no limits_free function */
   1853  1.2  christos 			if ( c->valx < 0 ) {
   1854  1.2  christos 				limits_destroy( c->be->be_limits );
   1855  1.2  christos 				c->be->be_limits = NULL;
   1856  1.2  christos 
   1857  1.2  christos 			} else {
   1858  1.2  christos 				int cnt, num = -1;
   1859  1.2  christos 
   1860  1.2  christos 				if ( c->be->be_limits ) {
   1861  1.2  christos 					for ( num = 0; c->be->be_limits[ num ]; num++ )
   1862  1.2  christos 						/* just count */ ;
   1863  1.2  christos 				}
   1864  1.2  christos 
   1865  1.2  christos 				if ( c->valx >= num ) {
   1866  1.2  christos 					return 1;
   1867  1.2  christos 				}
   1868  1.2  christos 
   1869  1.2  christos 				if ( num == 1 ) {
   1870  1.2  christos 					limits_destroy( c->be->be_limits );
   1871  1.2  christos 					c->be->be_limits = NULL;
   1872  1.2  christos 
   1873  1.2  christos 				} else {
   1874  1.2  christos 					limits_free_one( c->be->be_limits[ c->valx ] );
   1875  1.2  christos 
   1876  1.2  christos 					for ( cnt = c->valx; cnt < num; cnt++ ) {
   1877  1.2  christos 						c->be->be_limits[ cnt ] = c->be->be_limits[ cnt + 1 ];
   1878  1.2  christos 					}
   1879  1.2  christos 				}
   1880  1.2  christos 			}
   1881  1.2  christos 			break;
   1882  1.2  christos 
   1883  1.1     lukem 		case CFG_ATOPT:
   1884  1.1     lukem 			/* FIXME: there is no ad_option_free function */
   1885  1.1     lukem 		case CFG_ROOTDSE:
   1886  1.1     lukem 			/* FIXME: there is no way to remove attributes added by
   1887  1.1     lukem 				a DSE file */
   1888  1.1     lukem 		case CFG_OID:
   1889  1.1     lukem 		case CFG_DIT:
   1890  1.1     lukem 		case CFG_MODPATH:
   1891  1.1     lukem 		default:
   1892  1.1     lukem 			rc = 1;
   1893  1.1     lukem 			break;
   1894  1.1     lukem 		}
   1895  1.1     lukem 		return rc;
   1896  1.1     lukem 	}
   1897  1.1     lukem 
   1898  1.1     lukem 	switch(c->type) {
   1899  1.1     lukem 		case CFG_BACKEND:
   1900  1.1     lukem 			if(!(c->bi = backend_info(c->argv[1]))) {
   1901  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] );
   1902  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
   1903  1.1     lukem 					c->log, c->cr_msg, c->argv[1] );
   1904  1.1     lukem 				return(1);
   1905  1.1     lukem 			}
   1906  1.3  christos 			if ( c->bi->bi_flags & SLAP_BFLAG_STANDALONE ) {
   1907  1.3  christos 				c->bi->bi_nDB++;
   1908  1.3  christos 				nbackends++;
   1909  1.3  christos 			}
   1910  1.3  christos 			c->be = NULL;
   1911  1.1     lukem 			break;
   1912  1.1     lukem 
   1913  1.1     lukem 		case CFG_DATABASE:
   1914  1.1     lukem 			c->bi = NULL;
   1915  1.1     lukem 			/* NOTE: config is always the first backend!
   1916  1.1     lukem 			 */
   1917  1.1     lukem 			if ( !strcasecmp( c->argv[1], "config" )) {
   1918  1.3  christos 				if (config_unique_db & GOT_CONFIG) {
   1919  1.3  christos 					sprintf( c->cr_msg, "config DB already defined");
   1920  1.3  christos 					return(1);
   1921  1.3  christos 				}
   1922  1.1     lukem 				c->be = LDAP_STAILQ_FIRST(&backendDB);
   1923  1.3  christos 				config_unique_db |= GOT_CONFIG;
   1924  1.1     lukem 			} else if ( !strcasecmp( c->argv[1], "frontend" )) {
   1925  1.3  christos 				if (config_unique_db & GOT_FRONTEND) {
   1926  1.3  christos 					sprintf( c->cr_msg, "frontend DB already defined");
   1927  1.3  christos 					return(1);
   1928  1.3  christos 				}
   1929  1.1     lukem 				c->be = frontendDB;
   1930  1.3  christos 				config_unique_db |= GOT_FRONTEND;
   1931  1.1     lukem 			} else {
   1932  1.1     lukem 				c->be = backend_db_init(c->argv[1], NULL, c->valx, &c->reply);
   1933  1.1     lukem 				if ( !c->be ) {
   1934  1.1     lukem 					if ( c->cr_msg[0] == 0 )
   1935  1.1     lukem 						snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> failed init", c->argv[0] );
   1936  1.1     lukem 					Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n", c->log, c->cr_msg, c->argv[1] );
   1937  1.1     lukem 					return(1);
   1938  1.1     lukem 				}
   1939  1.1     lukem 			}
   1940  1.1     lukem 			break;
   1941  1.1     lukem 
   1942  1.1     lukem 		case CFG_CONCUR:
   1943  1.1     lukem 			ldap_pvt_thread_set_concurrency(c->value_int);
   1944  1.1     lukem 			break;
   1945  1.1     lukem 
   1946  1.1     lukem 		case CFG_THREADS:
   1947  1.1     lukem 			if ( c->value_int < 2 ) {
   1948  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1949  1.1     lukem 					"threads=%d smaller than minimum value 2",
   1950  1.1     lukem 					c->value_int );
   1951  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
   1952  1.3  christos 					c->log, c->cr_msg );
   1953  1.1     lukem 				return 1;
   1954  1.1     lukem 
   1955  1.1     lukem 			} else if ( c->value_int > 2 * SLAP_MAX_WORKER_THREADS ) {
   1956  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1957  1.1     lukem 					"warning, threads=%d larger than twice the default (2*%d=%d); YMMV",
   1958  1.1     lukem 					c->value_int, SLAP_MAX_WORKER_THREADS, 2 * SLAP_MAX_WORKER_THREADS );
   1959  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
   1960  1.3  christos 					c->log, c->cr_msg );
   1961  1.1     lukem 			}
   1962  1.1     lukem 			if ( slapMode & SLAP_SERVER_MODE )
   1963  1.1     lukem 				ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
   1964  1.1     lukem 			connection_pool_max = c->value_int;	/* save for reference */
   1965  1.1     lukem 			break;
   1966  1.1     lukem 
   1967  1.3  christos 		case CFG_THREADQS:
   1968  1.3  christos 			if ( c->value_int < 1 ) {
   1969  1.3  christos 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1970  1.3  christos 					"threadqueues=%d smaller than minimum value 1",
   1971  1.3  christos 					c->value_int );
   1972  1.3  christos 				Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
   1973  1.3  christos 					c->log, c->cr_msg );
   1974  1.3  christos 				return 1;
   1975  1.3  christos 			}
   1976  1.3  christos 			if ( slapMode & SLAP_SERVER_MODE )
   1977  1.3  christos 				ldap_pvt_thread_pool_queues(&connection_pool, c->value_int);
   1978  1.3  christos 			connection_pool_queues = c->value_int;	/* save for reference */
   1979  1.3  christos 			break;
   1980  1.3  christos 
   1981  1.1     lukem 		case CFG_TTHREADS:
   1982  1.1     lukem 			if ( slapMode & SLAP_TOOL_MODE )
   1983  1.1     lukem 				ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
   1984  1.1     lukem 			slap_tool_thread_max = c->value_int;	/* save for reference */
   1985  1.1     lukem 			break;
   1986  1.1     lukem 
   1987  1.2  christos 		case CFG_LTHREADS:
   1988  1.3  christos 			if ( c->value_uint < 1 ) {
   1989  1.3  christos 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
   1990  1.3  christos 					"listenerthreads=%u smaller than minimum value 1",
   1991  1.3  christos 					c->value_uint );
   1992  1.3  christos 				Debug(LDAP_DEBUG_ANY, "%s: %s.\n",
   1993  1.3  christos 					c->log, c->cr_msg );
   1994  1.3  christos 				return 1;
   1995  1.3  christos 			}
   1996  1.2  christos 			{ int mask = 0;
   1997  1.2  christos 			/* use a power of two */
   1998  1.2  christos 			while (c->value_uint > 1) {
   1999  1.2  christos 				c->value_uint >>= 1;
   2000  1.2  christos 				mask <<= 1;
   2001  1.2  christos 				mask |= 1;
   2002  1.2  christos 			}
   2003  1.3  christos 			new_daemon_threads = mask+1;
   2004  1.3  christos 			config_push_cleanup( c, config_resize_lthreads );
   2005  1.2  christos 			}
   2006  1.2  christos 			break;
   2007  1.2  christos 
   2008  1.1     lukem 		case CFG_SALT:
   2009  1.1     lukem 			if ( passwd_salt ) ch_free( passwd_salt );
   2010  1.1     lukem 			passwd_salt = c->value_string;
   2011  1.1     lukem 			lutil_salt_format(passwd_salt);
   2012  1.1     lukem 			break;
   2013  1.1     lukem 
   2014  1.1     lukem 		case CFG_LIMITS:
   2015  1.1     lukem 			if(limits_parse(c->be, c->fname, c->lineno, c->argc, c->argv))
   2016  1.1     lukem 				return(1);
   2017  1.1     lukem 			break;
   2018  1.1     lukem 
   2019  1.1     lukem 		case CFG_RO:
   2020  1.1     lukem 			if(c->value_int)
   2021  1.2  christos 				c->be->be_restrictops |= SLAP_RESTRICT_READONLY;
   2022  1.1     lukem 			else
   2023  1.2  christos 				c->be->be_restrictops &= ~SLAP_RESTRICT_READONLY;
   2024  1.1     lukem 			break;
   2025  1.1     lukem 
   2026  1.1     lukem 		case CFG_AZPOLICY:
   2027  1.1     lukem 			ch_free(c->value_string);
   2028  1.1     lukem 			if (slap_sasl_setpolicy( c->argv[1] )) {
   2029  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
   2030  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
   2031  1.1     lukem 					c->log, c->cr_msg, c->argv[1] );
   2032  1.1     lukem 				return(1);
   2033  1.1     lukem 			}
   2034  1.1     lukem 			break;
   2035  1.1     lukem 
   2036  1.1     lukem 		case CFG_AZREGEXP:
   2037  1.3  christos 			if (slap_sasl_regexp_config( c->argv[1], c->argv[2], c->valx ))
   2038  1.1     lukem 				return(1);
   2039  1.1     lukem 			break;
   2040  1.1     lukem 
   2041  1.1     lukem #ifdef HAVE_CYRUS_SASL
   2042  1.3  christos #ifdef SLAP_AUXPROP_DONTUSECOPY
   2043  1.3  christos 		case CFG_AZDUC: {
   2044  1.3  christos 			int arg, cnt;
   2045  1.3  christos 
   2046  1.3  christos 			for ( arg = 1; arg < c->argc; arg++ ) {
   2047  1.3  christos 				int duplicate = 0, err;
   2048  1.3  christos 				AttributeDescription *ad = NULL;
   2049  1.3  christos 				const char *text = NULL;
   2050  1.3  christos 
   2051  1.3  christos 				err = slap_str2ad( c->argv[ arg ], &ad, &text );
   2052  1.3  christos 				if ( err != LDAP_SUCCESS ) {
   2053  1.3  christos 					snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s>: attr #%d (\"%s\") unknown (err=%d \"%s\"; ignored)",
   2054  1.3  christos 						c->argv[0], arg, c->argv[ arg ], err, text );
   2055  1.3  christos 					Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   2056  1.3  christos 						c->log, c->cr_msg );
   2057  1.3  christos 
   2058  1.3  christos 				} else {
   2059  1.3  christos 					if ( slap_dontUseCopy_propnames != NULL ) {
   2060  1.3  christos 						for ( cnt = 0; !BER_BVISNULL( &slap_dontUseCopy_propnames[ cnt ] ); cnt++ ) {
   2061  1.3  christos 							if ( bvmatch( &slap_dontUseCopy_propnames[ cnt ], &ad->ad_cname ) ) {
   2062  1.3  christos 								duplicate = 1;
   2063  1.3  christos 								break;
   2064  1.3  christos 							}
   2065  1.3  christos 						}
   2066  1.3  christos 					}
   2067  1.3  christos 
   2068  1.3  christos 					if ( duplicate ) {
   2069  1.3  christos 						snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s>: attr #%d (\"%s\") already defined (ignored)",
   2070  1.3  christos 							c->argv[0], arg, ad->ad_cname.bv_val);
   2071  1.3  christos 						Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   2072  1.3  christos 							c->log, c->cr_msg );
   2073  1.3  christos 						continue;
   2074  1.3  christos 					}
   2075  1.3  christos 
   2076  1.3  christos 					value_add_one( &slap_dontUseCopy_propnames, &ad->ad_cname );
   2077  1.3  christos 				}
   2078  1.3  christos 			}
   2079  1.3  christos 
   2080  1.3  christos 			} break;
   2081  1.3  christos #endif /* SLAP_AUXPROP_DONTUSECOPY */
   2082  1.3  christos 
   2083  1.1     lukem 		case CFG_SASLSECP:
   2084  1.1     lukem 			{
   2085  1.1     lukem 			char *txt = slap_sasl_secprops( c->argv[1] );
   2086  1.1     lukem 			if ( txt ) {
   2087  1.1     lukem 				snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> %s",
   2088  1.1     lukem 					c->argv[0], txt );
   2089  1.3  christos 				Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
   2090  1.1     lukem 				return(1);
   2091  1.1     lukem 			}
   2092  1.1     lukem 			break;
   2093  1.1     lukem 			}
   2094  1.1     lukem #endif
   2095  1.1     lukem 
   2096  1.1     lukem 		case CFG_DEPTH:
   2097  1.1     lukem 			c->be->be_max_deref_depth = c->value_int;
   2098  1.1     lukem 			break;
   2099  1.1     lukem 
   2100  1.1     lukem 		case CFG_OID: {
   2101  1.1     lukem 			OidMacro *om;
   2102  1.1     lukem 
   2103  1.1     lukem 			if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
   2104  1.1     lukem 				cfn = c->ca_private;
   2105  1.1     lukem 			if(parse_oidm(c, 1, &om))
   2106  1.1     lukem 				return(1);
   2107  1.1     lukem 			if (!cfn->c_om_head) cfn->c_om_head = om;
   2108  1.1     lukem 			cfn->c_om_tail = om;
   2109  1.1     lukem 			}
   2110  1.1     lukem 			break;
   2111  1.1     lukem 
   2112  1.1     lukem 		case CFG_OC: {
   2113  1.1     lukem 			ObjectClass *oc, *prev;
   2114  1.1     lukem 
   2115  1.1     lukem 			if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
   2116  1.1     lukem 				cfn = c->ca_private;
   2117  1.1     lukem 			if ( c->valx < 0 ) {
   2118  1.1     lukem 				prev = cfn->c_oc_tail;
   2119  1.1     lukem 			} else {
   2120  1.1     lukem 				prev = NULL;
   2121  1.1     lukem 				/* If adding anything after the first, prev is easy */
   2122  1.1     lukem 				if ( c->valx ) {
   2123  1.1     lukem 					int i;
   2124  1.1     lukem 					for (i=0, oc = cfn->c_oc_head; i<c->valx; i++) {
   2125  1.1     lukem 						prev = oc;
   2126  1.2  christos 						if ( !oc_next( &oc ))
   2127  1.2  christos 							break;
   2128  1.1     lukem 					}
   2129  1.1     lukem 				} else
   2130  1.1     lukem 				/* If adding the first, and head exists, find its prev */
   2131  1.1     lukem 					if (cfn->c_oc_head) {
   2132  1.1     lukem 					for ( oc_start( &oc ); oc != cfn->c_oc_head; ) {
   2133  1.1     lukem 						prev = oc;
   2134  1.1     lukem 						oc_next( &oc );
   2135  1.1     lukem 					}
   2136  1.1     lukem 				}
   2137  1.1     lukem 				/* else prev is NULL, append to end of global list */
   2138  1.1     lukem 			}
   2139  1.1     lukem 			if(parse_oc(c, &oc, prev)) return(1);
   2140  1.2  christos 			if (!cfn->c_oc_head || !c->valx) cfn->c_oc_head = oc;
   2141  1.1     lukem 			if (cfn->c_oc_tail == prev) cfn->c_oc_tail = oc;
   2142  1.1     lukem 			}
   2143  1.1     lukem 			break;
   2144  1.1     lukem 
   2145  1.1     lukem 		case CFG_ATTR: {
   2146  1.1     lukem 			AttributeType *at, *prev;
   2147  1.1     lukem 
   2148  1.1     lukem 			if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
   2149  1.1     lukem 				cfn = c->ca_private;
   2150  1.1     lukem 			if ( c->valx < 0 ) {
   2151  1.1     lukem 				prev = cfn->c_at_tail;
   2152  1.1     lukem 			} else {
   2153  1.1     lukem 				prev = NULL;
   2154  1.1     lukem 				/* If adding anything after the first, prev is easy */
   2155  1.1     lukem 				if ( c->valx ) {
   2156  1.1     lukem 					int i;
   2157  1.1     lukem 					for (i=0, at = cfn->c_at_head; i<c->valx; i++) {
   2158  1.1     lukem 						prev = at;
   2159  1.2  christos 						if ( !at_next( &at ))
   2160  1.2  christos 							break;
   2161  1.1     lukem 					}
   2162  1.1     lukem 				} else
   2163  1.1     lukem 				/* If adding the first, and head exists, find its prev */
   2164  1.1     lukem 					if (cfn->c_at_head) {
   2165  1.1     lukem 					for ( at_start( &at ); at != cfn->c_at_head; ) {
   2166  1.1     lukem 						prev = at;
   2167  1.1     lukem 						at_next( &at );
   2168  1.1     lukem 					}
   2169  1.1     lukem 				}
   2170  1.1     lukem 				/* else prev is NULL, append to end of global list */
   2171  1.1     lukem 			}
   2172  1.1     lukem 			if(parse_at(c, &at, prev)) return(1);
   2173  1.2  christos 			if (!cfn->c_at_head || !c->valx) cfn->c_at_head = at;
   2174  1.1     lukem 			if (cfn->c_at_tail == prev) cfn->c_at_tail = at;
   2175  1.1     lukem 			}
   2176  1.1     lukem 			break;
   2177  1.1     lukem 
   2178  1.2  christos 		case CFG_SYNTAX: {
   2179  1.2  christos 			Syntax *syn, *prev;
   2180  1.2  christos 
   2181  1.2  christos 			if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
   2182  1.2  christos 				cfn = c->ca_private;
   2183  1.2  christos 			if ( c->valx < 0 ) {
   2184  1.2  christos 				prev = cfn->c_syn_tail;
   2185  1.2  christos 			} else {
   2186  1.2  christos 				prev = NULL;
   2187  1.2  christos 				/* If adding anything after the first, prev is easy */
   2188  1.2  christos 				if ( c->valx ) {
   2189  1.2  christos 					int i;
   2190  1.2  christos 					for ( i = 0, syn = cfn->c_syn_head; i < c->valx; i++ ) {
   2191  1.2  christos 						prev = syn;
   2192  1.2  christos 						if ( !syn_next( &syn ))
   2193  1.2  christos 							break;
   2194  1.2  christos 					}
   2195  1.2  christos 				} else
   2196  1.2  christos 				/* If adding the first, and head exists, find its prev */
   2197  1.2  christos 					if (cfn->c_syn_head) {
   2198  1.2  christos 					for ( syn_start( &syn ); syn != cfn->c_syn_head; ) {
   2199  1.2  christos 						prev = syn;
   2200  1.2  christos 						syn_next( &syn );
   2201  1.2  christos 					}
   2202  1.2  christos 				}
   2203  1.2  christos 				/* else prev is NULL, append to end of global list */
   2204  1.2  christos 			}
   2205  1.2  christos 			if ( parse_syn( c, &syn, prev ) ) return(1);
   2206  1.2  christos 			if ( !cfn->c_syn_head || !c->valx ) cfn->c_syn_head = syn;
   2207  1.2  christos 			if ( cfn->c_syn_tail == prev ) cfn->c_syn_tail = syn;
   2208  1.2  christos 			}
   2209  1.2  christos 			break;
   2210  1.2  christos 
   2211  1.1     lukem 		case CFG_DIT: {
   2212  1.1     lukem 			ContentRule *cr;
   2213  1.1     lukem 
   2214  1.1     lukem 			if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
   2215  1.1     lukem 				cfn = c->ca_private;
   2216  1.1     lukem 			if(parse_cr(c, &cr)) return(1);
   2217  1.1     lukem 			if (!cfn->c_cr_head) cfn->c_cr_head = cr;
   2218  1.1     lukem 			cfn->c_cr_tail = cr;
   2219  1.1     lukem 			}
   2220  1.1     lukem 			break;
   2221  1.1     lukem 
   2222  1.1     lukem 		case CFG_ATOPT:
   2223  1.1     lukem 			ad_define_option(NULL, NULL, 0);
   2224  1.1     lukem 			for(i = 1; i < c->argc; i++)
   2225  1.1     lukem 				if(ad_define_option(c->argv[i], c->fname, c->lineno))
   2226  1.1     lukem 					return(1);
   2227  1.1     lukem 			break;
   2228  1.1     lukem 
   2229  1.3  christos 		case CFG_IX_HASH64:
   2230  1.3  christos 			if ( slap_hash64( c->value_int != 0 ))
   2231  1.3  christos 				return 1;
   2232  1.3  christos 			break;
   2233  1.3  christos 
   2234  1.1     lukem 		case CFG_IX_INTLEN:
   2235  1.1     lukem 			if ( c->value_int < SLAP_INDEX_INTLEN_DEFAULT )
   2236  1.1     lukem 				c->value_int = SLAP_INDEX_INTLEN_DEFAULT;
   2237  1.1     lukem 			else if ( c->value_int > 255 )
   2238  1.1     lukem 				c->value_int = 255;
   2239  1.1     lukem 			index_intlen = c->value_int;
   2240  1.1     lukem 			index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
   2241  1.1     lukem 				index_intlen );
   2242  1.1     lukem 			break;
   2243  1.3  christos 
   2244  1.1     lukem 		case CFG_SORTVALS: {
   2245  1.1     lukem 			ADlist *svnew = NULL, *svtail, *sv;
   2246  1.1     lukem 
   2247  1.1     lukem 			for ( i = 1; i < c->argc; i++ ) {
   2248  1.1     lukem 				AttributeDescription *ad = NULL;
   2249  1.1     lukem 				const char *text;
   2250  1.1     lukem 				int rc;
   2251  1.1     lukem 
   2252  1.1     lukem 				rc = slap_str2ad( c->argv[i], &ad, &text );
   2253  1.1     lukem 				if ( rc ) {
   2254  1.1     lukem 					snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown attribute type #%d",
   2255  1.1     lukem 						c->argv[0], i );
   2256  1.1     lukem sortval_reject:
   2257  1.1     lukem 					Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   2258  1.1     lukem 						c->log, c->cr_msg, c->argv[i] );
   2259  1.1     lukem 					for ( sv = svnew; sv; sv = svnew ) {
   2260  1.1     lukem 						svnew = sv->al_next;
   2261  1.1     lukem 						ch_free( sv );
   2262  1.1     lukem 					}
   2263  1.1     lukem 					return 1;
   2264  1.1     lukem 				}
   2265  1.1     lukem 				if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED ) ||
   2266  1.1     lukem 					ad->ad_type->sat_single_value ) {
   2267  1.1     lukem 					snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> inappropriate attribute type #%d",
   2268  1.1     lukem 						c->argv[0], i );
   2269  1.1     lukem 					goto sortval_reject;
   2270  1.1     lukem 				}
   2271  1.1     lukem 				sv = ch_malloc( sizeof( ADlist ));
   2272  1.1     lukem 				sv->al_desc = ad;
   2273  1.1     lukem 				if ( !svnew ) {
   2274  1.1     lukem 					svnew = sv;
   2275  1.1     lukem 				} else {
   2276  1.1     lukem 					svtail->al_next = sv;
   2277  1.1     lukem 				}
   2278  1.1     lukem 				svtail = sv;
   2279  1.1     lukem 			}
   2280  1.1     lukem 			sv->al_next = NULL;
   2281  1.1     lukem 			for ( sv = svnew; sv; sv = sv->al_next )
   2282  1.1     lukem 				sv->al_desc->ad_type->sat_flags |= SLAP_AT_SORTED_VAL;
   2283  1.1     lukem 			for ( sv = sortVals; sv && sv->al_next; sv = sv->al_next );
   2284  1.1     lukem 			if ( sv )
   2285  1.1     lukem 				sv->al_next = svnew;
   2286  1.1     lukem 			else
   2287  1.1     lukem 				sortVals = svnew;
   2288  1.1     lukem 			}
   2289  1.1     lukem 			break;
   2290  1.1     lukem 
   2291  1.1     lukem 		case CFG_ACL:
   2292  1.2  christos 			if ( SLAP_CONFIG( c->be ) && c->be->be_acl == defacl_parsed) {
   2293  1.2  christos 				c->be->be_acl = NULL;
   2294  1.2  christos 			}
   2295  1.1     lukem 			/* Don't append to the global ACL if we're on a specific DB */
   2296  1.1     lukem 			i = c->valx;
   2297  1.2  christos 			if ( c->valx == -1 ) {
   2298  1.1     lukem 				AccessControl *a;
   2299  1.1     lukem 				i = 0;
   2300  1.2  christos 				for ( a=c->be->be_acl; a; a = a->acl_next )
   2301  1.1     lukem 					i++;
   2302  1.1     lukem 			}
   2303  1.4  christos 			if ( parse_acl( c, i ) ) {
   2304  1.2  christos 				if ( SLAP_CONFIG( c->be ) && !c->be->be_acl) {
   2305  1.2  christos 					c->be->be_acl = defacl_parsed;
   2306  1.2  christos 				}
   2307  1.1     lukem 				return 1;
   2308  1.1     lukem 			}
   2309  1.1     lukem 			break;
   2310  1.1     lukem 
   2311  1.2  christos 		case CFG_ACL_ADD:
   2312  1.2  christos 			if(c->value_int)
   2313  1.2  christos 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_ACL_ADD;
   2314  1.2  christos 			else
   2315  1.2  christos 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_ACL_ADD;
   2316  1.2  christos 			break;
   2317  1.2  christos 
   2318  1.1     lukem 		case CFG_ROOTDSE:
   2319  1.1     lukem 			if(root_dse_read_file(c->argv[1])) {
   2320  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> could not read file", c->argv[0] );
   2321  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   2322  1.1     lukem 					c->log, c->cr_msg, c->argv[1] );
   2323  1.1     lukem 				return(1);
   2324  1.1     lukem 			}
   2325  1.1     lukem 			{
   2326  1.1     lukem 				struct berval bv;
   2327  1.1     lukem 				ber_str2bv( c->argv[1], 0, 1, &bv );
   2328  1.1     lukem 				if ( c->op == LDAP_MOD_ADD && c->ca_private && cfn != c->ca_private )
   2329  1.1     lukem 					cfn = c->ca_private;
   2330  1.1     lukem 				ber_bvarray_add( &cfn->c_dseFiles, &bv );
   2331  1.1     lukem 			}
   2332  1.1     lukem 			break;
   2333  1.1     lukem 
   2334  1.1     lukem 		case CFG_SERVERID:
   2335  1.1     lukem 			{
   2336  1.1     lukem 				ServerID *si, **sip;
   2337  1.1     lukem 				LDAPURLDesc *lud;
   2338  1.1     lukem 				int num;
   2339  1.2  christos 				if (( lutil_atoi( &num, c->argv[1] ) &&
   2340  1.2  christos 					lutil_atoix( &num, c->argv[1], 16 )) ||
   2341  1.1     lukem 					num < 0 || num > SLAP_SYNC_SID_MAX )
   2342  1.1     lukem 				{
   2343  1.1     lukem 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
   2344  1.1     lukem 						"<%s> illegal server ID", c->argv[0] );
   2345  1.1     lukem 					Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   2346  1.1     lukem 						c->log, c->cr_msg, c->argv[1] );
   2347  1.1     lukem 					return 1;
   2348  1.1     lukem 				}
   2349  1.1     lukem 				/* only one value allowed if no URL is given */
   2350  1.1     lukem 				if ( c->argc > 2 ) {
   2351  1.1     lukem 					int len;
   2352  1.1     lukem 
   2353  1.1     lukem 					if ( sid_list && BER_BVISEMPTY( &sid_list->si_url )) {
   2354  1.1     lukem 						snprintf( c->cr_msg, sizeof( c->cr_msg ),
   2355  1.1     lukem 							"<%s> only one server ID allowed now", c->argv[0] );
   2356  1.1     lukem 						Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   2357  1.1     lukem 							c->log, c->cr_msg, c->argv[1] );
   2358  1.1     lukem 						return 1;
   2359  1.1     lukem 					}
   2360  1.1     lukem 
   2361  1.1     lukem 					if ( ldap_url_parse( c->argv[2], &lud )) {
   2362  1.1     lukem 						snprintf( c->cr_msg, sizeof( c->cr_msg ),
   2363  1.1     lukem 							"<%s> invalid URL", c->argv[0] );
   2364  1.1     lukem 						Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   2365  1.1     lukem 							c->log, c->cr_msg, c->argv[2] );
   2366  1.1     lukem 						return 1;
   2367  1.1     lukem 					}
   2368  1.1     lukem 					len = strlen( c->argv[2] );
   2369  1.1     lukem 					si = ch_malloc( sizeof(ServerID) + len + 1 );
   2370  1.1     lukem 					si->si_url.bv_val = (char *)(si+1);
   2371  1.1     lukem 					si->si_url.bv_len = len;
   2372  1.1     lukem 					strcpy( si->si_url.bv_val, c->argv[2] );
   2373  1.1     lukem 				} else {
   2374  1.1     lukem 					if ( sid_list ) {
   2375  1.1     lukem 						snprintf( c->cr_msg, sizeof( c->cr_msg ),
   2376  1.1     lukem 							"<%s> unqualified server ID not allowed now", c->argv[0] );
   2377  1.1     lukem 						Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   2378  1.1     lukem 							c->log, c->cr_msg, c->argv[1] );
   2379  1.1     lukem 						return 1;
   2380  1.1     lukem 					}
   2381  1.1     lukem 					si = ch_malloc( sizeof(ServerID) );
   2382  1.1     lukem 					BER_BVZERO( &si->si_url );
   2383  1.1     lukem 					slap_serverID = num;
   2384  1.1     lukem 					Debug( LDAP_DEBUG_CONFIG,
   2385  1.2  christos 						"%s: SID=0x%03x\n",
   2386  1.3  christos 						c->log, slap_serverID );
   2387  1.2  christos 					sid_set = si;
   2388  1.1     lukem 				}
   2389  1.1     lukem 				si->si_next = NULL;
   2390  1.1     lukem 				si->si_num = num;
   2391  1.1     lukem 				for ( sip = &sid_list; *sip; sip = &(*sip)->si_next );
   2392  1.1     lukem 				*sip = si;
   2393  1.1     lukem 
   2394  1.1     lukem 				if (( slapMode & SLAP_SERVER_MODE ) && c->argc > 2 ) {
   2395  1.2  christos 					Listener *l = config_check_my_url( c->argv[2], lud );
   2396  1.2  christos 					if ( l ) {
   2397  1.2  christos 						if ( sid_set ) {
   2398  1.2  christos 							ldap_free_urldesc( lud );
   2399  1.2  christos 							snprintf( c->cr_msg, sizeof( c->cr_msg ),
   2400  1.2  christos 								"<%s> multiple server ID URLs matched, only one is allowed", c->argv[0] );
   2401  1.2  christos 							Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   2402  1.2  christos 								c->log, c->cr_msg, c->argv[1] );
   2403  1.2  christos 							return 1;
   2404  1.1     lukem 						}
   2405  1.2  christos 						slap_serverID = si->si_num;
   2406  1.2  christos 						Debug( LDAP_DEBUG_CONFIG,
   2407  1.2  christos 							"%s: SID=0x%03x (listener=%s)\n",
   2408  1.2  christos 							c->log, slap_serverID,
   2409  1.2  christos 							l->sl_url.bv_val );
   2410  1.2  christos 						sid_set = si;
   2411  1.1     lukem 					}
   2412  1.1     lukem 				}
   2413  1.1     lukem 				if ( c->argc > 2 )
   2414  1.1     lukem 					ldap_free_urldesc( lud );
   2415  1.1     lukem 			}
   2416  1.1     lukem 			break;
   2417  1.1     lukem 
   2418  1.1     lukem 		case CFG_LASTMOD:
   2419  1.1     lukem 			if(SLAP_NOLASTMODCMD(c->be)) {
   2420  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> not available for %s database",
   2421  1.1     lukem 					c->argv[0], c->be->bd_info->bi_type );
   2422  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   2423  1.3  christos 					c->log, c->cr_msg );
   2424  1.1     lukem 				return(1);
   2425  1.1     lukem 			}
   2426  1.1     lukem 			if(c->value_int)
   2427  1.1     lukem 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_NOLASTMOD;
   2428  1.1     lukem 			else
   2429  1.1     lukem 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_NOLASTMOD;
   2430  1.1     lukem 			break;
   2431  1.1     lukem 
   2432  1.3  christos 		case CFG_LASTBIND:
   2433  1.3  christos 			if (c->value_int)
   2434  1.3  christos 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_LASTBIND;
   2435  1.3  christos 			else
   2436  1.3  christos 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_LASTBIND;
   2437  1.3  christos 			break;
   2438  1.3  christos 
   2439  1.4  christos 		case CFG_LASTBIND_PRECISION:
   2440  1.4  christos 			c->be->be_lastbind_precision = c->value_uint;
   2441  1.4  christos 			break;
   2442  1.4  christos 
   2443  1.3  christos 		case CFG_MULTIPROVIDER:
   2444  1.2  christos 			if(c->value_int && !SLAP_SHADOW(c->be)) {
   2445  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database is not a shadow",
   2446  1.1     lukem 					c->argv[0] );
   2447  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   2448  1.3  christos 					c->log, c->cr_msg );
   2449  1.1     lukem 				return(1);
   2450  1.1     lukem 			}
   2451  1.2  christos 			if(c->value_int) {
   2452  1.1     lukem 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SINGLE_SHADOW;
   2453  1.2  christos 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_MULTI_SHADOW;
   2454  1.2  christos 			} else {
   2455  1.1     lukem 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
   2456  1.2  christos 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MULTI_SHADOW;
   2457  1.2  christos 			}
   2458  1.1     lukem 			break;
   2459  1.1     lukem 
   2460  1.1     lukem 		case CFG_MONITORING:
   2461  1.1     lukem 			if(c->value_int)
   2462  1.1     lukem 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_MONITORING;
   2463  1.1     lukem 			else
   2464  1.1     lukem 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_MONITORING;
   2465  1.1     lukem 			break;
   2466  1.1     lukem 
   2467  1.3  christos 		case CFG_DISABLED:
   2468  1.3  christos 			if ( c->bi ) {
   2469  1.3  christos 				if (c->value_int) {
   2470  1.3  christos 					if ( c->bi->bi_db_close ) {
   2471  1.3  christos 						BackendInfo *bi_orig = c->be->bd_info;
   2472  1.3  christos 						c->be->bd_info = c->bi;
   2473  1.3  christos 						c->bi->bi_db_close( c->be, &c->reply );
   2474  1.3  christos 						c->be->bd_info = bi_orig;
   2475  1.3  christos 					}
   2476  1.3  christos 					c->bi->bi_flags |= SLAPO_BFLAG_DISABLED;
   2477  1.3  christos 				} else {
   2478  1.3  christos 					c->bi->bi_flags &= ~SLAPO_BFLAG_DISABLED;
   2479  1.3  christos 				}
   2480  1.3  christos 			} else {
   2481  1.3  christos 				if (c->value_int) {
   2482  1.3  christos 					backend_shutdown( c->be );
   2483  1.3  christos 					SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_DISABLED;
   2484  1.3  christos 				} else {
   2485  1.3  christos 					SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_DISABLED;
   2486  1.3  christos 				}
   2487  1.3  christos 			}
   2488  1.3  christos 			break;
   2489  1.3  christos 
   2490  1.1     lukem 		case CFG_HIDDEN:
   2491  1.1     lukem 			if (c->value_int)
   2492  1.1     lukem 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_HIDDEN;
   2493  1.1     lukem 			else
   2494  1.1     lukem 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_HIDDEN;
   2495  1.1     lukem 			break;
   2496  1.1     lukem 
   2497  1.2  christos 		case CFG_SYNC_SUBENTRY:
   2498  1.2  christos 			if (c->value_int)
   2499  1.2  christos 				SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SYNC_SUBENTRY;
   2500  1.2  christos 			else
   2501  1.2  christos 				SLAP_DBFLAGS(c->be) &= ~SLAP_DBFLAG_SYNC_SUBENTRY;
   2502  1.2  christos 			break;
   2503  1.2  christos 
   2504  1.1     lukem 		case CFG_SSTR_IF_MAX:
   2505  1.2  christos 			index_substr_if_maxlen = c->value_uint;
   2506  1.4  christos 			/* ITS#7215 Postpone range check until the entire modify is finished */
   2507  1.4  christos 			config_push_cleanup( c, config_substr_if_check );
   2508  1.1     lukem 			break;
   2509  1.1     lukem 
   2510  1.1     lukem 		case CFG_SSTR_IF_MIN:
   2511  1.2  christos 			index_substr_if_minlen = c->value_uint;
   2512  1.4  christos 			/* ITS#7215 Postpone range check until the entire modify is finished */
   2513  1.4  christos 			config_push_cleanup( c, config_substr_if_check );
   2514  1.1     lukem 			break;
   2515  1.1     lukem 
   2516  1.1     lukem #ifdef SLAPD_MODULES
   2517  1.1     lukem 		case CFG_MODLOAD:
   2518  1.1     lukem 			/* If we're just adding a module on an existing modpath,
   2519  1.1     lukem 			 * make sure we've selected the current path.
   2520  1.1     lukem 			 */
   2521  1.1     lukem 			if ( c->op == LDAP_MOD_ADD && c->ca_private && modcur != c->ca_private ) {
   2522  1.1     lukem 				modcur = c->ca_private;
   2523  1.1     lukem 				/* This should never fail */
   2524  1.1     lukem 				if ( module_path( modcur->mp_path.bv_val )) {
   2525  1.1     lukem 					snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> module path no longer valid",
   2526  1.1     lukem 						c->argv[0] );
   2527  1.1     lukem 					Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
   2528  1.1     lukem 						c->log, c->cr_msg, modcur->mp_path.bv_val );
   2529  1.1     lukem 					return(1);
   2530  1.1     lukem 				}
   2531  1.1     lukem 			}
   2532  1.1     lukem 			if(module_load(c->argv[1], c->argc - 2, (c->argc > 2) ? c->argv + 2 : NULL))
   2533  1.1     lukem 				return(1);
   2534  1.1     lukem 			/* Record this load on the current path */
   2535  1.1     lukem 			{
   2536  1.1     lukem 				struct berval bv;
   2537  1.1     lukem 				char *ptr;
   2538  1.1     lukem 				if ( c->op == SLAP_CONFIG_ADD ) {
   2539  1.1     lukem 					ptr = c->line + STRLENOF("moduleload");
   2540  1.1     lukem 					while (!isspace((unsigned char) *ptr)) ptr++;
   2541  1.1     lukem 					while (isspace((unsigned char) *ptr)) ptr++;
   2542  1.1     lukem 				} else {
   2543  1.1     lukem 					ptr = c->line;
   2544  1.1     lukem 				}
   2545  1.1     lukem 				ber_str2bv(ptr, 0, 1, &bv);
   2546  1.1     lukem 				ber_bvarray_add( &modcur->mp_loads, &bv );
   2547  1.1     lukem 			}
   2548  1.1     lukem 			/* Check for any new hardcoded schema */
   2549  1.1     lukem 			if ( c->op == LDAP_MOD_ADD && CONFIG_ONLINE_ADD( c )) {
   2550  1.1     lukem 				config_check_schema( NULL, &cfBackInfo );
   2551  1.1     lukem 			}
   2552  1.1     lukem 			break;
   2553  1.1     lukem 
   2554  1.1     lukem 		case CFG_MODPATH:
   2555  1.1     lukem 			if(module_path(c->argv[1])) return(1);
   2556  1.1     lukem 			/* Record which path was used with each module */
   2557  1.1     lukem 			{
   2558  1.1     lukem 				ModPaths *mp;
   2559  1.1     lukem 
   2560  1.1     lukem 				if (!modpaths.mp_loads) {
   2561  1.1     lukem 					mp = &modpaths;
   2562  1.1     lukem 				} else {
   2563  1.1     lukem 					mp = ch_malloc( sizeof( ModPaths ));
   2564  1.1     lukem 					modlast->mp_next = mp;
   2565  1.1     lukem 				}
   2566  1.1     lukem 				ber_str2bv(c->argv[1], 0, 1, &mp->mp_path);
   2567  1.1     lukem 				mp->mp_next = NULL;
   2568  1.1     lukem 				mp->mp_loads = NULL;
   2569  1.1     lukem 				modlast = mp;
   2570  1.1     lukem 				c->ca_private = mp;
   2571  1.1     lukem 				modcur = mp;
   2572  1.1     lukem 			}
   2573  1.1     lukem 
   2574  1.1     lukem 			break;
   2575  1.1     lukem #endif
   2576  1.1     lukem 
   2577  1.1     lukem #ifdef LDAP_SLAPI
   2578  1.1     lukem 		case CFG_PLUGIN:
   2579  1.4  christos 			if(slapi_int_read_config(c) != LDAP_SUCCESS)
   2580  1.1     lukem 				return(1);
   2581  1.1     lukem 			slapi_plugins_used++;
   2582  1.1     lukem 			break;
   2583  1.1     lukem #endif
   2584  1.1     lukem 
   2585  1.1     lukem 		case CFG_REWRITE: {
   2586  1.3  christos 			int rc;
   2587  1.2  christos 
   2588  1.2  christos 			if ( c->op == LDAP_MOD_ADD ) {
   2589  1.2  christos 				c->argv++;
   2590  1.2  christos 				c->argc--;
   2591  1.2  christos 			}
   2592  1.3  christos 			rc = slap_sasl_rewrite_config(c->fname, c->lineno, c->argc, c->argv, c->valx);
   2593  1.2  christos 			if ( c->op == LDAP_MOD_ADD ) {
   2594  1.2  christos 				c->argv--;
   2595  1.2  christos 				c->argc++;
   2596  1.1     lukem 			}
   2597  1.2  christos 			return rc;
   2598  1.1     lukem 			}
   2599  1.1     lukem 
   2600  1.1     lukem 
   2601  1.1     lukem 		default:
   2602  1.1     lukem 			Debug( LDAP_DEBUG_ANY,
   2603  1.1     lukem 				"%s: unknown CFG_TYPE %d.\n",
   2604  1.3  christos 				c->log, c->type );
   2605  1.1     lukem 			return 1;
   2606  1.1     lukem 
   2607  1.1     lukem 	}
   2608  1.1     lukem 	return(0);
   2609  1.1     lukem }
   2610  1.1     lukem 
   2611  1.1     lukem 
   2612  1.1     lukem static int
   2613  1.1     lukem config_fname(ConfigArgs *c) {
   2614  1.1     lukem 	if(c->op == SLAP_CONFIG_EMIT) {
   2615  1.1     lukem 		if (c->ca_private) {
   2616  1.1     lukem 			ConfigFile *cf = c->ca_private;
   2617  1.1     lukem 			value_add_one( &c->rvalue_vals, &cf->c_file );
   2618  1.1     lukem 			return 0;
   2619  1.1     lukem 		}
   2620  1.1     lukem 		return 1;
   2621  1.1     lukem 	}
   2622  1.1     lukem 	return(0);
   2623  1.1     lukem }
   2624  1.1     lukem 
   2625  1.1     lukem static int
   2626  1.1     lukem config_cfdir(ConfigArgs *c) {
   2627  1.1     lukem 	if(c->op == SLAP_CONFIG_EMIT) {
   2628  1.1     lukem 		if ( !BER_BVISEMPTY( &cfdir )) {
   2629  1.1     lukem 			value_add_one( &c->rvalue_vals, &cfdir );
   2630  1.1     lukem 			return 0;
   2631  1.1     lukem 		}
   2632  1.1     lukem 		return 1;
   2633  1.1     lukem 	}
   2634  1.1     lukem 	return(0);
   2635  1.1     lukem }
   2636  1.1     lukem 
   2637  1.1     lukem static int
   2638  1.1     lukem config_search_base(ConfigArgs *c) {
   2639  1.1     lukem 	if(c->op == SLAP_CONFIG_EMIT) {
   2640  1.1     lukem 		int rc = 1;
   2641  1.1     lukem 		if (!BER_BVISEMPTY(&default_search_base)) {
   2642  1.1     lukem 			value_add_one(&c->rvalue_vals, &default_search_base);
   2643  1.1     lukem 			value_add_one(&c->rvalue_nvals, &default_search_nbase);
   2644  1.1     lukem 			rc = 0;
   2645  1.1     lukem 		}
   2646  1.1     lukem 		return rc;
   2647  1.1     lukem 	} else if( c->op == LDAP_MOD_DELETE ) {
   2648  1.1     lukem 		ch_free( default_search_base.bv_val );
   2649  1.1     lukem 		ch_free( default_search_nbase.bv_val );
   2650  1.1     lukem 		BER_BVZERO( &default_search_base );
   2651  1.1     lukem 		BER_BVZERO( &default_search_nbase );
   2652  1.1     lukem 		return 0;
   2653  1.1     lukem 	}
   2654  1.1     lukem 
   2655  1.1     lukem 	if(c->bi || c->be != frontendDB) {
   2656  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: defaultSearchBase line must appear "
   2657  1.1     lukem 			"prior to any backend or database definition\n",
   2658  1.3  christos 			c->log );
   2659  1.1     lukem 		return(1);
   2660  1.1     lukem 	}
   2661  1.1     lukem 
   2662  1.1     lukem 	if(default_search_nbase.bv_len) {
   2663  1.1     lukem 		free(default_search_base.bv_val);
   2664  1.1     lukem 		free(default_search_nbase.bv_val);
   2665  1.1     lukem 	}
   2666  1.1     lukem 
   2667  1.1     lukem 	default_search_base = c->value_dn;
   2668  1.1     lukem 	default_search_nbase = c->value_ndn;
   2669  1.1     lukem 	return(0);
   2670  1.1     lukem }
   2671  1.1     lukem 
   2672  1.1     lukem /* For RE23 compatibility we allow this in the global entry
   2673  1.1     lukem  * but we now defer it to the frontend entry to allow modules
   2674  1.1     lukem  * to load new hash types.
   2675  1.1     lukem  */
   2676  1.1     lukem static int
   2677  1.1     lukem config_passwd_hash(ConfigArgs *c) {
   2678  1.1     lukem 	int i;
   2679  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   2680  1.1     lukem 		struct berval bv;
   2681  1.1     lukem 		/* Don't generate it in the global entry */
   2682  1.1     lukem 		if ( c->table == Cft_Global )
   2683  1.1     lukem 			return 1;
   2684  1.1     lukem 		for (i=0; default_passwd_hash && default_passwd_hash[i]; i++) {
   2685  1.1     lukem 			ber_str2bv(default_passwd_hash[i], 0, 0, &bv);
   2686  1.1     lukem 			value_add_one(&c->rvalue_vals, &bv);
   2687  1.1     lukem 		}
   2688  1.1     lukem 		return i ? 0 : 1;
   2689  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   2690  1.1     lukem 		/* Deleting from global is a no-op, only the frontendDB entry matters */
   2691  1.1     lukem 		if ( c->table == Cft_Global )
   2692  1.1     lukem 			return 0;
   2693  1.1     lukem 		if ( c->valx < 0 ) {
   2694  1.1     lukem 			ldap_charray_free( default_passwd_hash );
   2695  1.1     lukem 			default_passwd_hash = NULL;
   2696  1.1     lukem 		} else {
   2697  1.1     lukem 			i = c->valx;
   2698  1.1     lukem 			ch_free( default_passwd_hash[i] );
   2699  1.1     lukem 			for (; default_passwd_hash[i]; i++ )
   2700  1.1     lukem 				default_passwd_hash[i] = default_passwd_hash[i+1];
   2701  1.1     lukem 		}
   2702  1.1     lukem 		return 0;
   2703  1.1     lukem 	}
   2704  1.4  christos 	if ( c->op == LDAP_MOD_ADD && c->table == Cft_Global ) {
   2705  1.4  christos 		Debug( LDAP_DEBUG_ANY, "%s: setting password scheme in the global "
   2706  1.4  christos 				"entry is deprecated. The server may refuse to start if "
   2707  1.4  christos 				"it is provided by a loadable module, please move it to "
   2708  1.4  christos 				"the frontend database instead\n",
   2709  1.4  christos 				c->log );
   2710  1.4  christos 	}
   2711  1.1     lukem 	for(i = 1; i < c->argc; i++) {
   2712  1.1     lukem 		if(!lutil_passwd_scheme(c->argv[i])) {
   2713  1.1     lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> scheme not available", c->argv[0] );
   2714  1.1     lukem 			Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
   2715  1.1     lukem 				c->log, c->cr_msg, c->argv[i]);
   2716  1.1     lukem 		} else {
   2717  1.1     lukem 			ldap_charray_add(&default_passwd_hash, c->argv[i]);
   2718  1.1     lukem 		}
   2719  1.1     lukem 	}
   2720  1.1     lukem 	if(!default_passwd_hash) {
   2721  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> no valid hashes found", c->argv[0] );
   2722  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   2723  1.3  christos 			c->log, c->cr_msg );
   2724  1.1     lukem 		return(1);
   2725  1.1     lukem 	}
   2726  1.1     lukem 	return(0);
   2727  1.1     lukem }
   2728  1.1     lukem 
   2729  1.1     lukem static int
   2730  1.1     lukem config_schema_dn(ConfigArgs *c) {
   2731  1.1     lukem 	if ( c->op == SLAP_CONFIG_EMIT ) {
   2732  1.1     lukem 		int rc = 1;
   2733  1.1     lukem 		if ( !BER_BVISEMPTY( &c->be->be_schemadn )) {
   2734  1.1     lukem 			value_add_one(&c->rvalue_vals, &c->be->be_schemadn);
   2735  1.1     lukem 			value_add_one(&c->rvalue_nvals, &c->be->be_schemandn);
   2736  1.1     lukem 			rc = 0;
   2737  1.1     lukem 		}
   2738  1.1     lukem 		return rc;
   2739  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   2740  1.1     lukem 		ch_free( c->be->be_schemadn.bv_val );
   2741  1.1     lukem 		ch_free( c->be->be_schemandn.bv_val );
   2742  1.1     lukem 		BER_BVZERO( &c->be->be_schemadn );
   2743  1.1     lukem 		BER_BVZERO( &c->be->be_schemandn );
   2744  1.1     lukem 		return 0;
   2745  1.1     lukem 	}
   2746  1.1     lukem 	ch_free( c->be->be_schemadn.bv_val );
   2747  1.1     lukem 	ch_free( c->be->be_schemandn.bv_val );
   2748  1.1     lukem 	c->be->be_schemadn = c->value_dn;
   2749  1.1     lukem 	c->be->be_schemandn = c->value_ndn;
   2750  1.1     lukem 	return(0);
   2751  1.1     lukem }
   2752  1.1     lukem 
   2753  1.1     lukem static int
   2754  1.1     lukem config_sizelimit(ConfigArgs *c) {
   2755  1.1     lukem 	int i, rc = 0;
   2756  1.1     lukem 	struct slap_limits_set *lim = &c->be->be_def_limit;
   2757  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   2758  1.1     lukem 		char buf[8192];
   2759  1.1     lukem 		struct berval bv;
   2760  1.1     lukem 		bv.bv_val = buf;
   2761  1.1     lukem 		bv.bv_len = 0;
   2762  1.1     lukem 		limits_unparse_one( lim, SLAP_LIMIT_SIZE, &bv, sizeof( buf ) );
   2763  1.1     lukem 		if ( !BER_BVISEMPTY( &bv ))
   2764  1.1     lukem 			value_add_one( &c->rvalue_vals, &bv );
   2765  1.1     lukem 		else
   2766  1.1     lukem 			rc = 1;
   2767  1.1     lukem 		return rc;
   2768  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   2769  1.2  christos 		/* Reset to defaults or values from frontend */
   2770  1.2  christos 		if ( c->be == frontendDB ) {
   2771  1.2  christos 			lim->lms_s_soft = SLAPD_DEFAULT_SIZELIMIT;
   2772  1.2  christos 			lim->lms_s_hard = 0;
   2773  1.2  christos 			lim->lms_s_unchecked = -1;
   2774  1.2  christos 			lim->lms_s_pr = 0;
   2775  1.2  christos 			lim->lms_s_pr_hide = 0;
   2776  1.2  christos 			lim->lms_s_pr_total = 0;
   2777  1.2  christos 		} else {
   2778  1.2  christos 			lim->lms_s_soft = frontendDB->be_def_limit.lms_s_soft;
   2779  1.2  christos 			lim->lms_s_hard = frontendDB->be_def_limit.lms_s_hard;
   2780  1.2  christos 			lim->lms_s_unchecked = frontendDB->be_def_limit.lms_s_unchecked;
   2781  1.2  christos 			lim->lms_s_pr = frontendDB->be_def_limit.lms_s_pr;
   2782  1.2  christos 			lim->lms_s_pr_hide = frontendDB->be_def_limit.lms_s_pr_hide;
   2783  1.2  christos 			lim->lms_s_pr_total = frontendDB->be_def_limit.lms_s_pr_total;
   2784  1.2  christos 		}
   2785  1.2  christos 		goto ok;
   2786  1.1     lukem 	}
   2787  1.1     lukem 	for(i = 1; i < c->argc; i++) {
   2788  1.1     lukem 		if(!strncasecmp(c->argv[i], "size", 4)) {
   2789  1.1     lukem 			rc = limits_parse_one(c->argv[i], lim);
   2790  1.1     lukem 			if ( rc ) {
   2791  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
   2792  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
   2793  1.1     lukem 					c->log, c->cr_msg, c->argv[i]);
   2794  1.1     lukem 				return(1);
   2795  1.1     lukem 			}
   2796  1.1     lukem 		} else {
   2797  1.1     lukem 			if(!strcasecmp(c->argv[i], "unlimited")) {
   2798  1.1     lukem 				lim->lms_s_soft = -1;
   2799  1.1     lukem 			} else {
   2800  1.1     lukem 				if ( lutil_atoix( &lim->lms_s_soft, c->argv[i], 0 ) != 0 ) {
   2801  1.1     lukem 					snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]);
   2802  1.1     lukem 					Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
   2803  1.1     lukem 						c->log, c->cr_msg, c->argv[i]);
   2804  1.1     lukem 					return(1);
   2805  1.1     lukem 				}
   2806  1.1     lukem 			}
   2807  1.1     lukem 			lim->lms_s_hard = 0;
   2808  1.1     lukem 		}
   2809  1.1     lukem 	}
   2810  1.2  christos 
   2811  1.2  christos ok:
   2812  1.2  christos 	if ( ( c->be == frontendDB ) && ( c->ca_entry ) ) {
   2813  1.2  christos 		/* This is a modification to the global limits apply it to
   2814  1.2  christos 		 * the other databases as needed */
   2815  1.2  christos 		AttributeDescription *ad=NULL;
   2816  1.2  christos 		const char *text = NULL;
   2817  1.2  christos 		CfEntryInfo *ce = c->ca_entry->e_private;
   2818  1.2  christos 
   2819  1.2  christos 		slap_str2ad(c->argv[0], &ad, &text);
   2820  1.2  christos 		/* if we got here... */
   2821  1.2  christos 		assert( ad != NULL );
   2822  1.2  christos 
   2823  1.2  christos 		if ( ce->ce_type == Cft_Global ){
   2824  1.2  christos 			ce = ce->ce_kids;
   2825  1.2  christos 		}
   2826  1.2  christos 		for (; ce; ce=ce->ce_sibs) {
   2827  1.2  christos 			Entry *dbe = ce->ce_entry;
   2828  1.2  christos 			if ( (ce->ce_type == Cft_Database) && (ce->ce_be != frontendDB)
   2829  1.2  christos 					&& (!attr_find(dbe->e_attrs, ad)) ) {
   2830  1.2  christos 				ce->ce_be->be_def_limit.lms_s_soft = lim->lms_s_soft;
   2831  1.2  christos 				ce->ce_be->be_def_limit.lms_s_hard = lim->lms_s_hard;
   2832  1.2  christos 				ce->ce_be->be_def_limit.lms_s_unchecked =lim->lms_s_unchecked;
   2833  1.2  christos 				ce->ce_be->be_def_limit.lms_s_pr =lim->lms_s_pr;
   2834  1.2  christos 				ce->ce_be->be_def_limit.lms_s_pr_hide =lim->lms_s_pr_hide;
   2835  1.2  christos 				ce->ce_be->be_def_limit.lms_s_pr_total =lim->lms_s_pr_total;
   2836  1.2  christos 			}
   2837  1.2  christos 		}
   2838  1.2  christos 	}
   2839  1.1     lukem 	return(0);
   2840  1.1     lukem }
   2841  1.1     lukem 
   2842  1.1     lukem static int
   2843  1.1     lukem config_timelimit(ConfigArgs *c) {
   2844  1.1     lukem 	int i, rc = 0;
   2845  1.1     lukem 	struct slap_limits_set *lim = &c->be->be_def_limit;
   2846  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   2847  1.1     lukem 		char buf[8192];
   2848  1.1     lukem 		struct berval bv;
   2849  1.1     lukem 		bv.bv_val = buf;
   2850  1.1     lukem 		bv.bv_len = 0;
   2851  1.1     lukem 		limits_unparse_one( lim, SLAP_LIMIT_TIME, &bv, sizeof( buf ) );
   2852  1.1     lukem 		if ( !BER_BVISEMPTY( &bv ))
   2853  1.1     lukem 			value_add_one( &c->rvalue_vals, &bv );
   2854  1.1     lukem 		else
   2855  1.1     lukem 			rc = 1;
   2856  1.1     lukem 		return rc;
   2857  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   2858  1.2  christos 		/* Reset to defaults or values from frontend */
   2859  1.2  christos 		if ( c->be == frontendDB ) {
   2860  1.2  christos 			lim->lms_t_soft = SLAPD_DEFAULT_TIMELIMIT;
   2861  1.2  christos 			lim->lms_t_hard = 0;
   2862  1.2  christos 		} else {
   2863  1.2  christos 			lim->lms_t_soft = frontendDB->be_def_limit.lms_t_soft;
   2864  1.2  christos 			lim->lms_t_hard = frontendDB->be_def_limit.lms_t_hard;
   2865  1.2  christos 		}
   2866  1.2  christos 		goto ok;
   2867  1.1     lukem 	}
   2868  1.1     lukem 	for(i = 1; i < c->argc; i++) {
   2869  1.1     lukem 		if(!strncasecmp(c->argv[i], "time", 4)) {
   2870  1.1     lukem 			rc = limits_parse_one(c->argv[i], lim);
   2871  1.1     lukem 			if ( rc ) {
   2872  1.1     lukem 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse value", c->argv[0] );
   2873  1.1     lukem 				Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
   2874  1.1     lukem 					c->log, c->cr_msg, c->argv[i]);
   2875  1.1     lukem 				return(1);
   2876  1.1     lukem 			}
   2877  1.1     lukem 		} else {
   2878  1.1     lukem 			if(!strcasecmp(c->argv[i], "unlimited")) {
   2879  1.1     lukem 				lim->lms_t_soft = -1;
   2880  1.1     lukem 			} else {
   2881  1.1     lukem 				if ( lutil_atoix( &lim->lms_t_soft, c->argv[i], 0 ) != 0 ) {
   2882  1.1     lukem 					snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse limit", c->argv[0]);
   2883  1.1     lukem 					Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
   2884  1.1     lukem 						c->log, c->cr_msg, c->argv[i]);
   2885  1.1     lukem 					return(1);
   2886  1.1     lukem 				}
   2887  1.1     lukem 			}
   2888  1.1     lukem 			lim->lms_t_hard = 0;
   2889  1.1     lukem 		}
   2890  1.1     lukem 	}
   2891  1.2  christos 
   2892  1.2  christos ok:
   2893  1.2  christos 	if ( ( c->be == frontendDB ) && ( c->ca_entry ) ) {
   2894  1.2  christos 		/* This is a modification to the global limits apply it to
   2895  1.2  christos 		 * the other databases as needed */
   2896  1.2  christos 		AttributeDescription *ad=NULL;
   2897  1.2  christos 		const char *text = NULL;
   2898  1.2  christos 		CfEntryInfo *ce = c->ca_entry->e_private;
   2899  1.2  christos 
   2900  1.2  christos 		slap_str2ad(c->argv[0], &ad, &text);
   2901  1.2  christos 		/* if we got here... */
   2902  1.2  christos 		assert( ad != NULL );
   2903  1.2  christos 
   2904  1.2  christos 		if ( ce->ce_type == Cft_Global ){
   2905  1.2  christos 			ce = ce->ce_kids;
   2906  1.2  christos 		}
   2907  1.2  christos 		for (; ce; ce=ce->ce_sibs) {
   2908  1.2  christos 			Entry *dbe = ce->ce_entry;
   2909  1.2  christos 			if ( (ce->ce_type == Cft_Database) && (ce->ce_be != frontendDB)
   2910  1.2  christos 					&& (!attr_find(dbe->e_attrs, ad)) ) {
   2911  1.2  christos 				ce->ce_be->be_def_limit.lms_t_soft = lim->lms_t_soft;
   2912  1.2  christos 				ce->ce_be->be_def_limit.lms_t_hard = lim->lms_t_hard;
   2913  1.2  christos 			}
   2914  1.2  christos 		}
   2915  1.2  christos 	}
   2916  1.1     lukem 	return(0);
   2917  1.1     lukem }
   2918  1.1     lukem 
   2919  1.1     lukem static int
   2920  1.1     lukem config_overlay(ConfigArgs *c) {
   2921  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   2922  1.1     lukem 		return 1;
   2923  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   2924  1.1     lukem 		assert(0);
   2925  1.1     lukem 	}
   2926  1.1     lukem 	if(c->argv[1][0] == '-' && overlay_config(c->be, &c->argv[1][1],
   2927  1.2  christos 		c->valx, &c->bi, &c->reply)) {
   2928  1.1     lukem 		/* log error */
   2929  1.1     lukem 		Debug( LDAP_DEBUG_ANY,
   2930  1.1     lukem 			"%s: (optional) %s overlay \"%s\" configuration failed.\n",
   2931  1.1     lukem 			c->log, c->be == frontendDB ? "global " : "", &c->argv[1][1]);
   2932  1.1     lukem 		return 1;
   2933  1.2  christos 	} else if(overlay_config(c->be, c->argv[1], c->valx, &c->bi, &c->reply)) {
   2934  1.1     lukem 		return(1);
   2935  1.1     lukem 	}
   2936  1.1     lukem 	return(0);
   2937  1.1     lukem }
   2938  1.1     lukem 
   2939  1.1     lukem static int
   2940  1.1     lukem config_subordinate(ConfigArgs *c)
   2941  1.1     lukem {
   2942  1.1     lukem 	int rc = 1;
   2943  1.2  christos 	int advertise = 0;
   2944  1.1     lukem 
   2945  1.1     lukem 	switch( c->op ) {
   2946  1.1     lukem 	case SLAP_CONFIG_EMIT:
   2947  1.1     lukem 		if ( SLAP_GLUE_SUBORDINATE( c->be )) {
   2948  1.1     lukem 			struct berval bv;
   2949  1.1     lukem 
   2950  1.1     lukem 			bv.bv_val = SLAP_GLUE_ADVERTISE( c->be ) ? "advertise" : "TRUE";
   2951  1.1     lukem 			bv.bv_len = SLAP_GLUE_ADVERTISE( c->be ) ? STRLENOF("advertise") :
   2952  1.1     lukem 				STRLENOF("TRUE");
   2953  1.1     lukem 
   2954  1.1     lukem 			value_add_one( &c->rvalue_vals, &bv );
   2955  1.1     lukem 			rc = 0;
   2956  1.1     lukem 		}
   2957  1.1     lukem 		break;
   2958  1.1     lukem 	case LDAP_MOD_DELETE:
   2959  1.1     lukem 		if ( !c->line  || strcasecmp( c->line, "advertise" )) {
   2960  1.1     lukem 			glue_sub_del( c->be );
   2961  1.1     lukem 		} else {
   2962  1.1     lukem 			SLAP_DBFLAGS( c->be ) &= ~SLAP_DBFLAG_GLUE_ADVERTISE;
   2963  1.1     lukem 		}
   2964  1.1     lukem 		rc = 0;
   2965  1.1     lukem 		break;
   2966  1.1     lukem 	case LDAP_MOD_ADD:
   2967  1.1     lukem 	case SLAP_CONFIG_ADD:
   2968  1.2  christos 		if ( c->be->be_nsuffix == NULL ) {
   2969  1.2  christos 			/* log error */
   2970  1.2  christos 			snprintf( c->cr_msg, sizeof( c->cr_msg),
   2971  1.2  christos 				"subordinate configuration needs a suffix" );
   2972  1.2  christos 			Debug( LDAP_DEBUG_ANY,
   2973  1.2  christos 				"%s: %s.\n",
   2974  1.3  christos 				c->log, c->cr_msg );
   2975  1.2  christos 			rc = 1;
   2976  1.2  christos 			break;
   2977  1.2  christos 		}
   2978  1.2  christos 
   2979  1.2  christos 		if ( c->argc == 2 ) {
   2980  1.4  christos 			if ( strcasecmp( c->argv[1], "FALSE" ) == 0 ) {
   2981  1.4  christos 				rc = 0;
   2982  1.4  christos 				break;
   2983  1.4  christos 			} else if ( strcasecmp( c->argv[1], "advertise" ) == 0 ) {
   2984  1.2  christos 				advertise = 1;
   2985  1.2  christos 
   2986  1.2  christos 			} else if ( strcasecmp( c->argv[1], "TRUE" ) != 0 ) {
   2987  1.2  christos 				/* log error */
   2988  1.2  christos 				snprintf( c->cr_msg, sizeof( c->cr_msg),
   2989  1.4  christos 					"subordinate must be \"TRUE\", \"FALSE\" or \"advertise\"" );
   2990  1.2  christos 				Debug( LDAP_DEBUG_ANY,
   2991  1.2  christos 					"%s: suffix \"%s\": %s.\n",
   2992  1.2  christos 					c->log, c->be->be_suffix[0].bv_val, c->cr_msg );
   2993  1.2  christos 				rc = 1;
   2994  1.2  christos 				break;
   2995  1.2  christos 			}
   2996  1.2  christos 		}
   2997  1.2  christos 
   2998  1.1     lukem 		rc = glue_sub_add( c->be, advertise, CONFIG_ONLINE_ADD( c ));
   2999  1.1     lukem 		break;
   3000  1.1     lukem 	}
   3001  1.2  christos 
   3002  1.1     lukem 	return rc;
   3003  1.1     lukem }
   3004  1.1     lukem 
   3005  1.2  christos /*
   3006  1.2  christos  * [listener=<listener>] [{read|write}=]<size>
   3007  1.2  christos  */
   3008  1.2  christos 
   3009  1.2  christos #ifdef LDAP_TCP_BUFFER
   3010  1.2  christos static BerVarray tcp_buffer;
   3011  1.4  christos static int tcp_buffer_num;
   3012  1.2  christos 
   3013  1.2  christos #define SLAP_TCP_RMEM (0x1U)
   3014  1.2  christos #define SLAP_TCP_WMEM (0x2U)
   3015  1.2  christos 
   3016  1.2  christos static int
   3017  1.2  christos tcp_buffer_parse( struct berval *val, int argc, char **argv,
   3018  1.2  christos 		int *size, int *rw, Listener **l )
   3019  1.2  christos {
   3020  1.2  christos 	int i, rc = LDAP_SUCCESS;
   3021  1.2  christos 	LDAPURLDesc *lud = NULL;
   3022  1.2  christos 	char *ptr;
   3023  1.2  christos 
   3024  1.2  christos 	if ( val != NULL && argv == NULL ) {
   3025  1.2  christos 		char *s = val->bv_val;
   3026  1.2  christos 
   3027  1.2  christos 		argv = ldap_str2charray( s, " \t" );
   3028  1.2  christos 		if ( argv == NULL ) {
   3029  1.2  christos 			return LDAP_OTHER;
   3030  1.2  christos 		}
   3031  1.2  christos 	}
   3032  1.2  christos 
   3033  1.2  christos 	i = 0;
   3034  1.2  christos 	if ( strncasecmp( argv[ i ], "listener=", STRLENOF( "listener=" ) )
   3035  1.2  christos 		== 0 )
   3036  1.2  christos 	{
   3037  1.2  christos 		char *url = argv[ i ] + STRLENOF( "listener=" );
   3038  1.2  christos 
   3039  1.2  christos 		if ( ldap_url_parse( url, &lud ) ) {
   3040  1.2  christos 			rc = LDAP_INVALID_SYNTAX;
   3041  1.2  christos 			goto done;
   3042  1.2  christos 		}
   3043  1.2  christos 
   3044  1.2  christos 		*l = config_check_my_url( url, lud );
   3045  1.2  christos 		if ( *l == NULL ) {
   3046  1.2  christos 			rc = LDAP_NO_SUCH_ATTRIBUTE;
   3047  1.2  christos 			goto done;
   3048  1.2  christos 		}
   3049  1.2  christos 
   3050  1.2  christos 		i++;
   3051  1.2  christos 	}
   3052  1.2  christos 
   3053  1.2  christos 	ptr = argv[ i ];
   3054  1.2  christos 	if ( strncasecmp( ptr, "read=", STRLENOF( "read=" ) ) == 0 ) {
   3055  1.2  christos 		*rw |= SLAP_TCP_RMEM;
   3056  1.2  christos 		ptr += STRLENOF( "read=" );
   3057  1.2  christos 
   3058  1.2  christos 	} else if ( strncasecmp( ptr, "write=", STRLENOF( "write=" ) ) == 0 ) {
   3059  1.2  christos 		*rw |= SLAP_TCP_WMEM;
   3060  1.2  christos 		ptr += STRLENOF( "write=" );
   3061  1.2  christos 
   3062  1.2  christos 	} else {
   3063  1.2  christos 		*rw |= ( SLAP_TCP_RMEM | SLAP_TCP_WMEM );
   3064  1.2  christos 	}
   3065  1.2  christos 
   3066  1.2  christos 	/* accept any base */
   3067  1.2  christos 	if ( lutil_atoix( size, ptr, 0 ) ) {
   3068  1.2  christos 		rc = LDAP_INVALID_SYNTAX;
   3069  1.2  christos 		goto done;
   3070  1.2  christos 	}
   3071  1.2  christos 
   3072  1.2  christos done:;
   3073  1.2  christos 	if ( val != NULL && argv != NULL ) {
   3074  1.2  christos 		ldap_charray_free( argv );
   3075  1.2  christos 	}
   3076  1.2  christos 
   3077  1.2  christos 	if ( lud != NULL ) {
   3078  1.2  christos 		ldap_free_urldesc( lud );
   3079  1.2  christos 	}
   3080  1.2  christos 
   3081  1.2  christos 	return rc;
   3082  1.2  christos }
   3083  1.2  christos 
   3084  1.2  christos static int
   3085  1.2  christos tcp_buffer_delete_one( struct berval *val )
   3086  1.2  christos {
   3087  1.2  christos 	int rc = 0;
   3088  1.2  christos 	int size = -1, rw = 0;
   3089  1.2  christos 	Listener *l = NULL;
   3090  1.2  christos 
   3091  1.2  christos 	rc = tcp_buffer_parse( val, 0, NULL, &size, &rw, &l );
   3092  1.2  christos 	if ( rc != 0 ) {
   3093  1.2  christos 		return rc;
   3094  1.2  christos 	}
   3095  1.2  christos 
   3096  1.2  christos 	if ( l != NULL ) {
   3097  1.2  christos 		int i;
   3098  1.2  christos 		Listener **ll = slapd_get_listeners();
   3099  1.2  christos 
   3100  1.2  christos 		for ( i = 0; ll[ i ] != NULL; i++ ) {
   3101  1.2  christos 			if ( ll[ i ] == l ) break;
   3102  1.2  christos 		}
   3103  1.2  christos 
   3104  1.2  christos 		if ( ll[ i ] == NULL ) {
   3105  1.2  christos 			return LDAP_NO_SUCH_ATTRIBUTE;
   3106  1.2  christos 		}
   3107  1.2  christos 
   3108  1.2  christos 		if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = -1;
   3109  1.2  christos 		if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = -1;
   3110  1.2  christos 
   3111  1.2  christos 		for ( i++ ; ll[ i ] != NULL && bvmatch( &l->sl_url, &ll[ i ]->sl_url ); i++ ) {
   3112  1.2  christos 			if ( rw & SLAP_TCP_RMEM ) ll[ i ]->sl_tcp_rmem = -1;
   3113  1.2  christos 			if ( rw & SLAP_TCP_WMEM ) ll[ i ]->sl_tcp_wmem = -1;
   3114  1.2  christos 		}
   3115  1.2  christos 
   3116  1.2  christos 	} else {
   3117  1.2  christos 		/* NOTE: this affects listeners without a specific setting,
   3118  1.2  christos 		 * does not reset all listeners.  If a listener without
   3119  1.2  christos 		 * specific settings was assigned a buffer because of
   3120  1.2  christos 		 * a global setting, it will not be reset.  In any case,
   3121  1.2  christos 		 * buffer changes will only take place at restart. */
   3122  1.2  christos 		if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = -1;
   3123  1.2  christos 		if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = -1;
   3124  1.2  christos 	}
   3125  1.2  christos 
   3126  1.2  christos 	return rc;
   3127  1.2  christos }
   3128  1.2  christos 
   3129  1.2  christos static int
   3130  1.2  christos tcp_buffer_delete( BerVarray vals )
   3131  1.2  christos {
   3132  1.2  christos 	int i;
   3133  1.2  christos 
   3134  1.2  christos 	for ( i = 0; !BER_BVISNULL( &vals[ i ] ); i++ ) {
   3135  1.2  christos 		tcp_buffer_delete_one( &vals[ i ] );
   3136  1.2  christos 	}
   3137  1.2  christos 
   3138  1.2  christos 	return 0;
   3139  1.2  christos }
   3140  1.2  christos 
   3141  1.2  christos static int
   3142  1.2  christos tcp_buffer_unparse( int size, int rw, Listener *l, struct berval *val )
   3143  1.2  christos {
   3144  1.2  christos 	char buf[sizeof("2147483648")], *ptr;
   3145  1.2  christos 
   3146  1.2  christos 	/* unparse for later use */
   3147  1.2  christos 	val->bv_len = snprintf( buf, sizeof( buf ), "%d", size );
   3148  1.2  christos 	if ( l != NULL ) {
   3149  1.2  christos 		val->bv_len += STRLENOF( "listener=" " " ) + l->sl_url.bv_len;
   3150  1.2  christos 	}
   3151  1.2  christos 
   3152  1.2  christos 	if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) {
   3153  1.2  christos 		if ( rw & SLAP_TCP_RMEM ) {
   3154  1.2  christos 			val->bv_len += STRLENOF( "read=" );
   3155  1.2  christos 		} else if ( rw & SLAP_TCP_WMEM ) {
   3156  1.2  christos 			val->bv_len += STRLENOF( "write=" );
   3157  1.2  christos 		}
   3158  1.2  christos 	}
   3159  1.2  christos 
   3160  1.3  christos 	val->bv_val = ch_malloc( val->bv_len + 1 );
   3161  1.2  christos 
   3162  1.2  christos 	ptr = val->bv_val;
   3163  1.2  christos 
   3164  1.2  christos 	if ( l != NULL ) {
   3165  1.2  christos 		ptr = lutil_strcopy( ptr, "listener=" );
   3166  1.2  christos 		ptr = lutil_strncopy( ptr, l->sl_url.bv_val, l->sl_url.bv_len );
   3167  1.2  christos 		*ptr++ = ' ';
   3168  1.2  christos 	}
   3169  1.2  christos 
   3170  1.2  christos 	if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) {
   3171  1.2  christos 		if ( rw & SLAP_TCP_RMEM ) {
   3172  1.2  christos 			ptr = lutil_strcopy( ptr, "read=" );
   3173  1.2  christos 		} else if ( rw & SLAP_TCP_WMEM ) {
   3174  1.2  christos 			ptr = lutil_strcopy( ptr, "write=" );
   3175  1.2  christos 		}
   3176  1.2  christos 	}
   3177  1.2  christos 
   3178  1.2  christos 	ptr = lutil_strcopy( ptr, buf );
   3179  1.2  christos 	*ptr = '\0';
   3180  1.2  christos 
   3181  1.2  christos 	assert( val->bv_val + val->bv_len == ptr );
   3182  1.2  christos 
   3183  1.2  christos 	return LDAP_SUCCESS;
   3184  1.2  christos }
   3185  1.2  christos 
   3186  1.2  christos static int
   3187  1.2  christos tcp_buffer_add_one( int argc, char **argv )
   3188  1.2  christos {
   3189  1.2  christos 	int rc = 0;
   3190  1.2  christos 	int size = -1, rw = 0;
   3191  1.2  christos 	Listener *l = NULL;
   3192  1.2  christos 
   3193  1.2  christos 	struct berval val;
   3194  1.2  christos 
   3195  1.2  christos 	/* parse */
   3196  1.2  christos 	rc = tcp_buffer_parse( NULL, argc, argv, &size, &rw, &l );
   3197  1.2  christos 	if ( rc != 0 ) {
   3198  1.2  christos 		return rc;
   3199  1.2  christos 	}
   3200  1.2  christos 
   3201  1.2  christos 	/* unparse for later use */
   3202  1.2  christos 	rc = tcp_buffer_unparse( size, rw, l, &val );
   3203  1.2  christos 	if ( rc != LDAP_SUCCESS ) {
   3204  1.2  christos 		return rc;
   3205  1.2  christos 	}
   3206  1.2  christos 
   3207  1.2  christos 	/* use parsed values */
   3208  1.2  christos 	if ( l != NULL ) {
   3209  1.2  christos 		int i;
   3210  1.2  christos 		Listener **ll = slapd_get_listeners();
   3211  1.2  christos 
   3212  1.2  christos 		for ( i = 0; ll[ i ] != NULL; i++ ) {
   3213  1.2  christos 			if ( ll[ i ] == l ) break;
   3214  1.2  christos 		}
   3215  1.2  christos 
   3216  1.2  christos 		if ( ll[ i ] == NULL ) {
   3217  1.2  christos 			return LDAP_NO_SUCH_ATTRIBUTE;
   3218  1.2  christos 		}
   3219  1.2  christos 
   3220  1.2  christos 		/* buffer only applies to TCP listeners;
   3221  1.2  christos 		 * we do not do any check here, and delegate them
   3222  1.2  christos 		 * to setsockopt(2) */
   3223  1.2  christos 		if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = size;
   3224  1.2  christos 		if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = size;
   3225  1.2  christos 
   3226  1.2  christos 		for ( i++ ; ll[ i ] != NULL && bvmatch( &l->sl_url, &ll[ i ]->sl_url ); i++ ) {
   3227  1.2  christos 			if ( rw & SLAP_TCP_RMEM ) ll[ i ]->sl_tcp_rmem = size;
   3228  1.2  christos 			if ( rw & SLAP_TCP_WMEM ) ll[ i ]->sl_tcp_wmem = size;
   3229  1.2  christos 		}
   3230  1.2  christos 
   3231  1.2  christos 	} else {
   3232  1.2  christos 		/* NOTE: this affects listeners without a specific setting,
   3233  1.2  christos 		 * does not set all listeners */
   3234  1.2  christos 		if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = size;
   3235  1.2  christos 		if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = size;
   3236  1.2  christos 	}
   3237  1.2  christos 
   3238  1.3  christos 	tcp_buffer = ch_realloc( tcp_buffer, sizeof( struct berval ) * ( tcp_buffer_num + 2 ) );
   3239  1.2  christos 	/* append */
   3240  1.2  christos 	tcp_buffer[ tcp_buffer_num ] = val;
   3241  1.2  christos 
   3242  1.2  christos 	tcp_buffer_num++;
   3243  1.2  christos 	BER_BVZERO( &tcp_buffer[ tcp_buffer_num ] );
   3244  1.2  christos 
   3245  1.2  christos 	return rc;
   3246  1.2  christos }
   3247  1.2  christos 
   3248  1.2  christos static int
   3249  1.2  christos config_tcp_buffer( ConfigArgs *c )
   3250  1.2  christos {
   3251  1.2  christos 	if ( c->op == SLAP_CONFIG_EMIT ) {
   3252  1.2  christos 		if ( tcp_buffer == NULL || BER_BVISNULL( &tcp_buffer[ 0 ] ) ) {
   3253  1.2  christos 			return 1;
   3254  1.2  christos 		}
   3255  1.2  christos 		value_add( &c->rvalue_vals, tcp_buffer );
   3256  1.2  christos 		value_add( &c->rvalue_nvals, tcp_buffer );
   3257  1.2  christos 
   3258  1.2  christos 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3259  1.2  christos 		if ( !c->line  ) {
   3260  1.2  christos 			tcp_buffer_delete( tcp_buffer );
   3261  1.2  christos 			ber_bvarray_free( tcp_buffer );
   3262  1.2  christos 			tcp_buffer = NULL;
   3263  1.2  christos 			tcp_buffer_num = 0;
   3264  1.2  christos 
   3265  1.2  christos 		} else {
   3266  1.2  christos 			int rc = 0;
   3267  1.2  christos 			int size = -1, rw = 0;
   3268  1.2  christos 			Listener *l = NULL;
   3269  1.2  christos 
   3270  1.2  christos 			struct berval val = BER_BVNULL;
   3271  1.2  christos 
   3272  1.2  christos 			int i;
   3273  1.2  christos 
   3274  1.2  christos 			if ( tcp_buffer_num == 0 ) {
   3275  1.2  christos 				return 1;
   3276  1.2  christos 			}
   3277  1.2  christos 
   3278  1.2  christos 			/* parse */
   3279  1.2  christos 			rc = tcp_buffer_parse( NULL, c->argc - 1, &c->argv[ 1 ], &size, &rw, &l );
   3280  1.2  christos 			if ( rc != 0 ) {
   3281  1.2  christos 				return 1;
   3282  1.2  christos 			}
   3283  1.2  christos 
   3284  1.2  christos 			/* unparse for later use */
   3285  1.2  christos 			rc = tcp_buffer_unparse( size, rw, l, &val );
   3286  1.2  christos 			if ( rc != LDAP_SUCCESS ) {
   3287  1.2  christos 				return 1;
   3288  1.2  christos 			}
   3289  1.2  christos 
   3290  1.2  christos 			for ( i = 0; !BER_BVISNULL( &tcp_buffer[ i ] ); i++ ) {
   3291  1.2  christos 				if ( bvmatch( &tcp_buffer[ i ], &val ) ) {
   3292  1.2  christos 					break;
   3293  1.2  christos 				}
   3294  1.2  christos 			}
   3295  1.2  christos 
   3296  1.2  christos 			if ( BER_BVISNULL( &tcp_buffer[ i ] ) ) {
   3297  1.2  christos 				/* not found */
   3298  1.2  christos 				rc = 1;
   3299  1.2  christos 				goto done;
   3300  1.2  christos 			}
   3301  1.2  christos 
   3302  1.2  christos 			tcp_buffer_delete_one( &tcp_buffer[ i ] );
   3303  1.2  christos 			ber_memfree( tcp_buffer[ i ].bv_val );
   3304  1.2  christos 			for ( ; i < tcp_buffer_num; i++ ) {
   3305  1.2  christos 				tcp_buffer[ i ] = tcp_buffer[ i + 1 ];
   3306  1.2  christos 			}
   3307  1.2  christos 			tcp_buffer_num--;
   3308  1.2  christos 
   3309  1.2  christos done:;
   3310  1.2  christos 			if ( !BER_BVISNULL( &val ) ) {
   3311  1.2  christos 				SLAP_FREE( val.bv_val );
   3312  1.2  christos 			}
   3313  1.2  christos 
   3314  1.2  christos 		}
   3315  1.2  christos 
   3316  1.2  christos 	} else {
   3317  1.2  christos 		int rc;
   3318  1.2  christos 
   3319  1.2  christos 		rc = tcp_buffer_add_one( c->argc - 1, &c->argv[ 1 ] );
   3320  1.2  christos 		if ( rc ) {
   3321  1.2  christos 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
   3322  1.2  christos 				"<%s> unable to add value #%d",
   3323  1.2  christos 				c->argv[0], tcp_buffer_num );
   3324  1.2  christos 			Debug( LDAP_DEBUG_ANY, "%s: %s\n",
   3325  1.3  christos 				c->log, c->cr_msg );
   3326  1.2  christos 			return 1;
   3327  1.2  christos 		}
   3328  1.2  christos 	}
   3329  1.2  christos 
   3330  1.2  christos 	return 0;
   3331  1.2  christos }
   3332  1.2  christos #endif /* LDAP_TCP_BUFFER */
   3333  1.2  christos 
   3334  1.1     lukem static int
   3335  1.1     lukem config_suffix(ConfigArgs *c)
   3336  1.1     lukem {
   3337  1.1     lukem 	Backend *tbe;
   3338  1.1     lukem 	struct berval pdn, ndn;
   3339  1.1     lukem 	char	*notallowed = NULL;
   3340  1.1     lukem 
   3341  1.1     lukem 	if ( c->be == frontendDB ) {
   3342  1.1     lukem 		notallowed = "frontend";
   3343  1.1     lukem 
   3344  1.1     lukem 	} else if ( SLAP_MONITOR(c->be) ) {
   3345  1.1     lukem 		notallowed = "monitor";
   3346  1.1     lukem 
   3347  1.1     lukem 	} else if ( SLAP_CONFIG(c->be) ) {
   3348  1.1     lukem 		notallowed = "config";
   3349  1.1     lukem 	}
   3350  1.1     lukem 
   3351  1.1     lukem 	if ( notallowed != NULL ) {
   3352  1.1     lukem 		char	buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
   3353  1.1     lukem 
   3354  1.1     lukem 		switch ( c->op ) {
   3355  1.1     lukem 		case LDAP_MOD_ADD:
   3356  1.1     lukem 		case LDAP_MOD_DELETE:
   3357  1.1     lukem 		case LDAP_MOD_REPLACE:
   3358  1.1     lukem 		case LDAP_MOD_INCREMENT:
   3359  1.1     lukem 		case SLAP_CONFIG_ADD:
   3360  1.1     lukem 			if ( !BER_BVISNULL( &c->value_dn ) ) {
   3361  1.1     lukem 				snprintf( buf, sizeof( buf ), "<%s> ",
   3362  1.1     lukem 						c->value_dn.bv_val );
   3363  1.1     lukem 			}
   3364  1.1     lukem 
   3365  1.1     lukem 			Debug(LDAP_DEBUG_ANY,
   3366  1.1     lukem 				"%s: suffix %snot allowed in %s database.\n",
   3367  1.1     lukem 				c->log, buf, notallowed );
   3368  1.1     lukem 			break;
   3369  1.1     lukem 
   3370  1.1     lukem 		case SLAP_CONFIG_EMIT:
   3371  1.1     lukem 			/* don't complain when emitting... */
   3372  1.1     lukem 			break;
   3373  1.1     lukem 
   3374  1.1     lukem 		default:
   3375  1.1     lukem 			/* FIXME: don't know what values may be valid;
   3376  1.1     lukem 			 * please remove assertion, or add legal values
   3377  1.1     lukem 			 * to either block */
   3378  1.1     lukem 			assert( 0 );
   3379  1.1     lukem 			break;
   3380  1.1     lukem 		}
   3381  1.1     lukem 
   3382  1.1     lukem 		return 1;
   3383  1.1     lukem 	}
   3384  1.1     lukem 
   3385  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3386  1.1     lukem 		if ( c->be->be_suffix == NULL
   3387  1.1     lukem 				|| BER_BVISNULL( &c->be->be_suffix[0] ) )
   3388  1.1     lukem 		{
   3389  1.1     lukem 			return 1;
   3390  1.1     lukem 		} else {
   3391  1.1     lukem 			value_add( &c->rvalue_vals, c->be->be_suffix );
   3392  1.1     lukem 			value_add( &c->rvalue_nvals, c->be->be_nsuffix );
   3393  1.1     lukem 			return 0;
   3394  1.1     lukem 		}
   3395  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3396  1.1     lukem 		if ( c->valx < 0 ) {
   3397  1.1     lukem 			ber_bvarray_free( c->be->be_suffix );
   3398  1.1     lukem 			ber_bvarray_free( c->be->be_nsuffix );
   3399  1.1     lukem 			c->be->be_suffix = NULL;
   3400  1.1     lukem 			c->be->be_nsuffix = NULL;
   3401  1.1     lukem 		} else {
   3402  1.1     lukem 			int i = c->valx;
   3403  1.1     lukem 			ch_free( c->be->be_suffix[i].bv_val );
   3404  1.1     lukem 			ch_free( c->be->be_nsuffix[i].bv_val );
   3405  1.1     lukem 			do {
   3406  1.1     lukem 				c->be->be_suffix[i] = c->be->be_suffix[i+1];
   3407  1.1     lukem 				c->be->be_nsuffix[i] = c->be->be_nsuffix[i+1];
   3408  1.1     lukem 				i++;
   3409  1.1     lukem 			} while ( !BER_BVISNULL( &c->be->be_suffix[i] ) );
   3410  1.1     lukem 		}
   3411  1.1     lukem 		return 0;
   3412  1.1     lukem 	}
   3413  1.1     lukem 
   3414  1.1     lukem #ifdef SLAPD_MONITOR_DN
   3415  1.1     lukem 	if(!strcasecmp(c->argv[1], SLAPD_MONITOR_DN)) {
   3416  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> DN is reserved for monitoring slapd",
   3417  1.1     lukem 			c->argv[0] );
   3418  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
   3419  1.1     lukem 			c->log, c->cr_msg, SLAPD_MONITOR_DN);
   3420  1.1     lukem 		return(1);
   3421  1.1     lukem 	}
   3422  1.1     lukem #endif
   3423  1.1     lukem 
   3424  1.2  christos 	if (SLAP_DB_ONE_SUFFIX( c->be ) && c->be->be_suffix &&
   3425  1.2  christos 		!BER_BVISNULL( &c->be->be_suffix[0] )) {
   3426  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> Only one suffix is allowed on this %s backend",
   3427  1.1     lukem 			c->argv[0], c->be->bd_info->bi_type );
   3428  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   3429  1.3  christos 			c->log, c->cr_msg );
   3430  1.1     lukem 		return(1);
   3431  1.1     lukem 	}
   3432  1.1     lukem 
   3433  1.1     lukem 	pdn = c->value_dn;
   3434  1.1     lukem 	ndn = c->value_ndn;
   3435  1.1     lukem 
   3436  1.1     lukem 	if (SLAP_DBHIDDEN( c->be ))
   3437  1.1     lukem 		tbe = NULL;
   3438  1.1     lukem 	else
   3439  1.1     lukem 		tbe = select_backend(&ndn, 0);
   3440  1.1     lukem 	if(tbe == c->be) {
   3441  1.1     lukem 		Debug( LDAP_DEBUG_ANY, "%s: suffix already served by this backend!.\n",
   3442  1.3  christos 			c->log );
   3443  1.1     lukem 		free(pdn.bv_val);
   3444  1.1     lukem 		free(ndn.bv_val);
   3445  1.2  christos 		return 1;
   3446  1.1     lukem 	} else if(tbe) {
   3447  1.1     lukem 		BackendDB *b2 = tbe;
   3448  1.1     lukem 
   3449  1.1     lukem 		/* Does tbe precede be? */
   3450  1.1     lukem 		while (( b2 = LDAP_STAILQ_NEXT(b2, be_next )) && b2 && b2 != c->be );
   3451  1.1     lukem 
   3452  1.1     lukem 		if ( b2 ) {
   3453  1.1     lukem 			char	*type = tbe->bd_info->bi_type;
   3454  1.1     lukem 
   3455  1.1     lukem 			if ( overlay_is_over( tbe ) ) {
   3456  1.1     lukem 				slap_overinfo	*oi = (slap_overinfo *)tbe->bd_info->bi_private;
   3457  1.1     lukem 				type = oi->oi_orig->bi_type;
   3458  1.1     lukem 			}
   3459  1.1     lukem 
   3460  1.1     lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> namingContext \"%s\" "
   3461  1.1     lukem 				"already served by a preceding %s database",
   3462  1.1     lukem 				c->argv[0], pdn.bv_val, type );
   3463  1.1     lukem 			Debug(LDAP_DEBUG_ANY, "%s: %s serving namingContext \"%s\"\n",
   3464  1.1     lukem 				c->log, c->cr_msg, tbe->be_suffix[0].bv_val);
   3465  1.1     lukem 			free(pdn.bv_val);
   3466  1.1     lukem 			free(ndn.bv_val);
   3467  1.1     lukem 			return(1);
   3468  1.1     lukem 		}
   3469  1.1     lukem 	}
   3470  1.1     lukem 	if(pdn.bv_len == 0 && default_search_nbase.bv_len) {
   3471  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: suffix DN empty and default search "
   3472  1.1     lukem 			"base provided \"%s\" (assuming okay)\n",
   3473  1.3  christos 			c->log, default_search_base.bv_val );
   3474  1.1     lukem 	}
   3475  1.1     lukem 	ber_bvarray_add(&c->be->be_suffix, &pdn);
   3476  1.1     lukem 	ber_bvarray_add(&c->be->be_nsuffix, &ndn);
   3477  1.1     lukem 	return(0);
   3478  1.1     lukem }
   3479  1.1     lukem 
   3480  1.1     lukem static int
   3481  1.1     lukem config_rootdn(ConfigArgs *c) {
   3482  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3483  1.1     lukem 		if ( !BER_BVISNULL( &c->be->be_rootdn )) {
   3484  1.1     lukem 			value_add_one(&c->rvalue_vals, &c->be->be_rootdn);
   3485  1.1     lukem 			value_add_one(&c->rvalue_nvals, &c->be->be_rootndn);
   3486  1.1     lukem 			return 0;
   3487  1.1     lukem 		} else {
   3488  1.1     lukem 			return 1;
   3489  1.1     lukem 		}
   3490  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3491  1.1     lukem 		ch_free( c->be->be_rootdn.bv_val );
   3492  1.1     lukem 		ch_free( c->be->be_rootndn.bv_val );
   3493  1.1     lukem 		BER_BVZERO( &c->be->be_rootdn );
   3494  1.1     lukem 		BER_BVZERO( &c->be->be_rootndn );
   3495  1.1     lukem 		return 0;
   3496  1.1     lukem 	}
   3497  1.1     lukem 	if ( !BER_BVISNULL( &c->be->be_rootdn )) {
   3498  1.1     lukem 		ch_free( c->be->be_rootdn.bv_val );
   3499  1.1     lukem 		ch_free( c->be->be_rootndn.bv_val );
   3500  1.1     lukem 	}
   3501  1.1     lukem 	c->be->be_rootdn = c->value_dn;
   3502  1.1     lukem 	c->be->be_rootndn = c->value_ndn;
   3503  1.1     lukem 	return(0);
   3504  1.1     lukem }
   3505  1.1     lukem 
   3506  1.1     lukem static int
   3507  1.1     lukem config_rootpw(ConfigArgs *c) {
   3508  1.1     lukem 	Backend *tbe;
   3509  1.1     lukem 
   3510  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3511  1.1     lukem 		if (!BER_BVISEMPTY(&c->be->be_rootpw)) {
   3512  1.1     lukem 			/* don't copy, because "rootpw" is marked
   3513  1.1     lukem 			 * as CFG_BERVAL */
   3514  1.1     lukem 			c->value_bv = c->be->be_rootpw;
   3515  1.1     lukem 			return 0;
   3516  1.1     lukem 		}
   3517  1.1     lukem 		return 1;
   3518  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3519  1.1     lukem 		ch_free( c->be->be_rootpw.bv_val );
   3520  1.1     lukem 		BER_BVZERO( &c->be->be_rootpw );
   3521  1.1     lukem 		return 0;
   3522  1.1     lukem 	}
   3523  1.1     lukem 
   3524  1.1     lukem 	tbe = select_backend(&c->be->be_rootndn, 0);
   3525  1.2  christos 	if(tbe != c->be && !SLAP_DBHIDDEN( c->be )) {
   3526  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> can only be set when rootdn is under suffix",
   3527  1.1     lukem 			c->argv[0] );
   3528  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   3529  1.3  christos 			c->log, c->cr_msg );
   3530  1.1     lukem 		return(1);
   3531  1.1     lukem 	}
   3532  1.1     lukem 	if ( !BER_BVISNULL( &c->be->be_rootpw ))
   3533  1.1     lukem 		ch_free( c->be->be_rootpw.bv_val );
   3534  1.1     lukem 	c->be->be_rootpw = c->value_bv;
   3535  1.1     lukem 	return(0);
   3536  1.1     lukem }
   3537  1.1     lukem 
   3538  1.1     lukem static int
   3539  1.1     lukem config_restrict(ConfigArgs *c) {
   3540  1.1     lukem 	slap_mask_t restrictops = 0;
   3541  1.1     lukem 	int i;
   3542  1.1     lukem 	slap_verbmasks restrictable_ops[] = {
   3543  1.1     lukem 		{ BER_BVC("bind"),		SLAP_RESTRICT_OP_BIND },
   3544  1.1     lukem 		{ BER_BVC("add"),		SLAP_RESTRICT_OP_ADD },
   3545  1.1     lukem 		{ BER_BVC("modify"),		SLAP_RESTRICT_OP_MODIFY },
   3546  1.1     lukem 		{ BER_BVC("rename"),		SLAP_RESTRICT_OP_RENAME },
   3547  1.1     lukem 		{ BER_BVC("modrdn"),		0 },
   3548  1.1     lukem 		{ BER_BVC("delete"),		SLAP_RESTRICT_OP_DELETE },
   3549  1.1     lukem 		{ BER_BVC("search"),		SLAP_RESTRICT_OP_SEARCH },
   3550  1.1     lukem 		{ BER_BVC("compare"),		SLAP_RESTRICT_OP_COMPARE },
   3551  1.1     lukem 		{ BER_BVC("read"),		SLAP_RESTRICT_OP_READS },
   3552  1.1     lukem 		{ BER_BVC("write"),		SLAP_RESTRICT_OP_WRITES },
   3553  1.1     lukem 		{ BER_BVC("extended"),		SLAP_RESTRICT_OP_EXTENDED },
   3554  1.1     lukem 		{ BER_BVC("extended=" LDAP_EXOP_START_TLS ),		SLAP_RESTRICT_EXOP_START_TLS },
   3555  1.1     lukem 		{ BER_BVC("extended=" LDAP_EXOP_MODIFY_PASSWD ),	SLAP_RESTRICT_EXOP_MODIFY_PASSWD },
   3556  1.1     lukem 		{ BER_BVC("extended=" LDAP_EXOP_X_WHO_AM_I ),		SLAP_RESTRICT_EXOP_WHOAMI },
   3557  1.1     lukem 		{ BER_BVC("extended=" LDAP_EXOP_X_CANCEL ),		SLAP_RESTRICT_EXOP_CANCEL },
   3558  1.1     lukem 		{ BER_BVC("all"),		SLAP_RESTRICT_OP_ALL },
   3559  1.1     lukem 		{ BER_BVNULL,	0 }
   3560  1.1     lukem 	};
   3561  1.1     lukem 
   3562  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3563  1.1     lukem 		return mask_to_verbs( restrictable_ops, c->be->be_restrictops,
   3564  1.1     lukem 			&c->rvalue_vals );
   3565  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3566  1.1     lukem 		if ( !c->line ) {
   3567  1.1     lukem 			c->be->be_restrictops = 0;
   3568  1.1     lukem 		} else {
   3569  1.2  christos 			i = verb_to_mask( c->line, restrictable_ops );
   3570  1.2  christos 			c->be->be_restrictops &= ~restrictable_ops[i].mask;
   3571  1.1     lukem 		}
   3572  1.1     lukem 		return 0;
   3573  1.1     lukem 	}
   3574  1.1     lukem 	i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops );
   3575  1.1     lukem 	if ( i ) {
   3576  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown operation", c->argv[0] );
   3577  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   3578  1.1     lukem 			c->log, c->cr_msg, c->argv[i]);
   3579  1.1     lukem 		return(1);
   3580  1.1     lukem 	}
   3581  1.1     lukem 	if ( restrictops & SLAP_RESTRICT_OP_EXTENDED )
   3582  1.1     lukem 		restrictops &= ~SLAP_RESTRICT_EXOP_MASK;
   3583  1.1     lukem 	c->be->be_restrictops |= restrictops;
   3584  1.1     lukem 	return(0);
   3585  1.1     lukem }
   3586  1.1     lukem 
   3587  1.1     lukem static int
   3588  1.1     lukem config_allows(ConfigArgs *c) {
   3589  1.1     lukem 	slap_mask_t allows = 0;
   3590  1.1     lukem 	int i;
   3591  1.1     lukem 	slap_verbmasks allowable_ops[] = {
   3592  1.1     lukem 		{ BER_BVC("bind_v2"),		SLAP_ALLOW_BIND_V2 },
   3593  1.1     lukem 		{ BER_BVC("bind_anon_cred"),	SLAP_ALLOW_BIND_ANON_CRED },
   3594  1.1     lukem 		{ BER_BVC("bind_anon_dn"),	SLAP_ALLOW_BIND_ANON_DN },
   3595  1.1     lukem 		{ BER_BVC("update_anon"),	SLAP_ALLOW_UPDATE_ANON },
   3596  1.1     lukem 		{ BER_BVC("proxy_authz_anon"),	SLAP_ALLOW_PROXY_AUTHZ_ANON },
   3597  1.1     lukem 		{ BER_BVNULL,	0 }
   3598  1.1     lukem 	};
   3599  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3600  1.1     lukem 		return mask_to_verbs( allowable_ops, global_allows, &c->rvalue_vals );
   3601  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3602  1.1     lukem 		if ( !c->line ) {
   3603  1.1     lukem 			global_allows = 0;
   3604  1.1     lukem 		} else {
   3605  1.2  christos 			i = verb_to_mask( c->line, allowable_ops );
   3606  1.2  christos 			global_allows &= ~allowable_ops[i].mask;
   3607  1.1     lukem 		}
   3608  1.1     lukem 		return 0;
   3609  1.1     lukem 	}
   3610  1.1     lukem 	i = verbs_to_mask(c->argc, c->argv, allowable_ops, &allows);
   3611  1.1     lukem 	if ( i ) {
   3612  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] );
   3613  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   3614  1.1     lukem 			c->log, c->cr_msg, c->argv[i]);
   3615  1.1     lukem 		return(1);
   3616  1.1     lukem 	}
   3617  1.1     lukem 	global_allows |= allows;
   3618  1.1     lukem 	return(0);
   3619  1.1     lukem }
   3620  1.1     lukem 
   3621  1.1     lukem static int
   3622  1.1     lukem config_disallows(ConfigArgs *c) {
   3623  1.1     lukem 	slap_mask_t disallows = 0;
   3624  1.1     lukem 	int i;
   3625  1.1     lukem 	slap_verbmasks disallowable_ops[] = {
   3626  1.1     lukem 		{ BER_BVC("bind_anon"),		SLAP_DISALLOW_BIND_ANON },
   3627  1.1     lukem 		{ BER_BVC("bind_simple"),	SLAP_DISALLOW_BIND_SIMPLE },
   3628  1.1     lukem 		{ BER_BVC("tls_2_anon"),		SLAP_DISALLOW_TLS_2_ANON },
   3629  1.1     lukem 		{ BER_BVC("tls_authc"),		SLAP_DISALLOW_TLS_AUTHC },
   3630  1.2  christos 		{ BER_BVC("proxy_authz_non_critical"),	SLAP_DISALLOW_PROXY_AUTHZ_N_CRIT },
   3631  1.2  christos 		{ BER_BVC("dontusecopy_non_critical"),	SLAP_DISALLOW_DONTUSECOPY_N_CRIT },
   3632  1.1     lukem 		{ BER_BVNULL, 0 }
   3633  1.1     lukem 	};
   3634  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3635  1.1     lukem 		return mask_to_verbs( disallowable_ops, global_disallows, &c->rvalue_vals );
   3636  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3637  1.1     lukem 		if ( !c->line ) {
   3638  1.1     lukem 			global_disallows = 0;
   3639  1.1     lukem 		} else {
   3640  1.2  christos 			i = verb_to_mask( c->line, disallowable_ops );
   3641  1.2  christos 			global_disallows &= ~disallowable_ops[i].mask;
   3642  1.1     lukem 		}
   3643  1.1     lukem 		return 0;
   3644  1.1     lukem 	}
   3645  1.1     lukem 	i = verbs_to_mask(c->argc, c->argv, disallowable_ops, &disallows);
   3646  1.1     lukem 	if ( i ) {
   3647  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature", c->argv[0] );
   3648  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   3649  1.1     lukem 			c->log, c->cr_msg, c->argv[i]);
   3650  1.1     lukem 		return(1);
   3651  1.1     lukem 	}
   3652  1.1     lukem 	global_disallows |= disallows;
   3653  1.1     lukem 	return(0);
   3654  1.1     lukem }
   3655  1.1     lukem 
   3656  1.1     lukem static int
   3657  1.1     lukem config_requires(ConfigArgs *c) {
   3658  1.1     lukem 	slap_mask_t requires = frontendDB->be_requires;
   3659  1.1     lukem 	int i, argc = c->argc;
   3660  1.1     lukem 	char **argv = c->argv;
   3661  1.1     lukem 
   3662  1.1     lukem 	slap_verbmasks requires_ops[] = {
   3663  1.1     lukem 		{ BER_BVC("bind"),		SLAP_REQUIRE_BIND },
   3664  1.1     lukem 		{ BER_BVC("LDAPv3"),		SLAP_REQUIRE_LDAP_V3 },
   3665  1.1     lukem 		{ BER_BVC("authc"),		SLAP_REQUIRE_AUTHC },
   3666  1.1     lukem 		{ BER_BVC("sasl"),		SLAP_REQUIRE_SASL },
   3667  1.1     lukem 		{ BER_BVC("strong"),		SLAP_REQUIRE_STRONG },
   3668  1.1     lukem 		{ BER_BVNULL, 0 }
   3669  1.1     lukem 	};
   3670  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3671  1.1     lukem 		return mask_to_verbs( requires_ops, c->be->be_requires, &c->rvalue_vals );
   3672  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3673  1.1     lukem 		if ( !c->line ) {
   3674  1.1     lukem 			c->be->be_requires = 0;
   3675  1.1     lukem 		} else {
   3676  1.2  christos 			i = verb_to_mask( c->line, requires_ops );
   3677  1.2  christos 			c->be->be_requires &= ~requires_ops[i].mask;
   3678  1.1     lukem 		}
   3679  1.1     lukem 		return 0;
   3680  1.1     lukem 	}
   3681  1.1     lukem 	/* "none" can only be first, to wipe out default/global values */
   3682  1.1     lukem 	if ( strcasecmp( c->argv[ 1 ], "none" ) == 0 ) {
   3683  1.1     lukem 		argv++;
   3684  1.1     lukem 		argc--;
   3685  1.1     lukem 		requires = 0;
   3686  1.1     lukem 	}
   3687  1.2  christos 	i = verbs_to_mask(argc, argv, requires_ops, &requires);
   3688  1.2  christos 	if ( i ) {
   3689  1.2  christos 		if (strcasecmp( c->argv[ i ], "none" ) == 0 ) {
   3690  1.2  christos 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> \"none\" (#%d) must be listed first", c->argv[0], i - 1 );
   3691  1.2  christos 			Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   3692  1.3  christos 				c->log, c->cr_msg );
   3693  1.2  christos 		} else {
   3694  1.2  christos 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown feature #%d", c->argv[0], i - 1 );
   3695  1.2  christos 			Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
   3696  1.2  christos 				c->log, c->cr_msg, c->argv[i]);
   3697  1.2  christos 		}
   3698  1.2  christos 		return(1);
   3699  1.2  christos 	}
   3700  1.2  christos 	c->be->be_requires = requires;
   3701  1.2  christos 	return(0);
   3702  1.2  christos }
   3703  1.2  christos 
   3704  1.2  christos static int
   3705  1.2  christos config_extra_attrs(ConfigArgs *c)
   3706  1.2  christos {
   3707  1.2  christos 	assert( c->be != NULL );
   3708  1.2  christos 
   3709  1.2  christos 	if ( c->op == SLAP_CONFIG_EMIT ) {
   3710  1.2  christos 		int i;
   3711  1.2  christos 
   3712  1.2  christos 		if ( c->be->be_extra_anlist == NULL ) {
   3713  1.2  christos 			return 1;
   3714  1.2  christos 		}
   3715  1.2  christos 
   3716  1.2  christos 		for ( i = 0; !BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ); i++ ) {
   3717  1.2  christos 			value_add_one( &c->rvalue_vals, &c->be->be_extra_anlist[i].an_name );
   3718  1.2  christos 		}
   3719  1.2  christos 
   3720  1.2  christos 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3721  1.2  christos 		if ( c->be->be_extra_anlist == NULL ) {
   3722  1.2  christos 			return 1;
   3723  1.2  christos 		}
   3724  1.2  christos 
   3725  1.2  christos 		if ( c->valx < 0 ) {
   3726  1.2  christos 			anlist_free( c->be->be_extra_anlist, 1, NULL );
   3727  1.2  christos 			c->be->be_extra_anlist = NULL;
   3728  1.2  christos 
   3729  1.2  christos 		} else {
   3730  1.2  christos 			int i;
   3731  1.2  christos 
   3732  1.2  christos 			for ( i = 0; i < c->valx && !BER_BVISNULL( &c->be->be_extra_anlist[i + 1].an_name ); i++ )
   3733  1.2  christos 				;
   3734  1.2  christos 
   3735  1.2  christos 			if ( BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ) ) {
   3736  1.2  christos 				return 1;
   3737  1.2  christos 			}
   3738  1.2  christos 
   3739  1.2  christos 			ch_free( c->be->be_extra_anlist[i].an_name.bv_val );
   3740  1.2  christos 
   3741  1.2  christos 			for ( ; !BER_BVISNULL( &c->be->be_extra_anlist[i].an_name ); i++ ) {
   3742  1.2  christos 				c->be->be_extra_anlist[i] = c->be->be_extra_anlist[i + 1];
   3743  1.2  christos 			}
   3744  1.2  christos 		}
   3745  1.2  christos 
   3746  1.2  christos 	} else {
   3747  1.2  christos 		c->be->be_extra_anlist = str2anlist( c->be->be_extra_anlist, c->argv[1], " ,\t" );
   3748  1.2  christos 		if ( c->be->be_extra_anlist == NULL ) {
   3749  1.2  christos 			return 1;
   3750  1.1     lukem 		}
   3751  1.1     lukem 	}
   3752  1.2  christos 
   3753  1.2  christos 	return 0;
   3754  1.1     lukem }
   3755  1.1     lukem 
   3756  1.1     lukem static int
   3757  1.1     lukem config_referral(ConfigArgs *c) {
   3758  1.1     lukem 	struct berval val;
   3759  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3760  1.1     lukem 		if ( default_referral ) {
   3761  1.1     lukem 			value_add( &c->rvalue_vals, default_referral );
   3762  1.1     lukem 			return 0;
   3763  1.1     lukem 		} else {
   3764  1.1     lukem 			return 1;
   3765  1.1     lukem 		}
   3766  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3767  1.1     lukem 		if ( c->valx < 0 ) {
   3768  1.1     lukem 			ber_bvarray_free( default_referral );
   3769  1.1     lukem 			default_referral = NULL;
   3770  1.1     lukem 		} else {
   3771  1.1     lukem 			int i = c->valx;
   3772  1.1     lukem 			ch_free( default_referral[i].bv_val );
   3773  1.1     lukem 			for (; default_referral[i].bv_val; i++ )
   3774  1.1     lukem 				default_referral[i] = default_referral[i+1];
   3775  1.1     lukem 		}
   3776  1.1     lukem 		return 0;
   3777  1.1     lukem 	}
   3778  1.1     lukem 	if(validate_global_referral(c->argv[1])) {
   3779  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] );
   3780  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
   3781  1.1     lukem 			c->log, c->cr_msg, c->argv[1]);
   3782  1.1     lukem 		return(1);
   3783  1.1     lukem 	}
   3784  1.1     lukem 
   3785  1.1     lukem 	ber_str2bv(c->argv[1], 0, 0, &val);
   3786  1.1     lukem 	if(value_add_one(&default_referral, &val)) return(LDAP_OTHER);
   3787  1.1     lukem 	return(0);
   3788  1.1     lukem }
   3789  1.1     lukem 
   3790  1.1     lukem static struct {
   3791  1.1     lukem 	struct berval key;
   3792  1.1     lukem 	int off;
   3793  1.1     lukem } sec_keys[] = {
   3794  1.1     lukem 	{ BER_BVC("ssf="), offsetof(slap_ssf_set_t, sss_ssf) },
   3795  1.1     lukem 	{ BER_BVC("transport="), offsetof(slap_ssf_set_t, sss_transport) },
   3796  1.1     lukem 	{ BER_BVC("tls="), offsetof(slap_ssf_set_t, sss_tls) },
   3797  1.1     lukem 	{ BER_BVC("sasl="), offsetof(slap_ssf_set_t, sss_sasl) },
   3798  1.1     lukem 	{ BER_BVC("update_ssf="), offsetof(slap_ssf_set_t, sss_update_ssf) },
   3799  1.1     lukem 	{ BER_BVC("update_transport="), offsetof(slap_ssf_set_t, sss_update_transport) },
   3800  1.1     lukem 	{ BER_BVC("update_tls="), offsetof(slap_ssf_set_t, sss_update_tls) },
   3801  1.1     lukem 	{ BER_BVC("update_sasl="), offsetof(slap_ssf_set_t, sss_update_sasl) },
   3802  1.1     lukem 	{ BER_BVC("simple_bind="), offsetof(slap_ssf_set_t, sss_simple_bind) },
   3803  1.1     lukem 	{ BER_BVNULL, 0 }
   3804  1.1     lukem };
   3805  1.1     lukem 
   3806  1.1     lukem static int
   3807  1.1     lukem config_security(ConfigArgs *c) {
   3808  1.1     lukem 	slap_ssf_set_t *set = &c->be->be_ssf_set;
   3809  1.1     lukem 	char *next;
   3810  1.1     lukem 	int i, j;
   3811  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3812  1.1     lukem 		char numbuf[32];
   3813  1.1     lukem 		struct berval bv;
   3814  1.1     lukem 		slap_ssf_t *tgt;
   3815  1.1     lukem 		int rc = 1;
   3816  1.1     lukem 
   3817  1.1     lukem 		for (i=0; !BER_BVISNULL( &sec_keys[i].key ); i++) {
   3818  1.1     lukem 			tgt = (slap_ssf_t *)((char *)set + sec_keys[i].off);
   3819  1.1     lukem 			if ( *tgt ) {
   3820  1.1     lukem 				rc = 0;
   3821  1.1     lukem 				bv.bv_len = snprintf( numbuf, sizeof( numbuf ), "%u", *tgt );
   3822  1.1     lukem 				if ( bv.bv_len >= sizeof( numbuf ) ) {
   3823  1.1     lukem 					ber_bvarray_free_x( c->rvalue_vals, NULL );
   3824  1.1     lukem 					c->rvalue_vals = NULL;
   3825  1.1     lukem 					rc = 1;
   3826  1.1     lukem 					break;
   3827  1.1     lukem 				}
   3828  1.1     lukem 				bv.bv_len += sec_keys[i].key.bv_len;
   3829  1.1     lukem 				bv.bv_val = ch_malloc( bv.bv_len + 1);
   3830  1.1     lukem 				next = lutil_strcopy( bv.bv_val, sec_keys[i].key.bv_val );
   3831  1.1     lukem 				strcpy( next, numbuf );
   3832  1.1     lukem 				ber_bvarray_add( &c->rvalue_vals, &bv );
   3833  1.1     lukem 			}
   3834  1.1     lukem 		}
   3835  1.1     lukem 		return rc;
   3836  1.1     lukem 	}
   3837  1.1     lukem 	for(i = 1; i < c->argc; i++) {
   3838  1.1     lukem 		slap_ssf_t *tgt = NULL;
   3839  1.1     lukem 		char *src = NULL;
   3840  1.1     lukem 		for ( j=0; !BER_BVISNULL( &sec_keys[j].key ); j++ ) {
   3841  1.1     lukem 			if(!strncasecmp(c->argv[i], sec_keys[j].key.bv_val,
   3842  1.1     lukem 				sec_keys[j].key.bv_len)) {
   3843  1.1     lukem 				src = c->argv[i] + sec_keys[j].key.bv_len;
   3844  1.1     lukem 				tgt = (slap_ssf_t *)((char *)set + sec_keys[j].off);
   3845  1.1     lukem 				break;
   3846  1.1     lukem 			}
   3847  1.1     lukem 		}
   3848  1.1     lukem 		if ( !tgt ) {
   3849  1.1     lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unknown factor", c->argv[0] );
   3850  1.1     lukem 			Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
   3851  1.1     lukem 				c->log, c->cr_msg, c->argv[i]);
   3852  1.1     lukem 			return(1);
   3853  1.1     lukem 		}
   3854  1.1     lukem 
   3855  1.1     lukem 		if ( lutil_atou( tgt, src ) != 0 ) {
   3856  1.1     lukem 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> unable to parse factor", c->argv[0] );
   3857  1.1     lukem 			Debug(LDAP_DEBUG_ANY, "%s: %s \"%s\"\n",
   3858  1.1     lukem 				c->log, c->cr_msg, c->argv[i]);
   3859  1.1     lukem 			return(1);
   3860  1.1     lukem 		}
   3861  1.1     lukem 	}
   3862  1.1     lukem 	return(0);
   3863  1.1     lukem }
   3864  1.1     lukem 
   3865  1.1     lukem char *
   3866  1.1     lukem anlist_unparse( AttributeName *an, char *ptr, ber_len_t buflen ) {
   3867  1.1     lukem 	int comma = 0;
   3868  1.1     lukem 	char *start = ptr;
   3869  1.1     lukem 
   3870  1.1     lukem 	for (; !BER_BVISNULL( &an->an_name ); an++) {
   3871  1.1     lukem 		/* if buflen == 0, assume the buffer size has been
   3872  1.1     lukem 		 * already checked otherwise */
   3873  1.1     lukem 		if ( buflen > 0 && buflen - ( ptr - start ) < comma + an->an_name.bv_len ) return NULL;
   3874  1.1     lukem 		if ( comma ) *ptr++ = ',';
   3875  1.1     lukem 		ptr = lutil_strcopy( ptr, an->an_name.bv_val );
   3876  1.1     lukem 		comma = 1;
   3877  1.1     lukem 	}
   3878  1.1     lukem 	return ptr;
   3879  1.1     lukem }
   3880  1.1     lukem 
   3881  1.3  christos int
   3882  1.3  christos slap_bv_x_ordered_unparse( BerVarray in, BerVarray *out )
   3883  1.3  christos {
   3884  1.3  christos 	int		i;
   3885  1.3  christos 	BerVarray	bva = NULL;
   3886  1.3  christos 	char		ibuf[32], *ptr;
   3887  1.3  christos 	struct berval	idx;
   3888  1.3  christos 
   3889  1.3  christos 	assert( in != NULL );
   3890  1.3  christos 
   3891  1.3  christos 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
   3892  1.3  christos 		/* count'em */ ;
   3893  1.3  christos 
   3894  1.3  christos 	if ( i == 0 ) {
   3895  1.3  christos 		return 1;
   3896  1.3  christos 	}
   3897  1.3  christos 
   3898  1.3  christos 	idx.bv_val = ibuf;
   3899  1.3  christos 
   3900  1.3  christos 	bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
   3901  1.3  christos 	BER_BVZERO( &bva[ 0 ] );
   3902  1.3  christos 
   3903  1.3  christos 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
   3904  1.3  christos 		idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), SLAP_X_ORDERED_FMT, i );
   3905  1.3  christos 		if ( idx.bv_len >= sizeof( ibuf ) ) {
   3906  1.3  christos 			ber_bvarray_free( bva );
   3907  1.3  christos 			return 1;
   3908  1.3  christos 		}
   3909  1.3  christos 
   3910  1.3  christos 		bva[i].bv_len = idx.bv_len + in[i].bv_len;
   3911  1.3  christos 		bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
   3912  1.3  christos 		ptr = lutil_strcopy( bva[i].bv_val, ibuf );
   3913  1.3  christos 		ptr = lutil_strcopy( ptr, in[i].bv_val );
   3914  1.3  christos 		*ptr = '\0';
   3915  1.3  christos 		BER_BVZERO( &bva[ i + 1 ] );
   3916  1.3  christos 	}
   3917  1.3  christos 
   3918  1.3  christos 	*out = bva;
   3919  1.3  christos 	return 0;
   3920  1.3  christos }
   3921  1.3  christos 
   3922  1.1     lukem static int
   3923  1.1     lukem config_updatedn(ConfigArgs *c) {
   3924  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3925  1.1     lukem 		if (!BER_BVISEMPTY(&c->be->be_update_ndn)) {
   3926  1.1     lukem 			value_add_one(&c->rvalue_vals, &c->be->be_update_ndn);
   3927  1.1     lukem 			value_add_one(&c->rvalue_nvals, &c->be->be_update_ndn);
   3928  1.1     lukem 			return 0;
   3929  1.1     lukem 		}
   3930  1.1     lukem 		return 1;
   3931  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   3932  1.1     lukem 		ch_free( c->be->be_update_ndn.bv_val );
   3933  1.1     lukem 		BER_BVZERO( &c->be->be_update_ndn );
   3934  1.1     lukem 		SLAP_DBFLAGS(c->be) ^= (SLAP_DBFLAG_SHADOW | SLAP_DBFLAG_SLURP_SHADOW);
   3935  1.1     lukem 		return 0;
   3936  1.1     lukem 	}
   3937  1.1     lukem 	if(SLAP_SHADOW(c->be)) {
   3938  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> database already shadowed", c->argv[0] );
   3939  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   3940  1.3  christos 			c->log, c->cr_msg );
   3941  1.1     lukem 		return(1);
   3942  1.1     lukem 	}
   3943  1.1     lukem 
   3944  1.1     lukem 	ber_memfree_x( c->value_dn.bv_val, NULL );
   3945  1.1     lukem 	if ( !BER_BVISNULL( &c->be->be_update_ndn ) ) {
   3946  1.1     lukem 		ber_memfree_x( c->be->be_update_ndn.bv_val, NULL );
   3947  1.1     lukem 	}
   3948  1.1     lukem 	c->be->be_update_ndn = c->value_ndn;
   3949  1.1     lukem 	BER_BVZERO( &c->value_dn );
   3950  1.1     lukem 	BER_BVZERO( &c->value_ndn );
   3951  1.1     lukem 
   3952  1.1     lukem 	return config_slurp_shadow( c );
   3953  1.1     lukem }
   3954  1.1     lukem 
   3955  1.1     lukem int
   3956  1.2  christos config_shadow( ConfigArgs *c, slap_mask_t flag )
   3957  1.1     lukem {
   3958  1.1     lukem 	char	*notallowed = NULL;
   3959  1.1     lukem 
   3960  1.1     lukem 	if ( c->be == frontendDB ) {
   3961  1.1     lukem 		notallowed = "frontend";
   3962  1.1     lukem 
   3963  1.1     lukem 	} else if ( SLAP_MONITOR(c->be) ) {
   3964  1.1     lukem 		notallowed = "monitor";
   3965  1.1     lukem 	}
   3966  1.1     lukem 
   3967  1.1     lukem 	if ( notallowed != NULL ) {
   3968  1.3  christos 		Debug( LDAP_DEBUG_ANY, "%s: %s database cannot be shadow.\n", c->log, notallowed );
   3969  1.1     lukem 		return 1;
   3970  1.1     lukem 	}
   3971  1.1     lukem 
   3972  1.2  christos 	if ( SLAP_SHADOW(c->be) ) {
   3973  1.2  christos 		/* if already shadow, only check consistency */
   3974  1.2  christos 		if ( ( SLAP_DBFLAGS(c->be) & flag ) != flag ) {
   3975  1.2  christos 			Debug( LDAP_DEBUG_ANY, "%s: inconsistent shadow flag 0x%lx.\n",
   3976  1.3  christos 				c->log, flag );
   3977  1.2  christos 			return 1;
   3978  1.2  christos 		}
   3979  1.2  christos 
   3980  1.2  christos 	} else {
   3981  1.2  christos 		SLAP_DBFLAGS(c->be) |= (SLAP_DBFLAG_SHADOW | flag);
   3982  1.3  christos 		if ( !SLAP_MULTIPROVIDER( c->be ))
   3983  1.2  christos 			SLAP_DBFLAGS(c->be) |= SLAP_DBFLAG_SINGLE_SHADOW;
   3984  1.2  christos 	}
   3985  1.1     lukem 
   3986  1.1     lukem 	return 0;
   3987  1.1     lukem }
   3988  1.1     lukem 
   3989  1.1     lukem static int
   3990  1.1     lukem config_updateref(ConfigArgs *c) {
   3991  1.1     lukem 	struct berval val;
   3992  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   3993  1.1     lukem 		if ( c->be->be_update_refs ) {
   3994  1.1     lukem 			value_add( &c->rvalue_vals, c->be->be_update_refs );
   3995  1.1     lukem 			return 0;
   3996  1.1     lukem 		} else {
   3997  1.1     lukem 			return 1;
   3998  1.1     lukem 		}
   3999  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   4000  1.1     lukem 		if ( c->valx < 0 ) {
   4001  1.1     lukem 			ber_bvarray_free( c->be->be_update_refs );
   4002  1.1     lukem 			c->be->be_update_refs = NULL;
   4003  1.1     lukem 		} else {
   4004  1.1     lukem 			int i = c->valx;
   4005  1.1     lukem 			ch_free( c->be->be_update_refs[i].bv_val );
   4006  1.1     lukem 			for (; c->be->be_update_refs[i].bv_val; i++)
   4007  1.1     lukem 				c->be->be_update_refs[i] = c->be->be_update_refs[i+1];
   4008  1.1     lukem 		}
   4009  1.1     lukem 		return 0;
   4010  1.1     lukem 	}
   4011  1.1     lukem 	if(!SLAP_SHADOW(c->be) && !c->be->be_syncinfo) {
   4012  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must appear after syncrepl or updatedn",
   4013  1.1     lukem 			c->argv[0] );
   4014  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s\n",
   4015  1.3  christos 			c->log, c->cr_msg );
   4016  1.1     lukem 		return(1);
   4017  1.1     lukem 	}
   4018  1.1     lukem 
   4019  1.1     lukem 	if(validate_global_referral(c->argv[1])) {
   4020  1.1     lukem 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid URL", c->argv[0] );
   4021  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: %s (%s)\n",
   4022  1.1     lukem 			c->log, c->cr_msg, c->argv[1]);
   4023  1.1     lukem 		return(1);
   4024  1.1     lukem 	}
   4025  1.1     lukem 	ber_str2bv(c->argv[1], 0, 0, &val);
   4026  1.1     lukem 	if(value_add_one(&c->be->be_update_refs, &val)) return(LDAP_OTHER);
   4027  1.1     lukem 	return(0);
   4028  1.1     lukem }
   4029  1.1     lukem 
   4030  1.1     lukem static int
   4031  1.1     lukem config_obsolete(ConfigArgs *c) {
   4032  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT)
   4033  1.1     lukem 		return 1;
   4034  1.1     lukem 
   4035  1.1     lukem 	snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> keyword is obsolete (ignored)",
   4036  1.1     lukem 		c->argv[0] );
   4037  1.3  christos 	Debug(LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
   4038  1.1     lukem 	return(0);
   4039  1.1     lukem }
   4040  1.1     lukem 
   4041  1.1     lukem static int
   4042  1.1     lukem config_include(ConfigArgs *c) {
   4043  1.1     lukem 	int savelineno = c->lineno;
   4044  1.1     lukem 	int rc;
   4045  1.1     lukem 	ConfigFile *cf;
   4046  1.1     lukem 	ConfigFile *cfsave = cfn;
   4047  1.1     lukem 	ConfigFile *cf2 = NULL;
   4048  1.1     lukem 
   4049  1.1     lukem 	/* Leftover from RE23. No dynamic config for include files */
   4050  1.1     lukem 	if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE )
   4051  1.1     lukem 		return 1;
   4052  1.1     lukem 
   4053  1.1     lukem 	cf = ch_calloc( 1, sizeof(ConfigFile));
   4054  1.1     lukem 	if ( cfn->c_kids ) {
   4055  1.1     lukem 		for (cf2=cfn->c_kids; cf2 && cf2->c_sibs; cf2=cf2->c_sibs) ;
   4056  1.1     lukem 		cf2->c_sibs = cf;
   4057  1.1     lukem 	} else {
   4058  1.1     lukem 		cfn->c_kids = cf;
   4059  1.1     lukem 	}
   4060  1.1     lukem 	cfn = cf;
   4061  1.1     lukem 	ber_str2bv( c->argv[1], 0, 1, &cf->c_file );
   4062  1.1     lukem 	rc = read_config_file(c->argv[1], c->depth + 1, c, config_back_cf_table);
   4063  1.1     lukem 	c->lineno = savelineno - 1;
   4064  1.1     lukem 	cfn = cfsave;
   4065  1.1     lukem 	if ( rc ) {
   4066  1.1     lukem 		if ( cf2 ) cf2->c_sibs = NULL;
   4067  1.1     lukem 		else cfn->c_kids = NULL;
   4068  1.1     lukem 		ch_free( cf->c_file.bv_val );
   4069  1.1     lukem 		ch_free( cf );
   4070  1.1     lukem 	} else {
   4071  1.1     lukem 		c->ca_private = cf;
   4072  1.1     lukem 	}
   4073  1.1     lukem 	return(rc);
   4074  1.1     lukem }
   4075  1.1     lukem 
   4076  1.1     lukem #ifdef HAVE_TLS
   4077  1.1     lukem static int
   4078  1.2  christos config_tls_cleanup(ConfigArgs *c) {
   4079  1.2  christos 	int rc = 0;
   4080  1.2  christos 
   4081  1.2  christos 	if ( slap_tls_ld ) {
   4082  1.2  christos 		int opt = 1;
   4083  1.2  christos 
   4084  1.2  christos 		ldap_pvt_tls_ctx_free( slap_tls_ctx );
   4085  1.2  christos 		slap_tls_ctx = NULL;
   4086  1.2  christos 
   4087  1.2  christos 		/* Force new ctx to be created */
   4088  1.2  christos 		rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
   4089  1.2  christos 		if( rc == 0 ) {
   4090  1.2  christos 			/* The ctx's refcount is bumped up here */
   4091  1.2  christos 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );
   4092  1.2  christos 			/* This is a no-op if it's already loaded */
   4093  1.2  christos 			load_extop( &slap_EXOP_START_TLS, 0, starttls_extop );
   4094  1.2  christos 		} else {
   4095  1.2  christos 			if ( rc == LDAP_NOT_SUPPORTED )
   4096  1.2  christos 				rc = LDAP_UNWILLING_TO_PERFORM;
   4097  1.2  christos 			else
   4098  1.2  christos 				rc = LDAP_OTHER;
   4099  1.2  christos 		}
   4100  1.2  christos 	}
   4101  1.2  christos 	return rc;
   4102  1.2  christos }
   4103  1.2  christos 
   4104  1.2  christos static int
   4105  1.1     lukem config_tls_option(ConfigArgs *c) {
   4106  1.3  christos 	int flag, rc;
   4107  1.3  christos 	int berval = 0;
   4108  1.1     lukem 	LDAP *ld = slap_tls_ld;
   4109  1.1     lukem 	switch(c->type) {
   4110  1.1     lukem 	case CFG_TLS_RAND:	flag = LDAP_OPT_X_TLS_RANDOM_FILE;	ld = NULL; break;
   4111  1.1     lukem 	case CFG_TLS_CIPHER:	flag = LDAP_OPT_X_TLS_CIPHER_SUITE;	break;
   4112  1.1     lukem 	case CFG_TLS_CERT_FILE:	flag = LDAP_OPT_X_TLS_CERTFILE;		break;
   4113  1.1     lukem 	case CFG_TLS_CERT_KEY:	flag = LDAP_OPT_X_TLS_KEYFILE;		break;
   4114  1.1     lukem 	case CFG_TLS_CA_PATH:	flag = LDAP_OPT_X_TLS_CACERTDIR;	break;
   4115  1.1     lukem 	case CFG_TLS_CA_FILE:	flag = LDAP_OPT_X_TLS_CACERTFILE;	break;
   4116  1.1     lukem 	case CFG_TLS_DH_FILE:	flag = LDAP_OPT_X_TLS_DHFILE;	break;
   4117  1.2  christos 	case CFG_TLS_ECNAME:	flag = LDAP_OPT_X_TLS_ECNAME;	break;
   4118  1.1     lukem #ifdef HAVE_GNUTLS
   4119  1.1     lukem 	case CFG_TLS_CRL_FILE:	flag = LDAP_OPT_X_TLS_CRLFILE;	break;
   4120  1.1     lukem #endif
   4121  1.3  christos 	case CFG_TLS_CACERT:	flag = LDAP_OPT_X_TLS_CACERT;	berval = 1;	break;
   4122  1.3  christos 	case CFG_TLS_CERT:		flag = LDAP_OPT_X_TLS_CERT;	berval = 1;	break;
   4123  1.3  christos 	case CFG_TLS_KEY:		flag = LDAP_OPT_X_TLS_KEY;	berval = 1;	break;
   4124  1.1     lukem 	default:		Debug(LDAP_DEBUG_ANY, "%s: "
   4125  1.1     lukem 					"unknown tls_option <0x%x>\n",
   4126  1.3  christos 					c->log, c->type );
   4127  1.1     lukem 		return 1;
   4128  1.1     lukem 	}
   4129  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   4130  1.3  christos 		return ldap_pvt_tls_get_option( ld, flag, berval ? (void *)&c->value_bv : (void *)&c->value_string );
   4131  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   4132  1.3  christos 		config_push_cleanup( c, config_tls_cleanup );
   4133  1.1     lukem 		return ldap_pvt_tls_set_option( ld, flag, NULL );
   4134  1.1     lukem 	}
   4135  1.3  christos 	if ( !berval ) ch_free(c->value_string);
   4136  1.3  christos 	config_push_cleanup( c, config_tls_cleanup );
   4137  1.3  christos 	rc = ldap_pvt_tls_set_option(ld, flag, berval ? (void *)&c->value_bv : (void *)c->argv[1]);
   4138  1.3  christos 	if ( berval ) ch_free(c->value_bv.bv_val);
   4139  1.3  christos 	return rc;
   4140  1.1     lukem }
   4141  1.1     lukem 
   4142  1.1     lukem /* FIXME: this ought to be provided by libldap */
   4143  1.1     lukem static int
   4144  1.1     lukem config_tls_config(ConfigArgs *c) {
   4145  1.1     lukem 	int i, flag;
   4146  1.1     lukem 	switch(c->type) {
   4147  1.1     lukem 	case CFG_TLS_CRLCHECK:	flag = LDAP_OPT_X_TLS_CRLCHECK; break;
   4148  1.1     lukem 	case CFG_TLS_VERIFY:	flag = LDAP_OPT_X_TLS_REQUIRE_CERT; break;
   4149  1.2  christos 	case CFG_TLS_PROTOCOL_MIN: flag = LDAP_OPT_X_TLS_PROTOCOL_MIN; break;
   4150  1.1     lukem 	default:
   4151  1.1     lukem 		Debug(LDAP_DEBUG_ANY, "%s: "
   4152  1.1     lukem 				"unknown tls_option <0x%x>\n",
   4153  1.3  christos 				c->log, c->type );
   4154  1.1     lukem 		return 1;
   4155  1.1     lukem 	}
   4156  1.1     lukem 	if (c->op == SLAP_CONFIG_EMIT) {
   4157  1.1     lukem 		return slap_tls_get_config( slap_tls_ld, flag, &c->value_string );
   4158  1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   4159  1.1     lukem 		int i = 0;
   4160  1.3  christos 		config_push_cleanup( c, config_tls_cleanup );
   4161  1.1     lukem 		return ldap_pvt_tls_set_option( slap_tls_ld, flag, &i );
   4162  1.1     lukem 	}
   4163  1.1     lukem 	ch_free( c->value_string );
   4164  1.3  christos 	config_push_cleanup( c, config_tls_cleanup );
   4165  1.2  christos 	if ( isdigit( (unsigned char)c->argv[1][0] ) && c->type != CFG_TLS_PROTOCOL_MIN ) {
   4166  1.1     lukem 		if ( lutil_atoi( &i, c->argv[1] ) != 0 ) {
   4167  1.1     lukem 			Debug(LDAP_DEBUG_ANY, "%s: "
   4168  1.1     lukem 				"unable to parse %s \"%s\"\n",
   4169  1.1     lukem 				c->log, c->argv[0], c->argv[1] );
   4170  1.1     lukem 			return 1;
   4171  1.1     lukem 		}
   4172  1.1     lukem 		return(ldap_pvt_tls_set_option(slap_tls_ld, flag, &i));
   4173  1.1     lukem 	} else {
   4174  1.3  christos 		return(ldap_pvt_tls_config(slap_tls_ld, flag, c->argv[1]));
   4175  1.1     lukem 	}
   4176  1.1     lukem }
   4177  1.1     lukem #endif
   4178  1.1     lukem 
   4179  1.1     lukem static CfEntryInfo *
   4180  1.4  christos config_find_base( CfEntryInfo *root, struct berval *dn, CfEntryInfo **last,
   4181  1.4  christos 	Operation *op )
   4182  1.1     lukem {
   4183  1.1     lukem 	struct berval cdn;
   4184  1.1     lukem 	char *c;
   4185  1.1     lukem 
   4186  1.1     lukem 	if ( !root ) {
   4187  1.1     lukem 		*last = NULL;
   4188  1.1     lukem 		return NULL;
   4189  1.1     lukem 	}
   4190  1.1     lukem 
   4191  1.1     lukem 	if ( dn_match( &root->ce_entry->e_nname, dn ))
   4192  1.1     lukem 		return root;
   4193  1.1     lukem 
   4194  1.1     lukem 	c = dn->bv_val+dn->bv_len;
   4195  1.1     lukem 	for (;*c != ',';c--);
   4196  1.1     lukem 
   4197  1.1     lukem 	while(root) {
   4198  1.4  christos 		if ( !op || access_allowed( op, root->ce_entry,
   4199  1.4  christos 					slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) {
   4200  1.4  christos 			/*
   4201  1.4  christos 			 * ITS#10139: Only record the lowermost entry that the user has
   4202  1.4  christos 			 * disclose access to
   4203  1.4  christos 			 */
   4204  1.4  christos 			*last = root;
   4205  1.4  christos 		}
   4206  1.1     lukem 		for (--c;c>dn->bv_val && *c != ',';c--);
   4207  1.1     lukem 		cdn.bv_val = c;
   4208  1.1     lukem 		if ( *c == ',' )
   4209  1.1     lukem 			cdn.bv_val++;
   4210  1.1     lukem 		cdn.bv_len = dn->bv_len - (cdn.bv_val - dn->bv_val);
   4211  1.1     lukem 
   4212  1.1     lukem 		root = root->ce_kids;
   4213  1.1     lukem 
   4214  1.1     lukem 		for (;root;root=root->ce_sibs) {
   4215  1.1     lukem 			if ( dn_match( &root->ce_entry->e_nname, &cdn )) {
   4216  1.1     lukem 				if ( cdn.bv_val == dn->bv_val ) {
   4217  1.1     lukem 					return root;
   4218  1.1     lukem 				}
   4219  1.1     lukem 				break;
   4220  1.1     lukem 			}
   4221  1.1     lukem 		}
   4222  1.1     lukem 	}
   4223  1.1     lukem 	return root;
   4224  1.1     lukem }
   4225  1.1     lukem 
   4226  1.1     lukem typedef struct setup_cookie {
   4227  1.1     lukem 	CfBackInfo *cfb;
   4228  1.1     lukem 	ConfigArgs *ca;
   4229  1.1     lukem 	Entry *frontend;
   4230  1.1     lukem 	Entry *config;
   4231  1.2  christos 	int got_frontend;
   4232  1.1     lukem 	int got_config;
   4233  1.1     lukem } setup_cookie;
   4234  1.1     lukem 
   4235  1.1     lukem static int
   4236  1.1     lukem config_ldif_resp( Operation *op, SlapReply *rs )
   4237  1.1     lukem {
   4238  1.1     lukem 	if ( rs->sr_type == REP_SEARCH ) {
   4239  1.1     lukem 		setup_cookie *sc = op->o_callback->sc_private;
   4240  1.2  christos 		struct berval pdn;
   4241  1.1     lukem 
   4242  1.1     lukem 		sc->cfb->cb_got_ldif = 1;
   4243  1.1     lukem 		/* Does the frontend exist? */
   4244  1.1     lukem 		if ( !sc->got_frontend ) {
   4245  1.1     lukem 			if ( !strncmp( rs->sr_entry->e_nname.bv_val,
   4246  1.2  christos 				"olcDatabase", STRLENOF( "olcDatabase" )))
   4247  1.2  christos 			{
   4248  1.1     lukem 				if ( strncmp( rs->sr_entry->e_nname.bv_val +
   4249  1.1     lukem 					STRLENOF( "olcDatabase" ), "={-1}frontend",
   4250  1.2  christos 					STRLENOF( "={-1}frontend" )))
   4251  1.2  christos 				{
   4252  1.1     lukem 					struct berval rdn;
   4253  1.1     lukem 					int i = op->o_noop;
   4254  1.1     lukem 					sc->ca->be = frontendDB;
   4255  1.1     lukem 					sc->ca->bi = frontendDB->bd_info;
   4256  1.1     lukem 					frontendDB->be_cf_ocs = &CFOC_FRONTEND;
   4257  1.1     lukem 					rdn.bv_val = sc->ca->log;
   4258  1.1     lukem 					rdn.bv_len = snprintf(rdn.bv_val, sizeof( sc->ca->log ),
   4259  1.1     lukem 						"%s=" SLAP_X_ORDERED_FMT "%s",
   4260  1.1     lukem 						cfAd_database->ad_cname.bv_val, -1,
   4261  1.1     lukem 						sc->ca->bi->bi_type);
   4262  1.1     lukem 					op->o_noop = 1;
   4263  1.1     lukem 					sc->frontend = config_build_entry( op, rs,
   4264  1.1     lukem 						sc->cfb->cb_root, sc->ca, &rdn, &CFOC_DATABASE,
   4265  1.1     lukem 						sc->ca->be->be_cf_ocs );
   4266  1.1     lukem 					op->o_noop = i;
   4267  1.1     lukem 					sc->got_frontend++;
   4268  1.1     lukem 				} else {
   4269  1.1     lukem 					sc->got_frontend++;
   4270  1.1     lukem 					goto ok;
   4271  1.1     lukem 				}
   4272  1.1     lukem 			}
   4273  1.1     lukem 		}
   4274  1.2  christos 
   4275  1.2  christos 		dnParent( &rs->sr_entry->e_nname, &pdn );
   4276  1.2  christos 
   4277  1.1     lukem 		/* Does the configDB exist? */
   4278  1.1     lukem 		if ( sc->got_frontend && !sc->got_config &&
   4279  1.1     lukem 			!strncmp( rs->sr_entry->e_nname.bv_val,
   4280  1.2  christos 			"olcDatabase", STRLENOF( "olcDatabase" )) &&
   4281  1.2  christos 			dn_match( &config_rdn, &pdn ) )
   4282  1.2  christos 		{
   4283  1.1     lukem 			if ( strncmp( rs->sr_entry->e_nname.bv_val +
   4284  1.1     lukem 				STRLENOF( "olcDatabase" ), "={0}config",
   4285  1.2  christos 				STRLENOF( "={0}config" )))
   4286  1.2  christos 			{
   4287  1.1     lukem 				struct berval rdn;
   4288  1.1     lukem 				int i = op->o_noop;
   4289  1.1     lukem 				sc->ca->be = LDAP_STAILQ_FIRST( &backendDB );
   4290  1.1     lukem 				sc->ca->bi = sc->ca->be->bd_info;
   4291  1.1     lukem 				rdn.bv_val = sc->ca->log;
   4292  1.1     lukem 				rdn.bv_len = snprintf(rdn.bv_val, sizeof( sc->ca->log ),
   4293  1.1     lukem 					"%s=" SLAP_X_ORDERED_FMT "%s",
   4294  1.1     lukem 					cfAd_database->ad_cname.bv_val, 0,
   4295  1.1     lukem 					sc->ca->bi->bi_type);
   4296  1.1     lukem 				op->o_noop = 1;
   4297  1.1     lukem 				sc->config = config_build_entry( op, rs, sc->cfb->cb_root,
   4298  1.1     lukem 					sc->ca, &rdn, &CFOC_DATABASE, sc->ca->be->be_cf_ocs );
   4299  1.1     lukem 				op->o_noop = i;
   4300  1.1     lukem 			}
   4301  1.1     lukem 			sc->got_config++;
   4302  1.1     lukem 		}
   4303  1.1     lukem 
   4304  1.1     lukem ok:
   4305  1.1     lukem 		rs->sr_err = config_add_internal( sc->cfb, rs->sr_entry, sc->ca, NULL, NULL, NULL );
   4306  1.1     lukem 		if ( rs->sr_err != LDAP_SUCCESS ) {
   4307  1.1     lukem 			Debug( LDAP_DEBUG_ANY, "config error processing %s: %s\n",
   4308  1.3  christos 				rs->sr_entry->e_name.bv_val, sc->ca->cr_msg );
   4309  1.1     lukem 		}
   4310  1.1     lukem 	}
   4311  1.1     lukem 	return rs->sr_err;
   4312  1.1     lukem }
   4313  1.1     lukem 
   4314  1.1     lukem /* Configure and read the underlying back-ldif store */
   4315  1.1     lukem static int
   4316  1.1     lukem config_setup_ldif( BackendDB *be, const char *dir, int readit ) {
   4317  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   4318  1.1     lukem 	ConfigArgs c = {0};
   4319  1.1     lukem 	ConfigTable *ct;
   4320  1.1     lukem 	char *argv[3];
   4321  1.1     lukem 	int rc = 0;
   4322  1.1     lukem 	setup_cookie sc;
   4323  1.1     lukem 	slap_callback cb = { NULL, config_ldif_resp, NULL, NULL };
   4324  1.1     lukem 	Connection conn = {0};
   4325  1.1     lukem 	OperationBuffer opbuf;
   4326  1.1     lukem 	Operation *op;
   4327  1.1     lukem 	SlapReply rs = {REP_RESULT};
   4328  1.1     lukem 	Filter filter = { LDAP_FILTER_PRESENT };
   4329  1.1     lukem 	struct berval filterstr = BER_BVC("(objectclass=*)");
   4330  1.1     lukem 	struct stat st;
   4331  1.1     lukem 
   4332  1.1     lukem 	/* Is the config directory available? */
   4333  1.1     lukem 	if ( stat( dir, &st ) < 0 ) {
   4334  1.1     lukem 		/* No, so don't bother using the backing store.
   4335  1.1     lukem 		 * All changes will be in-memory only.
   4336  1.1     lukem 		 */
   4337  1.1     lukem 		return 0;
   4338  1.1     lukem 	}
   4339  1.1     lukem 
   4340  1.1     lukem 	cfb->cb_db.bd_info = backend_info( "ldif" );
   4341  1.1     lukem 	if ( !cfb->cb_db.bd_info )
   4342  1.1     lukem 		return 0;	/* FIXME: eventually this will be a fatal error */
   4343  1.1     lukem 
   4344  1.1     lukem 	if ( backend_db_init( "ldif", &cfb->cb_db, -1, NULL ) == NULL )
   4345  1.1     lukem 		return 1;
   4346  1.1     lukem 
   4347  1.1     lukem 	cfb->cb_db.be_suffix = be->be_suffix;
   4348  1.1     lukem 	cfb->cb_db.be_nsuffix = be->be_nsuffix;
   4349  1.1     lukem 
   4350  1.1     lukem 	/* The suffix is always "cn=config". The underlying DB's rootdn
   4351  1.1     lukem 	 * is always the same as the suffix.
   4352  1.1     lukem 	 */
   4353  1.1     lukem 	cfb->cb_db.be_rootdn = be->be_suffix[0];
   4354  1.1     lukem 	cfb->cb_db.be_rootndn = be->be_nsuffix[0];
   4355  1.1     lukem 
   4356  1.1     lukem 	ber_str2bv( dir, 0, 1, &cfdir );
   4357  1.1     lukem 
   4358  1.1     lukem 	c.be = &cfb->cb_db;
   4359  1.1     lukem 	c.fname = "slapd";
   4360  1.1     lukem 	c.argc = 2;
   4361  1.1     lukem 	argv[0] = "directory";
   4362  1.1     lukem 	argv[1] = (char *)dir;
   4363  1.1     lukem 	argv[2] = NULL;
   4364  1.1     lukem 	c.argv = argv;
   4365  1.1     lukem 	c.reply.err = 0;
   4366  1.1     lukem 	c.reply.msg[0] = 0;
   4367  1.1     lukem 	c.table = Cft_Database;
   4368  1.1     lukem 
   4369  1.1     lukem 	ct = config_find_keyword( c.be->be_cf_ocs->co_table, &c );
   4370  1.1     lukem 	if ( !ct )
   4371  1.1     lukem 		return 1;
   4372  1.1     lukem 
   4373  1.1     lukem 	if ( config_add_vals( ct, &c ))
   4374  1.1     lukem 		return 1;
   4375  1.1     lukem 
   4376  1.1     lukem 	if ( backend_startup_one( &cfb->cb_db, &c.reply ))
   4377  1.1     lukem 		return 1;
   4378  1.1     lukem 
   4379  1.1     lukem 	if ( readit ) {
   4380  1.1     lukem 		void *thrctx = ldap_pvt_thread_pool_context();
   4381  1.1     lukem 		int prev_DN_strict;
   4382  1.1     lukem 
   4383  1.1     lukem 		connection_fake_init( &conn, &opbuf, thrctx );
   4384  1.1     lukem 		op = &opbuf.ob_op;
   4385  1.1     lukem 
   4386  1.1     lukem 		filter.f_desc = slap_schema.si_ad_objectClass;
   4387  1.1     lukem 
   4388  1.1     lukem 		op->o_tag = LDAP_REQ_SEARCH;
   4389  1.1     lukem 
   4390  1.1     lukem 		op->ors_filter = &filter;
   4391  1.1     lukem 		op->ors_filterstr = filterstr;
   4392  1.1     lukem 		op->ors_scope = LDAP_SCOPE_SUBTREE;
   4393  1.1     lukem 
   4394  1.1     lukem 		op->o_dn = c.be->be_rootdn;
   4395  1.1     lukem 		op->o_ndn = c.be->be_rootndn;
   4396  1.1     lukem 
   4397  1.1     lukem 		op->o_req_dn = be->be_suffix[0];
   4398  1.1     lukem 		op->o_req_ndn = be->be_nsuffix[0];
   4399  1.1     lukem 
   4400  1.1     lukem 		op->ors_tlimit = SLAP_NO_LIMIT;
   4401  1.1     lukem 		op->ors_slimit = SLAP_NO_LIMIT;
   4402  1.1     lukem 
   4403  1.1     lukem 		op->ors_attrs = slap_anlist_all_attributes;
   4404  1.1     lukem 		op->ors_attrsonly = 0;
   4405  1.1     lukem 
   4406  1.1     lukem 		op->o_callback = &cb;
   4407  1.1     lukem 		sc.cfb = cfb;
   4408  1.1     lukem 		sc.ca = &c;
   4409  1.1     lukem 		cb.sc_private = &sc;
   4410  1.1     lukem 		sc.got_frontend = 0;
   4411  1.1     lukem 		sc.got_config = 0;
   4412  1.1     lukem 		sc.frontend = NULL;
   4413  1.1     lukem 		sc.config = NULL;
   4414  1.1     lukem 
   4415  1.1     lukem 		op->o_bd = &cfb->cb_db;
   4416  1.1     lukem 
   4417  1.1     lukem 		/* Allow unknown attrs in DNs */
   4418  1.1     lukem 		prev_DN_strict = slap_DN_strict;
   4419  1.1     lukem 		slap_DN_strict = 0;
   4420  1.1     lukem 
   4421  1.1     lukem 		rc = op->o_bd->be_search( op, &rs );
   4422  1.1     lukem 
   4423  1.1     lukem 		/* Restore normal DN validation */
   4424  1.1     lukem 		slap_DN_strict = prev_DN_strict;
   4425  1.1     lukem 
   4426  1.1     lukem 		op->o_tag = LDAP_REQ_ADD;
   4427  1.1     lukem 		if ( rc == LDAP_SUCCESS && sc.frontend ) {
   4428  1.2  christos 			rs_reinit( &rs, REP_RESULT );
   4429  1.1     lukem 			op->ora_e = sc.frontend;
   4430  1.1     lukem 			rc = op->o_bd->be_add( op, &rs );
   4431  1.1     lukem 		}
   4432  1.1     lukem 		if ( rc == LDAP_SUCCESS && sc.config ) {
   4433  1.2  christos 			rs_reinit( &rs, REP_RESULT );
   4434  1.1     lukem 			op->ora_e = sc.config;
   4435  1.1     lukem 			rc = op->o_bd->be_add( op, &rs );
   4436  1.1     lukem 		}
   4437  1.1     lukem 		ldap_pvt_thread_pool_context_reset( thrctx );
   4438  1.3  christos 	} else {
   4439  1.3  christos 		/* ITS#9016 Check directory is empty (except perhaps hidden files) */
   4440  1.3  christos 		DIR *dir_of_path;
   4441  1.3  christos 		struct dirent *entry;
   4442  1.3  christos 
   4443  1.3  christos 		dir_of_path = opendir( dir );
   4444  1.3  christos 		while ( (entry = readdir( dir_of_path )) != NULL ) {
   4445  1.3  christos 			if ( entry->d_name[0] != '.' ) {
   4446  1.3  christos 				Debug( LDAP_DEBUG_ANY, "config_setup_ldif: "
   4447  1.3  christos 						"expected directory %s to be empty!\n",
   4448  1.3  christos 						dir );
   4449  1.3  christos 				rc = LDAP_ALREADY_EXISTS;
   4450  1.3  christos 				break;
   4451  1.3  christos 			}
   4452  1.3  christos 		}
   4453  1.3  christos 		closedir( dir_of_path );
   4454  1.1     lukem 	}
   4455  1.1     lukem 
   4456  1.1     lukem 	/* ITS#4194 - only use if it's present, or we're converting. */
   4457  1.1     lukem 	if ( !readit || rc == LDAP_SUCCESS )
   4458  1.1     lukem 		cfb->cb_use_ldif = 1;
   4459  1.1     lukem 
   4460  1.1     lukem 	return rc;
   4461  1.1     lukem }
   4462  1.1     lukem 
   4463  1.1     lukem static int
   4464  1.1     lukem CfOc_cmp( const void *c1, const void *c2 ) {
   4465  1.1     lukem 	const ConfigOCs *co1 = c1;
   4466  1.1     lukem 	const ConfigOCs *co2 = c2;
   4467  1.1     lukem 
   4468  1.1     lukem 	return ber_bvcmp( co1->co_name, co2->co_name );
   4469  1.1     lukem }
   4470  1.1     lukem 
   4471  1.1     lukem int
   4472  1.1     lukem config_register_schema(ConfigTable *ct, ConfigOCs *ocs) {
   4473  1.1     lukem 	int i;
   4474  1.1     lukem 
   4475  1.1     lukem 	i = init_config_attrs( ct );
   4476  1.1     lukem 	if ( i ) return i;
   4477  1.1     lukem 
   4478  1.1     lukem 	/* set up the objectclasses */
   4479  1.1     lukem 	i = init_config_ocs( ocs );
   4480  1.1     lukem 	if ( i ) return i;
   4481  1.1     lukem 
   4482  1.1     lukem 	for (i=0; ocs[i].co_def; i++) {
   4483  1.1     lukem 		if ( ocs[i].co_oc ) {
   4484  1.1     lukem 			ocs[i].co_name = &ocs[i].co_oc->soc_cname;
   4485  1.1     lukem 			if ( !ocs[i].co_table )
   4486  1.1     lukem 				ocs[i].co_table = ct;
   4487  1.3  christos 			ldap_avl_insert( &CfOcTree, &ocs[i], CfOc_cmp, ldap_avl_dup_error );
   4488  1.1     lukem 		}
   4489  1.1     lukem 	}
   4490  1.1     lukem 	return 0;
   4491  1.1     lukem }
   4492  1.1     lukem 
   4493  1.1     lukem int
   4494  1.1     lukem read_config(const char *fname, const char *dir) {
   4495  1.1     lukem 	BackendDB *be;
   4496  1.1     lukem 	CfBackInfo *cfb;
   4497  1.1     lukem 	const char *cfdir, *cfname;
   4498  1.1     lukem 	int rc;
   4499  1.1     lukem 
   4500  1.1     lukem 	/* Setup the config backend */
   4501  1.1     lukem 	be = backend_db_init( "config", NULL, 0, NULL );
   4502  1.1     lukem 	if ( !be )
   4503  1.1     lukem 		return 1;
   4504  1.1     lukem 
   4505  1.1     lukem 	cfb = be->be_private;
   4506  1.1     lukem 	be->be_dfltaccess = ACL_NONE;
   4507  1.1     lukem 
   4508  1.1     lukem 	/* If no .conf, or a dir was specified, setup the dir */
   4509  1.1     lukem 	if ( !fname || dir ) {
   4510  1.1     lukem 		if ( dir ) {
   4511  1.1     lukem 			/* If explicitly given, check for existence */
   4512  1.1     lukem 			struct stat st;
   4513  1.1     lukem 
   4514  1.1     lukem 			if ( stat( dir, &st ) < 0 ) {
   4515  1.3  christos 				int saved_errno = errno;
   4516  1.1     lukem 				Debug( LDAP_DEBUG_ANY,
   4517  1.1     lukem 					"invalid config directory %s, error %d\n",
   4518  1.3  christos 						dir, saved_errno );
   4519  1.1     lukem 				return 1;
   4520  1.1     lukem 			}
   4521  1.1     lukem 			cfdir = dir;
   4522  1.1     lukem 		} else {
   4523  1.1     lukem 			cfdir = SLAPD_DEFAULT_CONFIGDIR;
   4524  1.1     lukem 		}
   4525  1.1     lukem 		/* if fname is defaulted, try reading .d */
   4526  1.1     lukem 		rc = config_setup_ldif( be, cfdir, !fname );
   4527  1.1     lukem 
   4528  1.1     lukem 		if ( rc ) {
   4529  1.1     lukem 			/* It may be OK if the base object doesn't exist yet. */
   4530  1.1     lukem 			if ( rc != LDAP_NO_SUCH_OBJECT )
   4531  1.1     lukem 				return 1;
   4532  1.1     lukem 			/* ITS#4194: But if dir was specified and no fname,
   4533  1.1     lukem 			 * then we were supposed to read the dir. Unless we're
   4534  1.1     lukem 			 * trying to slapadd the dir...
   4535  1.1     lukem 			 */
   4536  1.1     lukem 			if ( dir && !fname ) {
   4537  1.1     lukem 				if ( slapMode & (SLAP_SERVER_MODE|SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY))
   4538  1.1     lukem 					return 1;
   4539  1.1     lukem 				/* Assume it's slapadd with a config dir, let it continue */
   4540  1.1     lukem 				rc = 0;
   4541  1.1     lukem 				cfb->cb_got_ldif = 1;
   4542  1.1     lukem 				cfb->cb_use_ldif = 1;
   4543  1.1     lukem 				goto done;
   4544  1.1     lukem 			}
   4545  1.1     lukem 		}
   4546  1.1     lukem 
   4547  1.1     lukem 		/* If we read the config from back-ldif, nothing to do here */
   4548  1.1     lukem 		if ( cfb->cb_got_ldif ) {
   4549  1.1     lukem 			rc = 0;
   4550  1.1     lukem 			goto done;
   4551  1.1     lukem 		}
   4552  1.1     lukem 	}
   4553  1.1     lukem 
   4554  1.1     lukem 	if ( fname )
   4555  1.1     lukem 		cfname = fname;
   4556  1.1     lukem 	else
   4557  1.1     lukem 		cfname = SLAPD_DEFAULT_CONFIGFILE;
   4558  1.1     lukem 
   4559  1.1     lukem 	rc = read_config_file(cfname, 0, NULL, config_back_cf_table);
   4560  1.1     lukem 
   4561  1.1     lukem 	if ( rc == 0 )
   4562  1.1     lukem 		ber_str2bv( cfname, 0, 1, &cfb->cb_config->c_file );
   4563  1.1     lukem 
   4564  1.1     lukem done:
   4565  1.1     lukem 	if ( rc == 0 && BER_BVISNULL( &frontendDB->be_schemadn ) ) {
   4566  1.1     lukem 		ber_str2bv( SLAPD_SCHEMA_DN, STRLENOF( SLAPD_SCHEMA_DN ), 1,
   4567  1.1     lukem 			&frontendDB->be_schemadn );
   4568  1.1     lukem 		rc = dnNormalize( 0, NULL, NULL, &frontendDB->be_schemadn, &frontendDB->be_schemandn, NULL );
   4569  1.1     lukem 		if ( rc != LDAP_SUCCESS ) {
   4570  1.1     lukem 			Debug(LDAP_DEBUG_ANY, "read_config: "
   4571  1.1     lukem 				"unable to normalize default schema DN \"%s\"\n",
   4572  1.3  christos 				frontendDB->be_schemadn.bv_val );
   4573  1.1     lukem 			/* must not happen */
   4574  1.1     lukem 			assert( 0 );
   4575  1.1     lukem 		}
   4576  1.1     lukem 	}
   4577  1.2  christos 	if ( rc == 0 && ( slapMode & SLAP_SERVER_MODE ) && sid_list ) {
   4578  1.2  christos 		if ( !BER_BVISEMPTY( &sid_list->si_url ) && !sid_set ) {
   4579  1.2  christos 			Debug(LDAP_DEBUG_ANY, "read_config: no serverID / URL match found. "
   4580  1.3  christos 				"Check slapd -h arguments.\n" );
   4581  1.2  christos 			rc = LDAP_OTHER;
   4582  1.2  christos 		}
   4583  1.2  christos 	}
   4584  1.1     lukem 	return rc;
   4585  1.1     lukem }
   4586  1.1     lukem 
   4587  1.1     lukem static int
   4588  1.1     lukem config_back_bind( Operation *op, SlapReply *rs )
   4589  1.1     lukem {
   4590  1.1     lukem 	if ( be_isroot_pw( op ) ) {
   4591  1.1     lukem 		ber_dupbv( &op->orb_edn, be_root_dn( op->o_bd ));
   4592  1.1     lukem 		/* frontend sends result */
   4593  1.1     lukem 		return LDAP_SUCCESS;
   4594  1.1     lukem 	}
   4595  1.1     lukem 
   4596  1.1     lukem 	rs->sr_err = LDAP_INVALID_CREDENTIALS;
   4597  1.1     lukem 	send_ldap_result( op, rs );
   4598  1.1     lukem 
   4599  1.1     lukem 	return rs->sr_err;
   4600  1.1     lukem }
   4601  1.1     lukem 
   4602  1.1     lukem static int
   4603  1.1     lukem config_send( Operation *op, SlapReply *rs, CfEntryInfo *ce, int depth )
   4604  1.1     lukem {
   4605  1.1     lukem 	int rc = 0;
   4606  1.1     lukem 
   4607  1.1     lukem 	if ( test_filter( op, ce->ce_entry, op->ors_filter ) == LDAP_COMPARE_TRUE )
   4608  1.1     lukem 	{
   4609  1.1     lukem 		rs->sr_attrs = op->ors_attrs;
   4610  1.1     lukem 		rs->sr_entry = ce->ce_entry;
   4611  1.1     lukem 		rs->sr_flags = 0;
   4612  1.1     lukem 		rc = send_search_entry( op, rs );
   4613  1.2  christos 		if ( rc != LDAP_SUCCESS ) {
   4614  1.2  christos 			return rc;
   4615  1.2  christos 		}
   4616  1.1     lukem 	}
   4617  1.1     lukem 	if ( op->ors_scope == LDAP_SCOPE_SUBTREE ) {
   4618  1.1     lukem 		if ( ce->ce_kids ) {
   4619  1.1     lukem 			rc = config_send( op, rs, ce->ce_kids, 1 );
   4620  1.1     lukem 			if ( rc ) return rc;
   4621  1.1     lukem 		}
   4622  1.1     lukem 		if ( depth ) {
   4623  1.1     lukem 			for (ce=ce->ce_sibs; ce; ce=ce->ce_sibs) {
   4624  1.1     lukem 				rc = config_send( op, rs, ce, 0 );
   4625  1.1     lukem 				if ( rc ) break;
   4626  1.1     lukem 			}
   4627  1.1     lukem 		}
   4628  1.1     lukem 	}
   4629  1.1     lukem 	return rc;
   4630  1.1     lukem }
   4631  1.1     lukem 
   4632  1.1     lukem static ConfigTable *
   4633  1.1     lukem config_find_table( ConfigOCs **colst, int nocs, AttributeDescription *ad,
   4634  1.1     lukem 	ConfigArgs *ca )
   4635  1.1     lukem {
   4636  1.1     lukem 	int i, j;
   4637  1.3  christos 	if (ad->ad_flags & SLAP_DESC_BINARY)
   4638  1.3  christos 		ad = ad->ad_type->sat_ad;
   4639  1.1     lukem 
   4640  1.1     lukem 	for (j=0; j<nocs; j++) {
   4641  1.1     lukem 		for (i=0; colst[j]->co_table[i].name; i++)
   4642  1.1     lukem 			if ( colst[j]->co_table[i].ad == ad ) {
   4643  1.1     lukem 				ca->table = colst[j]->co_type;
   4644  1.4  christos 				ca->ca_desc = colst[j]->co_table+i;
   4645  1.1     lukem 				return &colst[j]->co_table[i];
   4646  1.1     lukem 			}
   4647  1.1     lukem 	}
   4648  1.1     lukem 	return NULL;
   4649  1.1     lukem }
   4650  1.1     lukem 
   4651  1.1     lukem /* Sort the attributes of the entry according to the order defined
   4652  1.1     lukem  * in the objectclass, with required attributes occurring before
   4653  1.1     lukem  * allowed attributes. For any attributes with sequencing dependencies
   4654  1.1     lukem  * (e.g., rootDN must be defined after suffix) the objectclass must
   4655  1.1     lukem  * list the attributes in the desired sequence.
   4656  1.1     lukem  */
   4657  1.1     lukem static void
   4658  1.1     lukem sort_attrs( Entry *e, ConfigOCs **colst, int nocs )
   4659  1.1     lukem {
   4660  1.1     lukem 	Attribute *a, *head = NULL, *tail = NULL, **prev;
   4661  1.1     lukem 	int i, j;
   4662  1.1     lukem 
   4663  1.1     lukem 	for (i=0; i<nocs; i++) {
   4664  1.1     lukem 		if ( colst[i]->co_oc->soc_required ) {
   4665  1.1     lukem 			AttributeType **at = colst[i]->co_oc->soc_required;
   4666  1.1     lukem 			for (j=0; at[j]; j++) {
   4667  1.1     lukem 				for (a=e->e_attrs, prev=&e->e_attrs; a;
   4668  1.1     lukem 					prev = &(*prev)->a_next, a=a->a_next) {
   4669  1.1     lukem 					if ( a->a_desc == at[j]->sat_ad ) {
   4670  1.1     lukem 						*prev = a->a_next;
   4671  1.1     lukem 						if (!head) {
   4672  1.1     lukem 							head = a;
   4673  1.1     lukem 							tail = a;
   4674  1.1     lukem 						} else {
   4675  1.1     lukem 							tail->a_next = a;
   4676  1.1     lukem 							tail = a;
   4677  1.1     lukem 						}
   4678  1.1     lukem 						break;
   4679  1.1     lukem 					}
   4680  1.1     lukem 				}
   4681  1.1     lukem 			}
   4682  1.1     lukem 		}
   4683  1.1     lukem 		if ( colst[i]->co_oc->soc_allowed ) {
   4684  1.1     lukem 			AttributeType **at = colst[i]->co_oc->soc_allowed;
   4685  1.1     lukem 			for (j=0; at[j]; j++) {
   4686  1.1     lukem 				for (a=e->e_attrs, prev=&e->e_attrs; a;
   4687  1.1     lukem 					prev = &(*prev)->a_next, a=a->a_next) {
   4688  1.1     lukem 					if ( a->a_desc == at[j]->sat_ad ) {
   4689  1.1     lukem 						*prev = a->a_next;
   4690  1.1     lukem 						if (!head) {
   4691  1.1     lukem 							head = a;
   4692  1.1     lukem 							tail = a;
   4693  1.1     lukem 						} else {
   4694  1.1     lukem 							tail->a_next = a;
   4695  1.1     lukem 							tail = a;
   4696  1.1     lukem 						}
   4697  1.1     lukem 						break;
   4698  1.1     lukem 					}
   4699  1.1     lukem 				}
   4700  1.1     lukem 			}
   4701  1.1     lukem 		}
   4702  1.1     lukem 	}
   4703  1.1     lukem 	if ( tail ) {
   4704  1.1     lukem 		tail->a_next = e->e_attrs;
   4705  1.1     lukem 		e->e_attrs = head;
   4706  1.1     lukem 	}
   4707  1.1     lukem }
   4708  1.1     lukem 
   4709  1.1     lukem static int
   4710  1.1     lukem check_vals( ConfigTable *ct, ConfigArgs *ca, void *ptr, int isAttr )
   4711  1.1     lukem {
   4712  1.1     lukem 	Attribute *a = NULL;
   4713  1.1     lukem 	AttributeDescription *ad;
   4714  1.1     lukem 	BerVarray vals;
   4715  1.1     lukem 
   4716  1.1     lukem 	int i, rc = 0;
   4717  1.1     lukem 
   4718  1.1     lukem 	if ( isAttr ) {
   4719  1.1     lukem 		a = ptr;
   4720  1.1     lukem 		ad = a->a_desc;
   4721  1.1     lukem 		vals = a->a_vals;
   4722  1.1     lukem 	} else {
   4723  1.1     lukem 		Modifications *ml = ptr;
   4724  1.1     lukem 		ad = ml->sml_desc;
   4725  1.1     lukem 		vals = ml->sml_values;
   4726  1.1     lukem 	}
   4727  1.1     lukem 
   4728  1.1     lukem 	if ( a && ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL )) {
   4729  1.1     lukem 		rc = ordered_value_sort( a, 1 );
   4730  1.1     lukem 		if ( rc ) {
   4731  1.1     lukem 			snprintf(ca->cr_msg, sizeof( ca->cr_msg ), "ordered_value_sort failed on attr %s\n",
   4732  1.1     lukem 				ad->ad_cname.bv_val );
   4733  1.1     lukem 			return rc;
   4734  1.1     lukem 		}
   4735  1.1     lukem 	}
   4736  1.1     lukem 	for ( i=0; vals[i].bv_val; i++ ) {
   4737  1.1     lukem 		ca->line = vals[i].bv_val;
   4738  1.3  christos 		ca->linelen = vals[i].bv_len;
   4739  1.1     lukem 		if (( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) &&
   4740  1.1     lukem 			ca->line[0] == '{' ) {
   4741  1.1     lukem 			char *idx = strchr( ca->line, '}' );
   4742  1.3  christos 			if ( idx ) {
   4743  1.3  christos 				ca->linelen -= (idx+1) - ca->line;
   4744  1.3  christos 				ca->line = idx+1;
   4745  1.3  christos 			}
   4746  1.1     lukem 		}
   4747  1.1     lukem 		rc = config_parse_vals( ct, ca, i );
   4748  1.1     lukem 		if ( rc ) {
   4749  1.1     lukem 			break;
   4750  1.1     lukem 		}
   4751  1.1     lukem 	}
   4752  1.1     lukem 	return rc;
   4753  1.1     lukem }
   4754  1.1     lukem 
   4755  1.1     lukem static int
   4756  1.1     lukem config_rename_attr( SlapReply *rs, Entry *e, struct berval *rdn,
   4757  1.1     lukem 	Attribute **at )
   4758  1.1     lukem {
   4759  1.1     lukem 	struct berval rtype, rval;
   4760  1.1     lukem 	Attribute *a;
   4761  1.1     lukem 	AttributeDescription *ad = NULL;
   4762  1.1     lukem 
   4763  1.1     lukem 	dnRdn( &e->e_name, rdn );
   4764  1.1     lukem 	rval.bv_val = strchr(rdn->bv_val, '=' ) + 1;
   4765  1.1     lukem 	rval.bv_len = rdn->bv_len - (rval.bv_val - rdn->bv_val);
   4766  1.1     lukem 	rtype.bv_val = rdn->bv_val;
   4767  1.1     lukem 	rtype.bv_len = rval.bv_val - rtype.bv_val - 1;
   4768  1.1     lukem 
   4769  1.1     lukem 	/* Find attr */
   4770  1.1     lukem 	slap_bv2ad( &rtype, &ad, &rs->sr_text );
   4771  1.1     lukem 	a = attr_find( e->e_attrs, ad );
   4772  1.1     lukem 	if (!a ) return LDAP_NAMING_VIOLATION;
   4773  1.1     lukem 	*at = a;
   4774  1.1     lukem 
   4775  1.1     lukem 	return 0;
   4776  1.1     lukem }
   4777  1.1     lukem 
   4778  1.1     lukem static void
   4779  1.1     lukem config_rename_kids( CfEntryInfo *ce )
   4780  1.1     lukem {
   4781  1.1     lukem 	CfEntryInfo *ce2;
   4782  1.1     lukem 	struct berval rdn, nrdn;
   4783  1.1     lukem 
   4784  1.1     lukem 	for (ce2 = ce->ce_kids; ce2; ce2 = ce2->ce_sibs) {
   4785  1.2  christos 		struct berval newdn, newndn;
   4786  1.1     lukem 		dnRdn ( &ce2->ce_entry->e_name, &rdn );
   4787  1.1     lukem 		dnRdn ( &ce2->ce_entry->e_nname, &nrdn );
   4788  1.2  christos 		build_new_dn( &newdn, &ce->ce_entry->e_name, &rdn, NULL );
   4789  1.2  christos 		build_new_dn( &newndn, &ce->ce_entry->e_nname, &nrdn, NULL );
   4790  1.1     lukem 		free( ce2->ce_entry->e_name.bv_val );
   4791  1.1     lukem 		free( ce2->ce_entry->e_nname.bv_val );
   4792  1.2  christos 		ce2->ce_entry->e_name = newdn;
   4793  1.2  christos 		ce2->ce_entry->e_nname = newndn;
   4794  1.1     lukem 		config_rename_kids( ce2 );
   4795  1.1     lukem 	}
   4796  1.1     lukem }
   4797  1.1     lukem 
   4798  1.1     lukem static int
   4799  1.1     lukem config_rename_one( Operation *op, SlapReply *rs, Entry *e,
   4800  1.1     lukem 	CfEntryInfo *parent, Attribute *a, struct berval *newrdn,
   4801  1.1     lukem 	struct berval *nnewrdn, int use_ldif )
   4802  1.1     lukem {
   4803  1.2  christos 	int cnt, rc = 0;
   4804  1.1     lukem 	struct berval odn, ondn;
   4805  1.2  christos 	const char *text = "";
   4806  1.2  christos 	LDAPRDN rDN;
   4807  1.1     lukem 
   4808  1.1     lukem 	odn = e->e_name;
   4809  1.1     lukem 	ondn = e->e_nname;
   4810  1.1     lukem 	build_new_dn( &e->e_name, &parent->ce_entry->e_name, newrdn, NULL );
   4811  1.1     lukem 	build_new_dn( &e->e_nname, &parent->ce_entry->e_nname, nnewrdn, NULL );
   4812  1.1     lukem 
   4813  1.1     lukem 	/* Replace attr */
   4814  1.3  christos 	rc = ldap_bv2rdn( &e->e_name, &rDN, (char **)&text, LDAP_DN_FORMAT_LDAP );
   4815  1.2  christos 	if ( rc ) {
   4816  1.2  christos 		return rc;
   4817  1.2  christos 	}
   4818  1.2  christos 	for ( cnt = 0; rDN[cnt]; cnt++ ) {
   4819  1.2  christos 		AttributeDescription *ad = NULL;
   4820  1.2  christos 		LDAPAVA *ava = rDN[cnt];
   4821  1.2  christos 
   4822  1.2  christos 		rc = slap_bv2ad( &ava->la_attr, &ad, &text );
   4823  1.2  christos 		if ( rc ) {
   4824  1.2  christos 			break;
   4825  1.2  christos 		}
   4826  1.2  christos 
   4827  1.2  christos 		if ( ad != a->a_desc ) continue;
   4828  1.2  christos 
   4829  1.2  christos 		free( a->a_vals[0].bv_val );
   4830  1.2  christos 		ber_dupbv( &a->a_vals[0], &ava->la_value );
   4831  1.2  christos 		if ( a->a_nvals != a->a_vals ) {
   4832  1.2  christos 			free( a->a_nvals[0].bv_val );
   4833  1.2  christos 			rc = attr_normalize_one( ad, &ava->la_value, &a->a_nvals[0], NULL );
   4834  1.2  christos 			if ( rc ) {
   4835  1.2  christos 				break;
   4836  1.2  christos 			}
   4837  1.2  christos 		}
   4838  1.2  christos 
   4839  1.2  christos 		/* attributes with X-ORDERED 'SIBLINGS' are single-valued, we're done */
   4840  1.2  christos 		break;
   4841  1.2  christos 	}
   4842  1.2  christos 	/* the attribute must be present in rDN */
   4843  1.2  christos 	assert( rDN[cnt] );
   4844  1.2  christos 	ldap_rdnfree( rDN );
   4845  1.2  christos 	if ( rc ) {
   4846  1.2  christos 		return rc;
   4847  1.1     lukem 	}
   4848  1.2  christos 
   4849  1.1     lukem 	if ( use_ldif ) {
   4850  1.1     lukem 		CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private;
   4851  1.1     lukem 		BackendDB *be = op->o_bd;
   4852  1.4  christos 		slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp;
   4853  1.1     lukem 		struct berval dn, ndn, xdn, xndn;
   4854  1.1     lukem 
   4855  1.1     lukem 		op->o_bd = &cfb->cb_db;
   4856  1.1     lukem 
   4857  1.1     lukem 		/* Save current rootdn; use the underlying DB's rootdn */
   4858  1.1     lukem 		dn = op->o_dn;
   4859  1.1     lukem 		ndn = op->o_ndn;
   4860  1.1     lukem 		xdn = op->o_req_dn;
   4861  1.1     lukem 		xndn = op->o_req_ndn;
   4862  1.1     lukem 		op->o_dn = op->o_bd->be_rootdn;
   4863  1.1     lukem 		op->o_ndn = op->o_bd->be_rootndn;
   4864  1.1     lukem 		op->o_req_dn = odn;
   4865  1.1     lukem 		op->o_req_ndn = ondn;
   4866  1.1     lukem 
   4867  1.1     lukem 		scp = op->o_callback;
   4868  1.1     lukem 		op->o_callback = &sc;
   4869  1.4  christos 		rs->sr_ctrls = NULL;
   4870  1.4  christos 
   4871  1.1     lukem 		op->orr_newrdn = *newrdn;
   4872  1.1     lukem 		op->orr_nnewrdn = *nnewrdn;
   4873  1.1     lukem 		op->orr_newSup = NULL;
   4874  1.1     lukem 		op->orr_nnewSup = NULL;
   4875  1.4  christos 		op->orr_newDN = e->e_name;
   4876  1.4  christos 		op->orr_nnewDN = e->e_nname;
   4877  1.1     lukem 		op->orr_deleteoldrdn = 1;
   4878  1.1     lukem 		op->orr_modlist = NULL;
   4879  1.1     lukem 		slap_modrdn2mods( op, rs );
   4880  1.1     lukem 		slap_mods_opattrs( op, &op->orr_modlist, 1 );
   4881  1.1     lukem 		rc = op->o_bd->be_modrdn( op, rs );
   4882  1.1     lukem 		slap_mods_free( op->orr_modlist, 1 );
   4883  1.1     lukem 
   4884  1.1     lukem 		op->o_bd = be;
   4885  1.1     lukem 		op->o_callback = scp;
   4886  1.1     lukem 		op->o_dn = dn;
   4887  1.1     lukem 		op->o_ndn = ndn;
   4888  1.1     lukem 		op->o_req_dn = xdn;
   4889  1.1     lukem 		op->o_req_ndn = xndn;
   4890  1.4  christos 
   4891  1.4  christos 		rs->sr_ctrls = sc.sc_private;
   4892  1.4  christos 		rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
   4893  1.1     lukem 	}
   4894  1.1     lukem 	free( odn.bv_val );
   4895  1.1     lukem 	free( ondn.bv_val );
   4896  1.1     lukem 	if ( e->e_private )
   4897  1.1     lukem 		config_rename_kids( e->e_private );
   4898  1.1     lukem 	return rc;
   4899  1.1     lukem }
   4900  1.1     lukem 
   4901  1.1     lukem static int
   4902  1.1     lukem config_renumber_one( Operation *op, SlapReply *rs, CfEntryInfo *parent,
   4903  1.1     lukem 	Entry *e, int idx, int tailindex, int use_ldif )
   4904  1.1     lukem {
   4905  1.1     lukem 	struct berval ival, newrdn, nnewrdn;
   4906  1.1     lukem 	struct berval rdn;
   4907  1.1     lukem 	Attribute *a;
   4908  1.1     lukem 	char ibuf[32], *ptr1, *ptr2 = NULL;
   4909  1.1     lukem 	int rc = 0;
   4910  1.1     lukem 
   4911  1.1     lukem 	rc = config_rename_attr( rs, e, &rdn, &a );
   4912  1.1     lukem 	if ( rc ) return rc;
   4913  1.1     lukem 
   4914  1.1     lukem 	ival.bv_val = ibuf;
   4915  1.1     lukem 	ival.bv_len = snprintf( ibuf, sizeof( ibuf ), SLAP_X_ORDERED_FMT, idx );
   4916  1.1     lukem 	if ( ival.bv_len >= sizeof( ibuf ) ) {
   4917  1.1     lukem 		return LDAP_NAMING_VIOLATION;
   4918  1.1     lukem 	}
   4919  1.1     lukem 
   4920  1.1     lukem 	newrdn.bv_len = rdn.bv_len + ival.bv_len;
   4921  1.1     lukem 	newrdn.bv_val = ch_malloc( newrdn.bv_len+1 );
   4922  1.1     lukem 
   4923  1.1     lukem 	if ( tailindex ) {
   4924  1.1     lukem 		ptr1 = lutil_strncopy( newrdn.bv_val, rdn.bv_val, rdn.bv_len );
   4925  1.1     lukem 		ptr1 = lutil_strcopy( ptr1, ival.bv_val );
   4926  1.1     lukem 	} else {
   4927  1.1     lukem 		int xlen;
   4928  1.1     lukem 		ptr2 = ber_bvchr( &rdn, '}' );
   4929  1.1     lukem 		if ( ptr2 ) {
   4930  1.1     lukem 			ptr2++;
   4931  1.1     lukem 		} else {
   4932  1.1     lukem 			ptr2 = rdn.bv_val + a->a_desc->ad_cname.bv_len + 1;
   4933  1.1     lukem 		}
   4934  1.1     lukem 		xlen = rdn.bv_len - (ptr2 - rdn.bv_val);
   4935  1.1     lukem 		ptr1 = lutil_strncopy( newrdn.bv_val, a->a_desc->ad_cname.bv_val,
   4936  1.1     lukem 			a->a_desc->ad_cname.bv_len );
   4937  1.1     lukem 		*ptr1++ = '=';
   4938  1.1     lukem 		ptr1 = lutil_strcopy( ptr1, ival.bv_val );
   4939  1.1     lukem 		ptr1 = lutil_strncopy( ptr1, ptr2, xlen );
   4940  1.1     lukem 		*ptr1 = '\0';
   4941  1.1     lukem 	}
   4942  1.1     lukem 
   4943  1.1     lukem 	/* Do the equivalent of ModRDN */
   4944  1.1     lukem 	/* Replace DN / NDN */
   4945  1.1     lukem 	newrdn.bv_len = ptr1 - newrdn.bv_val;
   4946  1.2  christos 	rc = rdnNormalize( 0, NULL, NULL, &newrdn, &nnewrdn, NULL );
   4947  1.2  christos 	if ( rc ) {
   4948  1.2  christos 		free( newrdn.bv_val );
   4949  1.2  christos 		return LDAP_NAMING_VIOLATION;
   4950  1.2  christos 	}
   4951  1.1     lukem 	rc = config_rename_one( op, rs, e, parent, a, &newrdn, &nnewrdn, use_ldif );
   4952  1.1     lukem 
   4953  1.1     lukem 	free( nnewrdn.bv_val );
   4954  1.1     lukem 	free( newrdn.bv_val );
   4955  1.1     lukem 	return rc;
   4956  1.1     lukem }
   4957  1.1     lukem 
   4958  1.1     lukem static int
   4959  1.1     lukem check_name_index( CfEntryInfo *parent, ConfigType ce_type, Entry *e,
   4960  1.1     lukem 	SlapReply *rs, int *renum, int *ibase )
   4961  1.1     lukem {
   4962  1.1     lukem 	CfEntryInfo *ce;
   4963  1.1     lukem 	int index = -1, gotindex = 0, nsibs, rc = 0;
   4964  1.1     lukem 	int renumber = 0, tailindex = 0, isfrontend = 0, isconfig = 0;
   4965  1.1     lukem 	char *ptr1, *ptr2 = NULL;
   4966  1.1     lukem 	struct berval rdn;
   4967  1.1     lukem 
   4968  1.1     lukem 	if ( renum ) *renum = 0;
   4969  1.1     lukem 
   4970  1.1     lukem 	/* These entries don't get indexed/renumbered */
   4971  1.1     lukem 	if ( ce_type == Cft_Global ) return 0;
   4972  1.1     lukem 	if ( ce_type == Cft_Schema && parent->ce_type == Cft_Global ) return 0;
   4973  1.1     lukem 
   4974  1.1     lukem 	if ( ce_type == Cft_Module )
   4975  1.1     lukem 		tailindex = 1;
   4976  1.1     lukem 
   4977  1.1     lukem 	/* See if the rdn has an index already */
   4978  1.1     lukem 	dnRdn( &e->e_name, &rdn );
   4979  1.1     lukem 	if ( ce_type == Cft_Database ) {
   4980  1.1     lukem 		if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("frontend"),
   4981  1.1     lukem 				"frontend", STRLENOF("frontend") ))
   4982  1.1     lukem 			isfrontend = 1;
   4983  1.1     lukem 		else if ( !strncmp( rdn.bv_val + rdn.bv_len - STRLENOF("config"),
   4984  1.1     lukem 				"config", STRLENOF("config") ))
   4985  1.1     lukem 			isconfig = 1;
   4986  1.1     lukem 	}
   4987  1.1     lukem 	ptr1 = ber_bvchr( &e->e_name, '{' );
   4988  1.2  christos 	if ( ptr1 && ptr1 < &e->e_name.bv_val[ rdn.bv_len ] ) {
   4989  1.1     lukem 		char	*next;
   4990  1.1     lukem 		ptr2 = strchr( ptr1, '}' );
   4991  1.2  christos 		if ( !ptr2 || ptr2 > &e->e_name.bv_val[ rdn.bv_len ] )
   4992  1.1     lukem 			return LDAP_NAMING_VIOLATION;
   4993  1.1     lukem 		if ( ptr2-ptr1 == 1)
   4994  1.1     lukem 			return LDAP_NAMING_VIOLATION;
   4995  1.1     lukem 		gotindex = 1;
   4996  1.1     lukem 		index = strtol( ptr1 + 1, &next, 10 );
   4997  1.1     lukem 		if ( next == ptr1 + 1 || next[ 0 ] != '}' ) {
   4998  1.1     lukem 			return LDAP_NAMING_VIOLATION;
   4999  1.1     lukem 		}
   5000  1.1     lukem 		if ( index < 0 ) {
   5001  1.1     lukem 			/* Special case, we allow -1 for the frontendDB */
   5002  1.1     lukem 			if ( index != -1 || !isfrontend )
   5003  1.1     lukem 				return LDAP_NAMING_VIOLATION;
   5004  1.1     lukem 		}
   5005  1.1     lukem 		if ( isconfig && index != 0 ){
   5006  1.1     lukem 			return LDAP_NAMING_VIOLATION;
   5007  1.1     lukem 		}
   5008  1.1     lukem 	}
   5009  1.1     lukem 
   5010  1.2  christos 	/* count related kids.
   5011  1.2  christos 	 * For entries of type Cft_Misc, only count siblings with same RDN type
   5012  1.2  christos 	 */
   5013  1.2  christos 	if ( ce_type == Cft_Misc ) {
   5014  1.2  christos 		rdn.bv_val = e->e_nname.bv_val;
   5015  1.2  christos 		ptr1 = strchr( rdn.bv_val, '=' );
   5016  1.2  christos 		assert( ptr1 != NULL );
   5017  1.2  christos 
   5018  1.2  christos 		rdn.bv_len = ptr1 - rdn.bv_val;
   5019  1.2  christos 
   5020  1.2  christos 		for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) {
   5021  1.2  christos 			struct berval rdn2;
   5022  1.2  christos 			if ( ce->ce_type != ce_type )
   5023  1.2  christos 				continue;
   5024  1.2  christos 
   5025  1.2  christos 			dnRdn( &ce->ce_entry->e_nname, &rdn2 );
   5026  1.2  christos 
   5027  1.2  christos 			ptr1 = strchr( rdn2.bv_val, '=' );
   5028  1.2  christos 			assert( ptr1 != NULL );
   5029  1.2  christos 
   5030  1.2  christos 			rdn2.bv_len = ptr1 - rdn2.bv_val;
   5031  1.2  christos 			if ( bvmatch( &rdn, &rdn2 ))
   5032  1.2  christos 				nsibs++;
   5033  1.2  christos 		}
   5034  1.2  christos 	} else {
   5035  1.2  christos 		for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) {
   5036  1.2  christos 			if ( ce->ce_type == ce_type ) nsibs++;
   5037  1.2  christos 		}
   5038  1.1     lukem 	}
   5039  1.1     lukem 
   5040  1.1     lukem 	/* account for -1 frontend */
   5041  1.1     lukem 	if ( ce_type == Cft_Database )
   5042  1.1     lukem 		nsibs--;
   5043  1.1     lukem 
   5044  1.2  christos 	if ( index != nsibs || isfrontend ) {
   5045  1.1     lukem 		if ( gotindex ) {
   5046  1.1     lukem 			if ( index < nsibs ) {
   5047  1.1     lukem 				if ( tailindex ) return LDAP_NAMING_VIOLATION;
   5048  1.1     lukem 				/* Siblings need to be renumbered */
   5049  1.1     lukem 				if ( index != -1 || !isfrontend )
   5050  1.1     lukem 					renumber = 1;
   5051  1.1     lukem 			}
   5052  1.1     lukem 		}
   5053  1.1     lukem 		/* config DB is always "0" */
   5054  1.1     lukem 		if ( isconfig && index == -1 ) {
   5055  1.1     lukem 			index = 0;
   5056  1.1     lukem 		}
   5057  1.2  christos 		if (( !isfrontend && index == -1 ) || ( index > nsibs ) ){
   5058  1.1     lukem 			index = nsibs;
   5059  1.1     lukem 		}
   5060  1.1     lukem 
   5061  1.1     lukem 		/* just make index = nsibs */
   5062  1.1     lukem 		if ( !renumber ) {
   5063  1.1     lukem 			rc = config_renumber_one( NULL, rs, parent, e, index, tailindex, 0 );
   5064  1.1     lukem 		}
   5065  1.1     lukem 	}
   5066  1.1     lukem 	if ( ibase ) *ibase = index;
   5067  1.1     lukem 	if ( renum ) *renum = renumber;
   5068  1.1     lukem 	return rc;
   5069  1.1     lukem }
   5070  1.1     lukem 
   5071  1.2  christos /* Insert all superior classes of the given class */
   5072  1.1     lukem static int
   5073  1.1     lukem count_oc( ObjectClass *oc, ConfigOCs ***copp, int *nocs )
   5074  1.1     lukem {
   5075  1.1     lukem 	ConfigOCs	co, *cop;
   5076  1.1     lukem 	ObjectClass	**sups;
   5077  1.1     lukem 
   5078  1.2  christos 	for ( sups = oc->soc_sups; sups && *sups; sups++ ) {
   5079  1.2  christos 		if ( count_oc( *sups, copp, nocs ) ) {
   5080  1.2  christos 			return -1;
   5081  1.2  christos 		}
   5082  1.2  christos 	}
   5083  1.2  christos 
   5084  1.1     lukem 	co.co_name = &oc->soc_cname;
   5085  1.3  christos 	cop = ldap_avl_find( CfOcTree, &co, CfOc_cmp );
   5086  1.1     lukem 	if ( cop ) {
   5087  1.1     lukem 		int	i;
   5088  1.1     lukem 
   5089  1.1     lukem 		/* check for duplicates */
   5090  1.1     lukem 		for ( i = 0; i < *nocs; i++ ) {
   5091  1.1     lukem 			if ( *copp && (*copp)[i] == cop ) {
   5092  1.1     lukem 				break;
   5093  1.1     lukem 			}
   5094  1.1     lukem 		}
   5095  1.1     lukem 
   5096  1.1     lukem 		if ( i == *nocs ) {
   5097  1.1     lukem 			ConfigOCs **tmp = ch_realloc( *copp, (*nocs + 1)*sizeof( ConfigOCs * ) );
   5098  1.1     lukem 			if ( tmp == NULL ) {
   5099  1.1     lukem 				return -1;
   5100  1.1     lukem 			}
   5101  1.1     lukem 			*copp = tmp;
   5102  1.1     lukem 			(*copp)[*nocs] = cop;
   5103  1.1     lukem 			(*nocs)++;
   5104  1.1     lukem 		}
   5105  1.1     lukem 	}
   5106  1.1     lukem 
   5107  1.1     lukem 	return 0;
   5108  1.1     lukem }
   5109  1.1     lukem 
   5110  1.2  christos /* Find all superior classes of the given objectclasses,
   5111  1.2  christos  * return list in order of most-subordinate first.
   5112  1.2  christos  *
   5113  1.2  christos  * Special / auxiliary / Cft_Misc classes always take precedence.
   5114  1.2  christos  */
   5115  1.1     lukem static ConfigOCs **
   5116  1.1     lukem count_ocs( Attribute *oc_at, int *nocs )
   5117  1.1     lukem {
   5118  1.2  christos 	int		i, j, misc = -1;
   5119  1.1     lukem 	ConfigOCs	**colst = NULL;
   5120  1.1     lukem 
   5121  1.1     lukem 	*nocs = 0;
   5122  1.1     lukem 
   5123  1.2  christos 	for ( i = oc_at->a_numvals; i--; ) {
   5124  1.1     lukem 		ObjectClass	*oc = oc_bvfind( &oc_at->a_nvals[i] );
   5125  1.1     lukem 
   5126  1.1     lukem 		assert( oc != NULL );
   5127  1.1     lukem 		if ( count_oc( oc, &colst, nocs ) ) {
   5128  1.1     lukem 			ch_free( colst );
   5129  1.1     lukem 			return NULL;
   5130  1.1     lukem 		}
   5131  1.1     lukem 	}
   5132  1.1     lukem 
   5133  1.2  christos 	/* invert order */
   5134  1.2  christos 	i = 0;
   5135  1.2  christos 	j = *nocs - 1;
   5136  1.2  christos 	while ( i < j ) {
   5137  1.2  christos 		ConfigOCs *tmp = colst[i];
   5138  1.2  christos 		colst[i] = colst[j];
   5139  1.2  christos 		colst[j] = tmp;
   5140  1.2  christos 		if (tmp->co_type == Cft_Misc)
   5141  1.2  christos 			misc = j;
   5142  1.2  christos 		i++; j--;
   5143  1.2  christos 	}
   5144  1.2  christos 	/* Move misc class to front of list */
   5145  1.2  christos 	if (misc > 0) {
   5146  1.2  christos 		ConfigOCs *tmp = colst[misc];
   5147  1.2  christos 		for (i=misc; i>0; i--)
   5148  1.2  christos 			colst[i] = colst[i-1];
   5149  1.2  christos 		colst[0] = tmp;
   5150  1.2  christos 	}
   5151  1.2  christos 
   5152  1.1     lukem 	return colst;
   5153  1.1     lukem }
   5154  1.1     lukem 
   5155  1.1     lukem static int
   5156  1.1     lukem cfAddInclude( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
   5157  1.1     lukem {
   5158  1.1     lukem 	/* Leftover from RE23. Never parse this entry */
   5159  1.1     lukem 	return LDAP_COMPARE_TRUE;
   5160  1.1     lukem }
   5161  1.1     lukem 
   5162  1.1     lukem static int
   5163  1.1     lukem cfAddSchema( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
   5164  1.1     lukem {
   5165  1.1     lukem 	ConfigFile *cfo;
   5166  1.1     lukem 
   5167  1.1     lukem 	/* This entry is hardcoded, don't re-parse it */
   5168  1.1     lukem 	if ( p->ce_type == Cft_Global ) {
   5169  1.1     lukem 		cfn = p->ce_private;
   5170  1.1     lukem 		ca->ca_private = cfn;
   5171  1.1     lukem 		return LDAP_COMPARE_TRUE;
   5172  1.1     lukem 	}
   5173  1.1     lukem 	if ( p->ce_type != Cft_Schema )
   5174  1.1     lukem 		return LDAP_CONSTRAINT_VIOLATION;
   5175  1.1     lukem 
   5176  1.1     lukem 	cfn = ch_calloc( 1, sizeof(ConfigFile) );
   5177  1.1     lukem 	ca->ca_private = cfn;
   5178  1.1     lukem 	cfo = p->ce_private;
   5179  1.1     lukem 	cfn->c_sibs = cfo->c_kids;
   5180  1.1     lukem 	cfo->c_kids = cfn;
   5181  1.1     lukem 	return LDAP_SUCCESS;
   5182  1.1     lukem }
   5183  1.1     lukem 
   5184  1.1     lukem static int
   5185  1.1     lukem cfAddDatabase( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
   5186  1.1     lukem {
   5187  1.1     lukem 	if ( p->ce_type != Cft_Global ) {
   5188  1.1     lukem 		return LDAP_CONSTRAINT_VIOLATION;
   5189  1.1     lukem 	}
   5190  1.2  christos 	/* config must be {0}, nothing else allowed */
   5191  1.2  christos 	if ( !strncmp( e->e_nname.bv_val, "olcDatabase={0}", STRLENOF("olcDatabase={0}")) &&
   5192  1.2  christos 		strncmp( e->e_nname.bv_val + STRLENOF("olcDatabase={0}"), "config,", STRLENOF("config,") )) {
   5193  1.2  christos 		return LDAP_CONSTRAINT_VIOLATION;
   5194  1.2  christos 	}
   5195  1.1     lukem 	ca->be = frontendDB;	/* just to get past check_vals */
   5196  1.1     lukem 	return LDAP_SUCCESS;
   5197  1.1     lukem }
   5198  1.1     lukem 
   5199  1.1     lukem static int
   5200  1.1     lukem cfAddBackend( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
   5201  1.1     lukem {
   5202  1.1     lukem 	if ( p->ce_type != Cft_Global ) {
   5203  1.1     lukem 		return LDAP_CONSTRAINT_VIOLATION;
   5204  1.1     lukem 	}
   5205  1.1     lukem 	return LDAP_SUCCESS;
   5206  1.1     lukem }
   5207  1.1     lukem 
   5208  1.1     lukem static int
   5209  1.1     lukem cfAddModule( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
   5210  1.1     lukem {
   5211  1.1     lukem 	if ( p->ce_type != Cft_Global ) {
   5212  1.1     lukem 		return LDAP_CONSTRAINT_VIOLATION;
   5213  1.1     lukem 	}
   5214  1.1     lukem 	return LDAP_SUCCESS;
   5215  1.1     lukem }
   5216  1.1     lukem 
   5217  1.1     lukem static int
   5218  1.1     lukem cfAddOverlay( CfEntryInfo *p, Entry *e, struct config_args_s *ca )
   5219  1.1     lukem {
   5220  1.1     lukem 	if ( p->ce_type != Cft_Database ) {
   5221  1.1     lukem 		return LDAP_CONSTRAINT_VIOLATION;
   5222  1.1     lukem 	}
   5223  1.1     lukem 	ca->be = p->ce_be;
   5224  1.1     lukem 	return LDAP_SUCCESS;
   5225  1.1     lukem }
   5226  1.1     lukem 
   5227  1.1     lukem static void
   5228  1.1     lukem schema_destroy_one( ConfigArgs *ca, ConfigOCs **colst, int nocs,
   5229  1.1     lukem 	CfEntryInfo *p )
   5230  1.1     lukem {
   5231  1.1     lukem 	ConfigTable *ct;
   5232  1.1     lukem 	ConfigFile *cfo;
   5233  1.1     lukem 	AttributeDescription *ad;
   5234  1.1     lukem 	const char *text;
   5235  1.1     lukem 
   5236  1.1     lukem 	ca->valx = -1;
   5237  1.1     lukem 	ca->line = NULL;
   5238  1.2  christos 	ca->argc = 1;
   5239  1.1     lukem 	if ( cfn->c_cr_head ) {
   5240  1.1     lukem 		struct berval bv = BER_BVC("olcDitContentRules");
   5241  1.1     lukem 		ad = NULL;
   5242  1.1     lukem 		slap_bv2ad( &bv, &ad, &text );
   5243  1.1     lukem 		ct = config_find_table( colst, nocs, ad, ca );
   5244  1.1     lukem 		config_del_vals( ct, ca );
   5245  1.1     lukem 	}
   5246  1.1     lukem 	if ( cfn->c_oc_head ) {
   5247  1.1     lukem 		struct berval bv = BER_BVC("olcObjectClasses");
   5248  1.1     lukem 		ad = NULL;
   5249  1.1     lukem 		slap_bv2ad( &bv, &ad, &text );
   5250  1.1     lukem 		ct = config_find_table( colst, nocs, ad, ca );
   5251  1.1     lukem 		config_del_vals( ct, ca );
   5252  1.1     lukem 	}
   5253  1.1     lukem 	if ( cfn->c_at_head ) {
   5254  1.1     lukem 		struct berval bv = BER_BVC("olcAttributeTypes");
   5255  1.1     lukem 		ad = NULL;
   5256  1.1     lukem 		slap_bv2ad( &bv, &ad, &text );
   5257  1.1     lukem 		ct = config_find_table( colst, nocs, ad, ca );
   5258  1.1     lukem 		config_del_vals( ct, ca );
   5259  1.1     lukem 	}
   5260  1.2  christos 	if ( cfn->c_syn_head ) {
   5261  1.2  christos 		struct berval bv = BER_BVC("olcLdapSyntaxes");
   5262  1.2  christos 		ad = NULL;
   5263  1.2  christos 		slap_bv2ad( &bv, &ad, &text );
   5264  1.2  christos 		ct = config_find_table( colst, nocs, ad, ca );
   5265  1.2  christos 		config_del_vals( ct, ca );
   5266  1.2  christos 	}
   5267  1.1     lukem 	if ( cfn->c_om_head ) {
   5268  1.1     lukem 		struct berval bv = BER_BVC("olcObjectIdentifier");
   5269  1.1     lukem 		ad = NULL;
   5270  1.1     lukem 		slap_bv2ad( &bv, &ad, &text );
   5271  1.1     lukem 		ct = config_find_table( colst, nocs, ad, ca );
   5272  1.1     lukem 		config_del_vals( ct, ca );
   5273  1.1     lukem 	}
   5274  1.1     lukem 	cfo = p->ce_private;
   5275  1.1     lukem 	cfo->c_kids = cfn->c_sibs;
   5276  1.1     lukem 	ch_free( cfn );
   5277  1.1     lukem }
   5278  1.1     lukem 
   5279  1.1     lukem static int
   5280  1.1     lukem config_add_oc( ConfigOCs **cop, CfEntryInfo *last, Entry *e, ConfigArgs *ca )
   5281  1.1     lukem {
   5282  1.1     lukem 	int		rc = LDAP_CONSTRAINT_VIOLATION;
   5283  1.1     lukem 	ObjectClass	**ocp;
   5284  1.1     lukem 
   5285  1.1     lukem 	if ( (*cop)->co_ldadd ) {
   5286  1.1     lukem 		rc = (*cop)->co_ldadd( last, e, ca );
   5287  1.1     lukem 		if ( rc != LDAP_CONSTRAINT_VIOLATION ) {
   5288  1.1     lukem 			return rc;
   5289  1.1     lukem 		}
   5290  1.1     lukem 	}
   5291  1.1     lukem 
   5292  1.1     lukem 	for ( ocp = (*cop)->co_oc->soc_sups; ocp && *ocp; ocp++ ) {
   5293  1.1     lukem 		ConfigOCs	co = { 0 };
   5294  1.1     lukem 
   5295  1.1     lukem 		co.co_name = &(*ocp)->soc_cname;
   5296  1.3  christos 		*cop = ldap_avl_find( CfOcTree, &co, CfOc_cmp );
   5297  1.1     lukem 		if ( *cop == NULL ) {
   5298  1.1     lukem 			return rc;
   5299  1.1     lukem 		}
   5300  1.1     lukem 
   5301  1.1     lukem 		rc = config_add_oc( cop, last, e, ca );
   5302  1.1     lukem 		if ( rc != LDAP_CONSTRAINT_VIOLATION ) {
   5303  1.1     lukem 			return rc;
   5304  1.1     lukem 		}
   5305  1.1     lukem 	}
   5306  1.1     lukem 
   5307  1.1     lukem 	return rc;
   5308  1.1     lukem }
   5309  1.1     lukem 
   5310  1.4  christos static BackendDB *configDB;		/* only set by slapadd */
   5311  1.4  christos 
   5312  1.1     lukem /* Parse an LDAP entry into config directives */
   5313  1.1     lukem static int
   5314  1.1     lukem config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
   5315  1.1     lukem 	int *renum, Operation *op )
   5316  1.1     lukem {
   5317  1.1     lukem 	CfEntryInfo	*ce, *last = NULL;
   5318  1.1     lukem 	ConfigOCs	co, *coptr, **colst;
   5319  1.1     lukem 	Attribute	*a, *oc_at, *soc_at;
   5320  1.1     lukem 	int		i, ibase = -1, nocs, rc = 0;
   5321  1.1     lukem 	struct berval	pdn;
   5322  1.1     lukem 	ConfigTable	*ct;
   5323  1.1     lukem 	char		*ptr, *log_prefix = op ? op->o_log_prefix : "";
   5324  1.1     lukem 
   5325  1.1     lukem 	memset( ca, 0, sizeof(ConfigArgs));
   5326  1.1     lukem 
   5327  1.1     lukem 	/* Make sure parent exists and entry does not. But allow
   5328  1.1     lukem 	 * Databases and Overlays to be inserted. Don't do any
   5329  1.1     lukem 	 * auto-renumbering if manageDSAit control is present.
   5330  1.1     lukem 	 */
   5331  1.4  christos 	ce = config_find_base( cfb->cb_root, &e->e_nname, &last, op );
   5332  1.1     lukem 	if ( ce ) {
   5333  1.1     lukem 		if ( ( op && op->o_managedsait ) ||
   5334  1.1     lukem 			( ce->ce_type != Cft_Database && ce->ce_type != Cft_Overlay &&
   5335  1.1     lukem 			  ce->ce_type != Cft_Module ) )
   5336  1.1     lukem 		{
   5337  1.1     lukem 			Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5338  1.1     lukem 				"DN=\"%s\" already exists\n",
   5339  1.3  christos 				log_prefix, e->e_name.bv_val );
   5340  1.2  christos 			/* global schema ignores all writes */
   5341  1.2  christos 			if ( ce->ce_type == Cft_Schema && ce->ce_parent->ce_type == Cft_Global )
   5342  1.2  christos 				return LDAP_COMPARE_TRUE;
   5343  1.1     lukem 			return LDAP_ALREADY_EXISTS;
   5344  1.1     lukem 		}
   5345  1.1     lukem 	}
   5346  1.1     lukem 
   5347  1.1     lukem 	dnParent( &e->e_nname, &pdn );
   5348  1.1     lukem 
   5349  1.1     lukem 	/* If last is NULL, the new entry is the root/suffix entry,
   5350  1.1     lukem 	 * otherwise last should be the parent.
   5351  1.1     lukem 	 */
   5352  1.4  christos 	if ( cfb->cb_root && ( !last || !dn_match( &last->ce_entry->e_nname, &pdn ) ) ) {
   5353  1.4  christos 		if ( last && rs ) {
   5354  1.1     lukem 			rs->sr_matched = last->ce_entry->e_name.bv_val;
   5355  1.1     lukem 		}
   5356  1.1     lukem 		Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5357  1.1     lukem 			"DN=\"%s\" not child of DN=\"%s\"\n",
   5358  1.1     lukem 			log_prefix, e->e_name.bv_val,
   5359  1.4  christos 			last ? last->ce_entry->e_name.bv_val : "" );
   5360  1.1     lukem 		return LDAP_NO_SUCH_OBJECT;
   5361  1.1     lukem 	}
   5362  1.1     lukem 
   5363  1.1     lukem 	if ( op ) {
   5364  1.1     lukem 		/* No parent, must be root. This will never happen... */
   5365  1.1     lukem 		if ( !last && !be_isroot( op ) && !be_shadow_update( op ) ) {
   5366  1.1     lukem 			return LDAP_NO_SUCH_OBJECT;
   5367  1.1     lukem 		}
   5368  1.1     lukem 
   5369  1.1     lukem 		if ( last && !access_allowed( op, last->ce_entry,
   5370  1.1     lukem 			slap_schema.si_ad_children, NULL, ACL_WADD, NULL ) )
   5371  1.1     lukem 		{
   5372  1.1     lukem 			Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5373  1.1     lukem 				"DN=\"%s\" no write access to \"children\" of parent\n",
   5374  1.3  christos 				log_prefix, e->e_name.bv_val );
   5375  1.1     lukem 			return LDAP_INSUFFICIENT_ACCESS;
   5376  1.1     lukem 		}
   5377  1.1     lukem 	}
   5378  1.1     lukem 
   5379  1.1     lukem 	oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
   5380  1.1     lukem 	if ( !oc_at ) {
   5381  1.1     lukem 		Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5382  1.1     lukem 			"DN=\"%s\" no objectClass\n",
   5383  1.3  christos 			log_prefix, e->e_name.bv_val );
   5384  1.1     lukem 		return LDAP_OBJECT_CLASS_VIOLATION;
   5385  1.1     lukem 	}
   5386  1.1     lukem 
   5387  1.1     lukem 	soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass );
   5388  1.1     lukem 	if ( !soc_at ) {
   5389  1.1     lukem 		ObjectClass	*soc = NULL;
   5390  1.1     lukem 		char		textbuf[ SLAP_TEXT_BUFLEN ];
   5391  1.1     lukem 		const char	*text = textbuf;
   5392  1.1     lukem 
   5393  1.1     lukem 		/* FIXME: check result */
   5394  1.1     lukem 		rc = structural_class( oc_at->a_nvals, &soc, NULL,
   5395  1.1     lukem 			&text, textbuf, sizeof(textbuf), NULL );
   5396  1.1     lukem 		if ( rc != LDAP_SUCCESS ) {
   5397  1.1     lukem 			Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5398  1.1     lukem 				"DN=\"%s\" no structural objectClass (%s)\n",
   5399  1.1     lukem 				log_prefix, e->e_name.bv_val, text );
   5400  1.1     lukem 			return rc;
   5401  1.1     lukem 		}
   5402  1.1     lukem 		attr_merge_one( e, slap_schema.si_ad_structuralObjectClass, &soc->soc_cname, NULL );
   5403  1.1     lukem 		soc_at = attr_find( e->e_attrs, slap_schema.si_ad_structuralObjectClass );
   5404  1.1     lukem 		if ( soc_at == NULL ) {
   5405  1.1     lukem 			Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5406  1.1     lukem 				"DN=\"%s\" no structural objectClass; "
   5407  1.1     lukem 				"unable to merge computed class %s\n",
   5408  1.1     lukem 				log_prefix, e->e_name.bv_val,
   5409  1.1     lukem 				soc->soc_cname.bv_val );
   5410  1.1     lukem 			return LDAP_OBJECT_CLASS_VIOLATION;
   5411  1.1     lukem 		}
   5412  1.1     lukem 
   5413  1.1     lukem 		Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5414  1.1     lukem 			"DN=\"%s\" no structural objectClass; "
   5415  1.1     lukem 			"computed objectClass %s merged\n",
   5416  1.1     lukem 			log_prefix, e->e_name.bv_val,
   5417  1.1     lukem 			soc->soc_cname.bv_val );
   5418  1.1     lukem 	}
   5419  1.1     lukem 
   5420  1.1     lukem 	/* Fake the coordinates based on whether we're part of an
   5421  1.1     lukem 	 * LDAP Add or if reading the config dir
   5422  1.1     lukem 	 */
   5423  1.1     lukem 	if ( rs ) {
   5424  1.1     lukem 		ca->fname = "slapd";
   5425  1.1     lukem 		ca->lineno = 0;
   5426  1.1     lukem 	} else {
   5427  1.1     lukem 		ca->fname = cfdir.bv_val;
   5428  1.1     lukem 		ca->lineno = 1;
   5429  1.1     lukem 	}
   5430  1.1     lukem 	ca->ca_op = op;
   5431  1.1     lukem 
   5432  1.4  christos 	{
   5433  1.4  christos 		ObjectClass *soc = oc_bvfind( &soc_at->a_nvals[0] );
   5434  1.4  christos 		if ( !soc ) {
   5435  1.4  christos 			Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5436  1.4  christos 				"DN=\"%s\" invalid structural objectClass %s\n",
   5437  1.4  christos 				log_prefix, e->e_name.bv_val, soc_at->a_vals[0].bv_val );
   5438  1.4  christos 			return LDAP_OBJECT_CLASS_VIOLATION;
   5439  1.4  christos 		}
   5440  1.4  christos 		co.co_name = &soc->soc_cname;
   5441  1.4  christos 	}
   5442  1.3  christos 	coptr = ldap_avl_find( CfOcTree, &co, CfOc_cmp );
   5443  1.1     lukem 	if ( coptr == NULL ) {
   5444  1.1     lukem 		Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5445  1.1     lukem 			"DN=\"%s\" no structural objectClass in configuration table\n",
   5446  1.3  christos 			log_prefix, e->e_name.bv_val );
   5447  1.1     lukem 		return LDAP_OBJECT_CLASS_VIOLATION;
   5448  1.1     lukem 	}
   5449  1.1     lukem 
   5450  1.1     lukem 	/* Only the root can be Cft_Global, everything else must
   5451  1.1     lukem 	 * have a parent. Only limited nesting arrangements are allowed.
   5452  1.1     lukem 	 */
   5453  1.1     lukem 	rc = LDAP_CONSTRAINT_VIOLATION;
   5454  1.1     lukem 	if ( coptr->co_type == Cft_Global && !last ) {
   5455  1.1     lukem 		cfn = cfb->cb_config;
   5456  1.1     lukem 		ca->ca_private = cfn;
   5457  1.1     lukem 		ca->be = frontendDB;	/* just to get past check_vals */
   5458  1.1     lukem 		rc = LDAP_SUCCESS;
   5459  1.1     lukem 	}
   5460  1.1     lukem 
   5461  1.1     lukem 	colst = count_ocs( oc_at, &nocs );
   5462  1.1     lukem 
   5463  1.1     lukem 	/* Check whether the Add is allowed by its parent, and do
   5464  1.1     lukem 	 * any necessary arg setup
   5465  1.1     lukem 	 */
   5466  1.1     lukem 	if ( last ) {
   5467  1.1     lukem 		rc = config_add_oc( &coptr, last, e, ca );
   5468  1.1     lukem 		if ( rc == LDAP_CONSTRAINT_VIOLATION ) {
   5469  1.1     lukem 			for ( i = 0; i<nocs; i++ ) {
   5470  1.1     lukem 				/* Already checked these */
   5471  1.1     lukem 				if ( colst[i]->co_oc->soc_kind == LDAP_SCHEMA_STRUCTURAL )
   5472  1.1     lukem 					continue;
   5473  1.1     lukem 				if ( colst[i]->co_ldadd &&
   5474  1.1     lukem 					( rc = colst[i]->co_ldadd( last, e, ca ))
   5475  1.1     lukem 						!= LDAP_CONSTRAINT_VIOLATION ) {
   5476  1.1     lukem 					coptr = colst[i];
   5477  1.1     lukem 					break;
   5478  1.1     lukem 				}
   5479  1.1     lukem 			}
   5480  1.1     lukem 		}
   5481  1.1     lukem 		if ( rc == LDAP_CONSTRAINT_VIOLATION ) {
   5482  1.1     lukem 			Debug( LDAP_DEBUG_TRACE, "%s: config_add_internal: "
   5483  1.1     lukem 				"DN=\"%s\" no structural objectClass add function\n",
   5484  1.3  christos 				log_prefix, e->e_name.bv_val );
   5485  1.1     lukem 			return LDAP_OBJECT_CLASS_VIOLATION;
   5486  1.1     lukem 		}
   5487  1.1     lukem 	}
   5488  1.1     lukem 
   5489  1.1     lukem 	/* Add the entry but don't parse it, we already have its contents */
   5490  1.1     lukem 	if ( rc == LDAP_COMPARE_TRUE ) {
   5491  1.1     lukem 		rc = LDAP_SUCCESS;
   5492  1.1     lukem 		goto ok;
   5493  1.1     lukem 	}
   5494  1.1     lukem 
   5495  1.1     lukem 	if ( rc != LDAP_SUCCESS )
   5496  1.1     lukem 		goto done_noop;
   5497  1.1     lukem 
   5498  1.1     lukem 	/* Parse all the values and check for simple syntax errors before
   5499  1.1     lukem 	 * performing any set actions.
   5500  1.1     lukem 	 *
   5501  1.1     lukem 	 * If doing an LDAPadd, check for indexed names and any necessary
   5502  1.1     lukem 	 * renaming/renumbering. Entries that don't need indexed names are
   5503  1.1     lukem 	 * ignored. Entries that need an indexed name and arrive without one
   5504  1.1     lukem 	 * are assigned to the end. Entries that arrive with an index may
   5505  1.1     lukem 	 * cause the following entries to be renumbered/bumped down.
   5506  1.1     lukem 	 *
   5507  1.1     lukem 	 * Note that "pseudo-indexed" entries (cn=Include{xx}, cn=Module{xx})
   5508  1.1     lukem 	 * don't allow Adding an entry with an index that's already in use.
   5509  1.1     lukem 	 * This is flagged as an error (LDAP_ALREADY_EXISTS) up above.
   5510  1.1     lukem 	 *
   5511  1.1     lukem 	 * These entries can have auto-assigned indexes (appended to the end)
   5512  1.1     lukem 	 * but only the other types support auto-renumbering of siblings.
   5513  1.1     lukem 	 */
   5514  1.1     lukem 	{
   5515  1.1     lukem 		rc = check_name_index( last, coptr->co_type, e, rs, renum,
   5516  1.1     lukem 			&ibase );
   5517  1.1     lukem 		if ( rc ) {
   5518  1.1     lukem 			goto done_noop;
   5519  1.1     lukem 		}
   5520  1.1     lukem 		if ( renum && *renum && coptr->co_type != Cft_Database &&
   5521  1.1     lukem 			coptr->co_type != Cft_Overlay )
   5522  1.1     lukem 		{
   5523  1.1     lukem 			snprintf( ca->cr_msg, sizeof( ca->cr_msg ),
   5524  1.1     lukem 				"operation requires sibling renumbering" );
   5525  1.1     lukem 			rc = LDAP_UNWILLING_TO_PERFORM;
   5526  1.1     lukem 			goto done_noop;
   5527  1.1     lukem 		}
   5528  1.1     lukem 	}
   5529  1.1     lukem 
   5530  1.1     lukem 	init_config_argv( ca );
   5531  1.1     lukem 
   5532  1.1     lukem 	/* Make sure we process attrs in the required order */
   5533  1.1     lukem 	sort_attrs( e, colst, nocs );
   5534  1.1     lukem 
   5535  1.1     lukem 	for ( a = e->e_attrs; a; a = a->a_next ) {
   5536  1.1     lukem 		if ( a == oc_at ) continue;
   5537  1.1     lukem 		ct = config_find_table( colst, nocs, a->a_desc, ca );
   5538  1.1     lukem 		if ( !ct ) continue;	/* user data? */
   5539  1.1     lukem 		rc = check_vals( ct, ca, a, 1 );
   5540  1.1     lukem 		if ( rc ) goto done_noop;
   5541  1.1     lukem 	}
   5542  1.1     lukem 
   5543  1.1     lukem 	/* Basic syntax checks are OK. Do the actual settings. */
   5544  1.1     lukem 	for ( a=e->e_attrs; a; a=a->a_next ) {
   5545  1.1     lukem 		if ( a == oc_at ) continue;
   5546  1.1     lukem 		ct = config_find_table( colst, nocs, a->a_desc, ca );
   5547  1.1     lukem 		if ( !ct ) continue;	/* user data? */
   5548  1.1     lukem 		for (i=0; a->a_vals[i].bv_val; i++) {
   5549  1.1     lukem 			char *iptr = NULL;
   5550  1.2  christos 			ca->valx = -1;
   5551  1.1     lukem 			ca->line = a->a_vals[i].bv_val;
   5552  1.3  christos 			ca->linelen = a->a_vals[i].bv_len;
   5553  1.1     lukem 			if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED ) {
   5554  1.1     lukem 				ptr = strchr( ca->line, '}' );
   5555  1.1     lukem 				if ( ptr ) {
   5556  1.1     lukem 					iptr = strchr( ca->line, '{' );
   5557  1.3  christos 					ca->linelen -= (ptr+1) - ca->line;
   5558  1.1     lukem 					ca->line = ptr+1;
   5559  1.1     lukem 				}
   5560  1.1     lukem 			}
   5561  1.1     lukem 			if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED_SIB ) {
   5562  1.1     lukem 				if ( iptr ) {
   5563  1.1     lukem 					ca->valx = strtol( iptr+1, NULL, 0 );
   5564  1.1     lukem 				}
   5565  1.1     lukem 			} else {
   5566  1.1     lukem 				ca->valx = i;
   5567  1.1     lukem 			}
   5568  1.1     lukem 			rc = config_parse_add( ct, ca, i );
   5569  1.1     lukem 			if ( rc ) {
   5570  1.1     lukem 				rc = LDAP_OTHER;
   5571  1.1     lukem 				goto done;
   5572  1.1     lukem 			}
   5573  1.1     lukem 		}
   5574  1.1     lukem 	}
   5575  1.1     lukem ok:
   5576  1.1     lukem 	/* Newly added databases and overlays need to be started up */
   5577  1.1     lukem 	if ( CONFIG_ONLINE_ADD( ca )) {
   5578  1.2  christos 		if ( coptr->co_type == Cft_Database ) {
   5579  1.1     lukem 			rc = backend_startup_one( ca->be, &ca->reply );
   5580  1.1     lukem 
   5581  1.3  christos 		} else if ( coptr->co_type == Cft_Backend ) {
   5582  1.3  christos 			if ( ca->bi->bi_open ) {
   5583  1.3  christos 				rc = ca->bi->bi_open( ca->bi );
   5584  1.3  christos 			}
   5585  1.3  christos 
   5586  1.2  christos 		} else if ( coptr->co_type == Cft_Overlay ) {
   5587  1.1     lukem 			if ( ca->bi->bi_db_open ) {
   5588  1.1     lukem 				BackendInfo *bi_orig = ca->be->bd_info;
   5589  1.1     lukem 				ca->be->bd_info = ca->bi;
   5590  1.1     lukem 				rc = ca->bi->bi_db_open( ca->be, &ca->reply );
   5591  1.1     lukem 				ca->be->bd_info = bi_orig;
   5592  1.1     lukem 			}
   5593  1.3  christos 		} else if ( ca->num_cleanups ) {
   5594  1.3  christos 			rc = config_run_cleanup( ca );
   5595  1.1     lukem 		}
   5596  1.1     lukem 		if ( rc ) {
   5597  1.1     lukem 			if (ca->cr_msg[0] == '\0')
   5598  1.1     lukem 				snprintf( ca->cr_msg, sizeof( ca->cr_msg ), "<%s> failed startup", ca->argv[0] );
   5599  1.1     lukem 
   5600  1.1     lukem 			Debug(LDAP_DEBUG_ANY, "%s: %s (%s)!\n",
   5601  1.1     lukem 				ca->log, ca->cr_msg, ca->argv[1] );
   5602  1.1     lukem 			rc = LDAP_OTHER;
   5603  1.1     lukem 			goto done;
   5604  1.1     lukem 		}
   5605  1.1     lukem 	}
   5606  1.1     lukem 
   5607  1.1     lukem 	ca->valx = ibase;
   5608  1.1     lukem 	ce = ch_calloc( 1, sizeof(CfEntryInfo) );
   5609  1.1     lukem 	ce->ce_parent = last;
   5610  1.1     lukem 	ce->ce_entry = entry_dup( e );
   5611  1.1     lukem 	ce->ce_entry->e_private = ce;
   5612  1.2  christos 	ce->ce_type = coptr->co_type;
   5613  1.1     lukem 	ce->ce_be = ca->be;
   5614  1.1     lukem 	ce->ce_bi = ca->bi;
   5615  1.1     lukem 	ce->ce_private = ca->ca_private;
   5616  1.1     lukem 	ca->ca_entry = ce->ce_entry;
   5617  1.1     lukem 	if ( !last ) {
   5618  1.1     lukem 		cfb->cb_root = ce;
   5619  1.1     lukem 	} else if ( last->ce_kids ) {
   5620  1.1     lukem 		CfEntryInfo *c2, **cprev;
   5621  1.1     lukem 
   5622  1.1     lukem 		/* Advance to first of this type */
   5623  1.1     lukem 		cprev = &last->ce_kids;
   5624  1.1     lukem 		for ( c2 = *cprev; c2 && c2->ce_type < ce->ce_type; ) {
   5625  1.1     lukem 			cprev = &c2->ce_sibs;
   5626  1.1     lukem 			c2 = c2->ce_sibs;
   5627  1.1     lukem 		}
   5628  1.1     lukem 		/* Account for the (-1) frontendDB entry */
   5629  1.1     lukem 		if ( ce->ce_type == Cft_Database ) {
   5630  1.1     lukem 			if ( ca->be == frontendDB )
   5631  1.1     lukem 				ibase = 0;
   5632  1.1     lukem 			else if ( ibase != -1 )
   5633  1.1     lukem 				ibase++;
   5634  1.1     lukem 		}
   5635  1.1     lukem 		/* Append */
   5636  1.1     lukem 		if ( ibase < 0 ) {
   5637  1.1     lukem 			for (c2 = *cprev; c2 && c2->ce_type == ce->ce_type;) {
   5638  1.1     lukem 				cprev = &c2->ce_sibs;
   5639  1.1     lukem 				c2 = c2->ce_sibs;
   5640  1.1     lukem 			}
   5641  1.1     lukem 		} else {
   5642  1.1     lukem 		/* Insert */
   5643  1.1     lukem 			int i;
   5644  1.1     lukem 			for ( i=0; i<ibase; i++ ) {
   5645  1.1     lukem 				c2 = *cprev;
   5646  1.1     lukem 				cprev = &c2->ce_sibs;
   5647  1.1     lukem 			}
   5648  1.1     lukem 		}
   5649  1.1     lukem 		ce->ce_sibs = *cprev;
   5650  1.1     lukem 		*cprev = ce;
   5651  1.1     lukem 	} else {
   5652  1.1     lukem 		last->ce_kids = ce;
   5653  1.1     lukem 	}
   5654  1.1     lukem 
   5655  1.1     lukem done:
   5656  1.1     lukem 	if ( rc ) {
   5657  1.2  christos 		if ( (coptr->co_type == Cft_Database) && ca->be ) {
   5658  1.4  christos 			if ( ca->be != frontendDB && ca->be != configDB )
   5659  1.1     lukem 				backend_destroy_one( ca->be, 1 );
   5660  1.2  christos 		} else if ( (coptr->co_type == Cft_Overlay) && ca->bi ) {
   5661  1.1     lukem 			overlay_destroy_one( ca->be, (slap_overinst *)ca->bi );
   5662  1.2  christos 		} else if ( coptr->co_type == Cft_Schema ) {
   5663  1.1     lukem 			schema_destroy_one( ca, colst, nocs, last );
   5664  1.3  christos 		} else if ( ca->num_cleanups ) {
   5665  1.4  christos 			ca->reply.err = rc;
   5666  1.3  christos 			config_run_cleanup( ca );
   5667  1.1     lukem 		}
   5668  1.1     lukem 	}
   5669  1.1     lukem done_noop:
   5670  1.1     lukem 
   5671  1.1     lukem 	ch_free( ca->argv );
   5672  1.1     lukem 	if ( colst ) ch_free( colst );
   5673  1.1     lukem 	return rc;
   5674  1.1     lukem }
   5675  1.1     lukem 
   5676  1.1     lukem #define	BIGTMP	10000
   5677  1.1     lukem static int
   5678  1.1     lukem config_rename_add( Operation *op, SlapReply *rs, CfEntryInfo *ce,
   5679  1.1     lukem 	int base, int rebase, int max, int use_ldif )
   5680  1.1     lukem {
   5681  1.1     lukem 	CfEntryInfo *ce2, *ce3, *cetmp = NULL, *cerem = NULL;
   5682  1.1     lukem 	ConfigType etype = ce->ce_type;
   5683  1.1     lukem 	int count = 0, rc = 0;
   5684  1.4  christos 	char preread = op->o_preread, postread = op->o_postread;
   5685  1.1     lukem 
   5686  1.1     lukem 	/* Reverse ce list */
   5687  1.1     lukem 	for (ce2 = ce->ce_sibs;ce2;ce2 = ce3) {
   5688  1.1     lukem 		if (ce2->ce_type != etype) {
   5689  1.1     lukem 			cerem = ce2;
   5690  1.1     lukem 			break;
   5691  1.1     lukem 		}
   5692  1.1     lukem 		ce3 = ce2->ce_sibs;
   5693  1.1     lukem 		ce2->ce_sibs = cetmp;
   5694  1.1     lukem 		cetmp = ce2;
   5695  1.1     lukem 		count++;
   5696  1.1     lukem 		if ( max && count >= max ) {
   5697  1.1     lukem 			cerem = ce3;
   5698  1.1     lukem 			break;
   5699  1.1     lukem 		}
   5700  1.1     lukem 	}
   5701  1.1     lukem 
   5702  1.4  christos 	/* Suppress control generation for internal ops */
   5703  1.4  christos 	op->o_postread = SLAP_CONTROL_NONE;
   5704  1.4  christos 
   5705  1.1     lukem 	/* Move original to a temp name until increments are done */
   5706  1.1     lukem 	if ( rebase ) {
   5707  1.1     lukem 		ce->ce_entry->e_private = NULL;
   5708  1.1     lukem 		rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
   5709  1.1     lukem 			base+BIGTMP, 0, use_ldif );
   5710  1.1     lukem 		ce->ce_entry->e_private = ce;
   5711  1.1     lukem 	}
   5712  1.4  christos 	op->o_preread = SLAP_CONTROL_NONE;
   5713  1.4  christos 
   5714  1.1     lukem 	/* start incrementing */
   5715  1.1     lukem 	for (ce2=cetmp; ce2; ce2=ce3) {
   5716  1.1     lukem 		ce3 = ce2->ce_sibs;
   5717  1.1     lukem 		ce2->ce_sibs = cerem;
   5718  1.1     lukem 		cerem = ce2;
   5719  1.1     lukem 		if ( rc == 0 )
   5720  1.1     lukem 			rc = config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
   5721  1.1     lukem 				count+base, 0, use_ldif );
   5722  1.1     lukem 		count--;
   5723  1.1     lukem 	}
   5724  1.4  christos 
   5725  1.4  christos 	op->o_postread = postread;
   5726  1.1     lukem 	if ( rebase )
   5727  1.1     lukem 		rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
   5728  1.1     lukem 			base, 0, use_ldif );
   5729  1.4  christos 	op->o_preread = preread;
   5730  1.1     lukem 	return rc;
   5731  1.1     lukem }
   5732  1.1     lukem 
   5733  1.1     lukem static int
   5734  1.1     lukem config_rename_del( Operation *op, SlapReply *rs, CfEntryInfo *ce,
   5735  1.1     lukem 	CfEntryInfo *ce2, int old, int use_ldif )
   5736  1.1     lukem {
   5737  1.4  christos 	int rc, count = 0;
   5738  1.4  christos 	char preread = op->o_preread, postread = op->o_postread;
   5739  1.4  christos 
   5740  1.4  christos 	/* Suppress control generation for internal ops */
   5741  1.4  christos 	op->o_postread = SLAP_CONTROL_NONE;
   5742  1.1     lukem 
   5743  1.1     lukem 	/* Renumber original to a temp value */
   5744  1.1     lukem 	ce->ce_entry->e_private = NULL;
   5745  1.1     lukem 	config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
   5746  1.1     lukem 		old+BIGTMP, 0, use_ldif );
   5747  1.1     lukem 	ce->ce_entry->e_private = ce;
   5748  1.1     lukem 
   5749  1.4  christos 	op->o_preread = SLAP_CONTROL_NONE;
   5750  1.4  christos 
   5751  1.1     lukem 	/* start decrementing */
   5752  1.1     lukem 	for (; ce2 != ce; ce2=ce2->ce_sibs) {
   5753  1.1     lukem 		config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
   5754  1.1     lukem 			count+old, 0, use_ldif );
   5755  1.1     lukem 		count++;
   5756  1.1     lukem 	}
   5757  1.4  christos 
   5758  1.4  christos 	op->o_postread = postread;
   5759  1.4  christos 	rc = config_renumber_one( op, rs, ce->ce_parent, ce->ce_entry,
   5760  1.1     lukem 		count+old, 0, use_ldif );
   5761  1.4  christos 	op->o_preread = preread;
   5762  1.4  christos 	return rc;
   5763  1.1     lukem }
   5764  1.1     lukem 
   5765  1.1     lukem /* Parse an LDAP entry into config directives, then store in underlying
   5766  1.1     lukem  * database.
   5767  1.1     lukem  */
   5768  1.1     lukem static int
   5769  1.1     lukem config_back_add( Operation *op, SlapReply *rs )
   5770  1.1     lukem {
   5771  1.1     lukem 	CfBackInfo *cfb;
   5772  1.3  christos 	int renumber, dopause = 1;
   5773  1.1     lukem 	ConfigArgs ca;
   5774  1.1     lukem 
   5775  1.4  christos 	LDAPControl **postread_ctrl = NULL;
   5776  1.4  christos 	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
   5777  1.4  christos 	int num_ctrls = 0;
   5778  1.4  christos 	char postread = op->o_postread;
   5779  1.4  christos 
   5780  1.4  christos 	op->o_postread = SLAP_CONTROL_NONE;
   5781  1.4  christos 	ctrls[num_ctrls] = NULL;
   5782  1.4  christos 
   5783  1.1     lukem 	if ( !access_allowed( op, op->ora_e, slap_schema.si_ad_entry,
   5784  1.1     lukem 		NULL, ACL_WADD, NULL )) {
   5785  1.1     lukem 		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
   5786  1.1     lukem 		goto out;
   5787  1.1     lukem 	}
   5788  1.1     lukem 
   5789  1.2  christos 	/*
   5790  1.2  christos 	 * Check for attribute ACL
   5791  1.2  christos 	 */
   5792  1.2  christos 	if ( !acl_check_modlist( op, op->ora_e, op->orm_modlist )) {
   5793  1.2  christos 		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
   5794  1.2  christos 		rs->sr_text = "no write access to attribute";
   5795  1.2  christos 		goto out;
   5796  1.2  christos 	}
   5797  1.2  christos 
   5798  1.1     lukem 	cfb = (CfBackInfo *)op->o_bd->be_private;
   5799  1.1     lukem 
   5800  1.1     lukem 	/* add opattrs for syncprov */
   5801  1.1     lukem 	{
   5802  1.1     lukem 		char textbuf[SLAP_TEXT_BUFLEN];
   5803  1.1     lukem 		size_t textlen = sizeof textbuf;
   5804  1.2  christos 		rs->sr_err = entry_schema_check(op, op->ora_e, NULL, 0, 1, NULL,
   5805  1.1     lukem 			&rs->sr_text, textbuf, sizeof( textbuf ) );
   5806  1.1     lukem 		if ( rs->sr_err != LDAP_SUCCESS )
   5807  1.1     lukem 			goto out;
   5808  1.1     lukem 		rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
   5809  1.1     lukem 		if ( rs->sr_err != LDAP_SUCCESS ) {
   5810  1.1     lukem 			Debug( LDAP_DEBUG_TRACE,
   5811  1.1     lukem 				LDAP_XSTRING(config_back_add) ": entry failed op attrs add: "
   5812  1.3  christos 				"%s (%d)\n", rs->sr_text, rs->sr_err );
   5813  1.1     lukem 			goto out;
   5814  1.1     lukem 		}
   5815  1.1     lukem 	}
   5816  1.1     lukem 
   5817  1.4  christos 	/*
   5818  1.4  christos 	 * ITS#10045 Pre-check for abandon but be willing to handle that the
   5819  1.4  christos 	 * operation might be abandoned while waiting for the server to pause.
   5820  1.4  christos 	 */
   5821  1.2  christos 	if ( op->o_abandon ) {
   5822  1.2  christos 		rs->sr_err = SLAPD_ABANDON;
   5823  1.4  christos 		dopause = 0;
   5824  1.2  christos 		goto out;
   5825  1.2  christos 	}
   5826  1.3  christos 	if ( slap_pause_server() < 0 )
   5827  1.3  christos 		dopause = 0;
   5828  1.4  christos 	if ( op->o_abandon ) {
   5829  1.4  christos 		rs->sr_err = SLAPD_ABANDON;
   5830  1.4  christos 		goto unpause;
   5831  1.4  christos 	}
   5832  1.4  christos 
   5833  1.4  christos 	ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
   5834  1.1     lukem 
   5835  1.1     lukem 	/* Strategy:
   5836  1.1     lukem 	 * 1) check for existence of entry
   5837  1.1     lukem 	 * 2) check for sibling renumbering
   5838  1.1     lukem 	 * 3) perform internal add
   5839  1.1     lukem 	 * 4) perform any necessary renumbering
   5840  1.1     lukem 	 * 5) store entry in underlying database
   5841  1.1     lukem 	 */
   5842  1.1     lukem 	rs->sr_err = config_add_internal( cfb, op->ora_e, &ca, rs, &renumber, op );
   5843  1.1     lukem 	if ( rs->sr_err != LDAP_SUCCESS ) {
   5844  1.1     lukem 		rs->sr_text = ca.cr_msg;
   5845  1.1     lukem 		goto out2;
   5846  1.1     lukem 	}
   5847  1.1     lukem 
   5848  1.1     lukem 	if ( renumber ) {
   5849  1.1     lukem 		CfEntryInfo *ce = ca.ca_entry->e_private;
   5850  1.1     lukem 		req_add_s addr = op->oq_add;
   5851  1.1     lukem 		op->o_tag = LDAP_REQ_MODRDN;
   5852  1.1     lukem 		rs->sr_err = config_rename_add( op, rs, ce, ca.valx, 0, 0, cfb->cb_use_ldif );
   5853  1.1     lukem 		op->o_tag = LDAP_REQ_ADD;
   5854  1.1     lukem 		op->oq_add = addr;
   5855  1.1     lukem 		if ( rs->sr_err != LDAP_SUCCESS ) {
   5856  1.1     lukem 			goto out2;
   5857  1.1     lukem 		}
   5858  1.1     lukem 	}
   5859  1.1     lukem 
   5860  1.1     lukem 	if ( cfb->cb_use_ldif ) {
   5861  1.1     lukem 		BackendDB *be = op->o_bd;
   5862  1.4  christos 		slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp;
   5863  1.1     lukem 		struct berval dn, ndn;
   5864  1.1     lukem 
   5865  1.1     lukem 		op->o_bd = &cfb->cb_db;
   5866  1.1     lukem 
   5867  1.1     lukem 		/* Save current rootdn; use the underlying DB's rootdn */
   5868  1.1     lukem 		dn = op->o_dn;
   5869  1.1     lukem 		ndn = op->o_ndn;
   5870  1.1     lukem 		op->o_dn = op->o_bd->be_rootdn;
   5871  1.1     lukem 		op->o_ndn = op->o_bd->be_rootndn;
   5872  1.1     lukem 
   5873  1.1     lukem 		scp = op->o_callback;
   5874  1.1     lukem 		op->o_callback = &sc;
   5875  1.4  christos 		op->o_postread = postread;
   5876  1.4  christos 		rs->sr_ctrls = NULL;
   5877  1.4  christos 
   5878  1.1     lukem 		op->o_bd->be_add( op, rs );
   5879  1.1     lukem 		op->o_bd = be;
   5880  1.1     lukem 		op->o_callback = scp;
   5881  1.1     lukem 		op->o_dn = dn;
   5882  1.1     lukem 		op->o_ndn = ndn;
   5883  1.4  christos 
   5884  1.4  christos 		rs->sr_ctrls = sc.sc_private;
   5885  1.4  christos 		rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
   5886  1.4  christos 	} else if ( postread ) {
   5887  1.4  christos 		if ( postread_ctrl == NULL ) {
   5888  1.4  christos 			postread_ctrl = &ctrls[num_ctrls++];
   5889  1.4  christos 			ctrls[num_ctrls] = NULL;
   5890  1.4  christos 		}
   5891  1.4  christos 		if ( slap_read_controls( op, rs, op->ora_e,
   5892  1.4  christos 			&slap_post_read_bv, postread_ctrl ) )
   5893  1.4  christos 		{
   5894  1.4  christos 			Debug( LDAP_DEBUG_ANY, "config_back_add: "
   5895  1.4  christos 				"post-read failed \"%s\"\n",
   5896  1.4  christos 				op->ora_e->e_name.bv_val );
   5897  1.4  christos 			if ( op->o_postread & SLAP_CONTROL_CRITICAL ) {
   5898  1.4  christos 				/* FIXME: is it correct to abort
   5899  1.4  christos 					* operation if control fails? */
   5900  1.4  christos 			}
   5901  1.4  christos 		}
   5902  1.1     lukem 	}
   5903  1.1     lukem 
   5904  1.1     lukem out2:;
   5905  1.4  christos 	ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
   5906  1.4  christos 
   5907  1.4  christos unpause:;
   5908  1.3  christos 	if ( dopause )
   5909  1.3  christos 		slap_unpause_server();
   5910  1.1     lukem 
   5911  1.1     lukem out:;
   5912  1.2  christos 	{	int repl = op->o_dont_replicate;
   5913  1.2  christos 		if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
   5914  1.2  christos 			rs->sr_text = NULL; /* Set after config_add_internal */
   5915  1.2  christos 			rs->sr_err = LDAP_SUCCESS;
   5916  1.2  christos 			op->o_dont_replicate = 1;
   5917  1.2  christos 		}
   5918  1.2  christos 		send_ldap_result( op, rs );
   5919  1.2  christos 		op->o_dont_replicate = repl;
   5920  1.2  christos 	}
   5921  1.1     lukem 	slap_graduate_commit_csn( op );
   5922  1.1     lukem 	return rs->sr_err;
   5923  1.1     lukem }
   5924  1.1     lukem 
   5925  1.1     lukem typedef struct delrec {
   5926  1.1     lukem 	struct delrec *next;
   5927  1.1     lukem 	int nidx;
   5928  1.1     lukem 	int idx[1];
   5929  1.1     lukem } delrec;
   5930  1.1     lukem 
   5931  1.1     lukem static int
   5932  1.1     lukem config_modify_add( ConfigTable *ct, ConfigArgs *ca, AttributeDescription *ad,
   5933  1.1     lukem 	int i )
   5934  1.1     lukem {
   5935  1.1     lukem 	int rc;
   5936  1.1     lukem 
   5937  1.2  christos 	ca->valx = -1;
   5938  1.1     lukem 	if (ad->ad_type->sat_flags & SLAP_AT_ORDERED &&
   5939  1.1     lukem 		ca->line[0] == '{' )
   5940  1.1     lukem 	{
   5941  1.1     lukem 		char *ptr = strchr( ca->line + 1, '}' );
   5942  1.1     lukem 		if ( ptr ) {
   5943  1.1     lukem 			char	*next;
   5944  1.1     lukem 
   5945  1.1     lukem 			ca->valx = strtol( ca->line + 1, &next, 0 );
   5946  1.1     lukem 			if ( next == ca->line + 1 || next[ 0 ] != '}' ) {
   5947  1.1     lukem 				return LDAP_OTHER;
   5948  1.1     lukem 			}
   5949  1.3  christos 			ca->linelen -= (ptr+1) - ca->line;
   5950  1.1     lukem 			ca->line = ptr+1;
   5951  1.1     lukem 		}
   5952  1.1     lukem 	}
   5953  1.1     lukem 	rc = config_parse_add( ct, ca, i );
   5954  1.1     lukem 	if ( rc ) {
   5955  1.1     lukem 		rc = LDAP_OTHER;
   5956  1.1     lukem 	}
   5957  1.1     lukem 	return rc;
   5958  1.1     lukem }
   5959  1.1     lukem 
   5960  1.1     lukem static int
   5961  1.1     lukem config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
   5962  1.1     lukem 	ConfigArgs *ca )
   5963  1.1     lukem {
   5964  1.1     lukem 	int rc = LDAP_UNWILLING_TO_PERFORM;
   5965  1.1     lukem 	Modifications *ml;
   5966  1.1     lukem 	Entry *e = ce->ce_entry;
   5967  1.1     lukem 	Attribute *save_attrs = e->e_attrs, *oc_at, *s, *a;
   5968  1.1     lukem 	ConfigTable *ct;
   5969  1.1     lukem 	ConfigOCs **colst;
   5970  1.1     lukem 	int i, nocs;
   5971  1.1     lukem 	char *ptr;
   5972  1.1     lukem 	delrec *dels = NULL, *deltail = NULL;
   5973  1.1     lukem 
   5974  1.1     lukem 	oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
   5975  1.1     lukem 	if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
   5976  1.1     lukem 
   5977  1.2  christos 	for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
   5978  1.4  christos 		if (ml->sml_desc == slap_schema.si_ad_objectClass) {
   5979  1.4  christos 			/* We'd be fine comparing the structural objectclass before and
   5980  1.4  christos 			 * after, but AUXILIARY ocs exist so we have to check them all */
   5981  1.4  christos 			unsigned int i, j;
   5982  1.4  christos 
   5983  1.4  christos 			if ( ml->sml_numvals != oc_at->a_numvals ) {
   5984  1.4  christos 				snprintf( ca->cr_msg, sizeof(ca->cr_msg),
   5985  1.4  christos 					"objectclass modification disallowed" );
   5986  1.4  christos 				return LDAP_UNWILLING_TO_PERFORM;
   5987  1.4  christos 			}
   5988  1.4  christos 
   5989  1.4  christos 			for ( i = 0; i < oc_at->a_numvals; i++ ) {
   5990  1.4  christos 				ObjectClass *new_oc, *old_oc = oc_bvfind( &oc_at->a_vals[i] );
   5991  1.4  christos 				int found = 0;
   5992  1.4  christos 
   5993  1.4  christos 				if ( old_oc == NULL ) {
   5994  1.4  christos 					snprintf( ca->cr_msg, sizeof(ca->cr_msg),
   5995  1.4  christos 						"no objectClass named %s",
   5996  1.4  christos 						oc_at->a_vals[i].bv_val );
   5997  1.4  christos 					return LDAP_OBJECT_CLASS_VIOLATION;
   5998  1.4  christos 				}
   5999  1.4  christos 				for ( j = 0; j < ml->sml_numvals; j++ ) {
   6000  1.4  christos 					new_oc = oc_bvfind( &ml->sml_values[j] );
   6001  1.4  christos 					if ( new_oc == NULL ) {
   6002  1.4  christos 						snprintf( ca->cr_msg, sizeof(ca->cr_msg),
   6003  1.4  christos 							"no objectClass named %s",
   6004  1.4  christos 							ml->sml_values[j].bv_val );
   6005  1.4  christos 						return LDAP_OBJECT_CLASS_VIOLATION;
   6006  1.4  christos 					}
   6007  1.4  christos 
   6008  1.4  christos 					if ( old_oc == new_oc ) {
   6009  1.4  christos 						found = 1;
   6010  1.4  christos 						break;
   6011  1.4  christos 					}
   6012  1.4  christos 				}
   6013  1.4  christos 
   6014  1.4  christos 				if ( !found ) {
   6015  1.4  christos 					snprintf( ca->cr_msg, sizeof(ca->cr_msg),
   6016  1.4  christos 						"objectclass modification disallowed" );
   6017  1.4  christos 					return LDAP_UNWILLING_TO_PERFORM;
   6018  1.4  christos 				}
   6019  1.4  christos 			}
   6020  1.4  christos 		}
   6021  1.2  christos 	}
   6022  1.2  christos 
   6023  1.1     lukem 	colst = count_ocs( oc_at, &nocs );
   6024  1.1     lukem 
   6025  1.1     lukem 	/* make sure add/del flags are clear; should always be true */
   6026  1.1     lukem 	for ( s = save_attrs; s; s = s->a_next ) {
   6027  1.1     lukem 		s->a_flags &= ~(SLAP_ATTR_IXADD|SLAP_ATTR_IXDEL);
   6028  1.1     lukem 	}
   6029  1.1     lukem 
   6030  1.1     lukem 	e->e_attrs = attrs_dup( e->e_attrs );
   6031  1.1     lukem 
   6032  1.1     lukem 	init_config_argv( ca );
   6033  1.1     lukem 	ca->be = ce->ce_be;
   6034  1.1     lukem 	ca->bi = ce->ce_bi;
   6035  1.1     lukem 	ca->ca_private = ce->ce_private;
   6036  1.1     lukem 	ca->ca_entry = e;
   6037  1.1     lukem 	ca->fname = "slapd";
   6038  1.1     lukem 	ca->ca_op = op;
   6039  1.1     lukem 	strcpy( ca->log, "back-config" );
   6040  1.1     lukem 
   6041  1.1     lukem 	for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
   6042  1.1     lukem 		ct = config_find_table( colst, nocs, ml->sml_desc, ca );
   6043  1.1     lukem 		switch (ml->sml_op) {
   6044  1.1     lukem 		case LDAP_MOD_DELETE:
   6045  1.2  christos 		case LDAP_MOD_REPLACE:
   6046  1.2  christos 		case SLAP_MOD_SOFTDEL:
   6047  1.2  christos 		{
   6048  1.1     lukem 			BerVarray vals = NULL, nvals = NULL;
   6049  1.1     lukem 			int *idx = NULL;
   6050  1.1     lukem 			if ( ct && ( ct->arg_type & ARG_NO_DELETE )) {
   6051  1.1     lukem 				rc = LDAP_OTHER;
   6052  1.1     lukem 				snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot delete %s",
   6053  1.1     lukem 					ml->sml_desc->ad_cname.bv_val );
   6054  1.1     lukem 				goto out_noop;
   6055  1.1     lukem 			}
   6056  1.1     lukem 			if ( ml->sml_op == LDAP_MOD_REPLACE ) {
   6057  1.1     lukem 				vals = ml->sml_values;
   6058  1.1     lukem 				nvals = ml->sml_nvalues;
   6059  1.1     lukem 				ml->sml_values = NULL;
   6060  1.1     lukem 				ml->sml_nvalues = NULL;
   6061  1.1     lukem 			}
   6062  1.1     lukem 			/* If we're deleting by values, remember the indexes of the
   6063  1.1     lukem 			 * values we deleted.
   6064  1.1     lukem 			 */
   6065  1.1     lukem 			if ( ct && ml->sml_values ) {
   6066  1.1     lukem 				delrec *d;
   6067  1.1     lukem 				i = ml->sml_numvals;
   6068  1.1     lukem 				d = ch_malloc( sizeof(delrec) + (i - 1)* sizeof(int));
   6069  1.1     lukem 				d->nidx = i;
   6070  1.1     lukem 				d->next = NULL;
   6071  1.1     lukem 				if ( dels ) {
   6072  1.1     lukem 					deltail->next = d;
   6073  1.1     lukem 				} else {
   6074  1.1     lukem 					dels = d;
   6075  1.1     lukem 				}
   6076  1.1     lukem 				deltail = d;
   6077  1.1     lukem 				idx = d->idx;
   6078  1.1     lukem 			}
   6079  1.1     lukem 			rc = modify_delete_vindex(e, &ml->sml_mod,
   6080  1.1     lukem 				get_permissiveModify(op),
   6081  1.1     lukem 				&rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg), idx );
   6082  1.1     lukem 			if ( ml->sml_op == LDAP_MOD_REPLACE ) {
   6083  1.1     lukem 				ml->sml_values = vals;
   6084  1.1     lukem 				ml->sml_nvalues = nvals;
   6085  1.1     lukem 			}
   6086  1.2  christos 			if ( rc == LDAP_NO_SUCH_ATTRIBUTE && ml->sml_op == SLAP_MOD_SOFTDEL )
   6087  1.2  christos 			{
   6088  1.2  christos 				rc = LDAP_SUCCESS;
   6089  1.2  christos 			}
   6090  1.2  christos 			/* FIXME: check rc before fallthru? */
   6091  1.1     lukem 			if ( !vals )
   6092  1.1     lukem 				break;
   6093  1.2  christos 		}
   6094  1.2  christos 			/* FALLTHRU: LDAP_MOD_REPLACE && vals */
   6095  1.2  christos 
   6096  1.2  christos 		case SLAP_MOD_ADD_IF_NOT_PRESENT:
   6097  1.2  christos 			if ( ml->sml_op == SLAP_MOD_ADD_IF_NOT_PRESENT
   6098  1.2  christos 				&& attr_find( e->e_attrs, ml->sml_desc ) )
   6099  1.2  christos 			{
   6100  1.2  christos 				rc = LDAP_SUCCESS;
   6101  1.2  christos 				break;
   6102  1.1     lukem 			}
   6103  1.1     lukem 
   6104  1.1     lukem 		case LDAP_MOD_ADD:
   6105  1.1     lukem 		case SLAP_MOD_SOFTADD: {
   6106  1.1     lukem 			int mop = ml->sml_op;
   6107  1.1     lukem 			int navals = -1;
   6108  1.1     lukem 			ml->sml_op = LDAP_MOD_ADD;
   6109  1.1     lukem 			if ( ct ) {
   6110  1.1     lukem 				if ( ct->arg_type & ARG_NO_INSERT ) {
   6111  1.1     lukem 					Attribute *a = attr_find( e->e_attrs, ml->sml_desc );
   6112  1.1     lukem 					if ( a ) {
   6113  1.1     lukem 						navals = a->a_numvals;
   6114  1.1     lukem 					}
   6115  1.1     lukem 				}
   6116  1.1     lukem 				for ( i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++ ) {
   6117  1.1     lukem 					if ( ml->sml_values[i].bv_val[0] == '{' &&
   6118  1.1     lukem 						navals >= 0 )
   6119  1.1     lukem 					{
   6120  1.1     lukem 						char	*next, *val = ml->sml_values[i].bv_val + 1;
   6121  1.1     lukem 						int	j;
   6122  1.1     lukem 
   6123  1.1     lukem 						j = strtol( val, &next, 0 );
   6124  1.1     lukem 						if ( next == val || next[ 0 ] != '}' || j < navals ) {
   6125  1.1     lukem 							rc = LDAP_OTHER;
   6126  1.1     lukem 							snprintf(ca->cr_msg, sizeof(ca->cr_msg), "cannot insert %s",
   6127  1.1     lukem 								ml->sml_desc->ad_cname.bv_val );
   6128  1.1     lukem 							goto out_noop;
   6129  1.1     lukem 						}
   6130  1.1     lukem 					}
   6131  1.1     lukem 					rc = check_vals( ct, ca, ml, 0 );
   6132  1.1     lukem 					if ( rc ) goto out_noop;
   6133  1.1     lukem 				}
   6134  1.1     lukem 			}
   6135  1.1     lukem 			rc = modify_add_values(e, &ml->sml_mod,
   6136  1.1     lukem 				   get_permissiveModify(op),
   6137  1.1     lukem 				   &rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) );
   6138  1.1     lukem 
   6139  1.1     lukem 			/* If value already exists, show success here
   6140  1.1     lukem 			 * and ignore this operation down below.
   6141  1.1     lukem 			 */
   6142  1.1     lukem 			if ( mop == SLAP_MOD_SOFTADD ) {
   6143  1.1     lukem 				if ( rc == LDAP_TYPE_OR_VALUE_EXISTS )
   6144  1.1     lukem 					rc = LDAP_SUCCESS;
   6145  1.1     lukem 				else
   6146  1.1     lukem 					mop = LDAP_MOD_ADD;
   6147  1.1     lukem 			}
   6148  1.1     lukem 			ml->sml_op = mop;
   6149  1.1     lukem 			break;
   6150  1.1     lukem 			}
   6151  1.1     lukem 
   6152  1.1     lukem 			break;
   6153  1.1     lukem 		case LDAP_MOD_INCREMENT:	/* FIXME */
   6154  1.1     lukem 			break;
   6155  1.1     lukem 		default:
   6156  1.1     lukem 			break;
   6157  1.1     lukem 		}
   6158  1.1     lukem 		if(rc != LDAP_SUCCESS) break;
   6159  1.1     lukem 	}
   6160  1.1     lukem 
   6161  1.1     lukem 	if ( rc == LDAP_SUCCESS) {
   6162  1.1     lukem 		/* check that the entry still obeys the schema */
   6163  1.2  christos 		rc = entry_schema_check(op, e, NULL, 0, 0, NULL,
   6164  1.1     lukem 			&rs->sr_text, ca->cr_msg, sizeof(ca->cr_msg) );
   6165  1.1     lukem 	}
   6166  1.1     lukem 	if ( rc ) goto out_noop;
   6167  1.1     lukem 
   6168  1.1     lukem 	/* Basic syntax checks are OK. Do the actual settings. */
   6169  1.1     lukem 	for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
   6170  1.1     lukem 		ct = config_find_table( colst, nocs, ml->sml_desc, ca );
   6171  1.1     lukem 		if ( !ct ) continue;
   6172  1.1     lukem 
   6173  1.1     lukem 		s = attr_find( save_attrs, ml->sml_desc );
   6174  1.1     lukem 		a = attr_find( e->e_attrs, ml->sml_desc );
   6175  1.1     lukem 
   6176  1.1     lukem 		switch (ml->sml_op) {
   6177  1.1     lukem 		case LDAP_MOD_DELETE:
   6178  1.1     lukem 		case LDAP_MOD_REPLACE: {
   6179  1.1     lukem 			BerVarray vals = NULL, nvals = NULL;
   6180  1.1     lukem 			delrec *d = NULL;
   6181  1.1     lukem 
   6182  1.1     lukem 			if ( ml->sml_op == LDAP_MOD_REPLACE ) {
   6183  1.1     lukem 				vals = ml->sml_values;
   6184  1.1     lukem 				nvals = ml->sml_nvalues;
   6185  1.1     lukem 				ml->sml_values = NULL;
   6186  1.1     lukem 				ml->sml_nvalues = NULL;
   6187  1.1     lukem 			}
   6188  1.1     lukem 
   6189  1.1     lukem 			if ( ml->sml_values )
   6190  1.1     lukem 				d = dels;
   6191  1.1     lukem 
   6192  1.1     lukem 			/* If we didn't delete the whole attribute */
   6193  1.1     lukem 			if ( ml->sml_values && a ) {
   6194  1.1     lukem 				struct berval *mvals;
   6195  1.1     lukem 				int j;
   6196  1.1     lukem 
   6197  1.1     lukem 				if ( ml->sml_nvalues )
   6198  1.1     lukem 					mvals = ml->sml_nvalues;
   6199  1.1     lukem 				else
   6200  1.1     lukem 					mvals = ml->sml_values;
   6201  1.1     lukem 
   6202  1.1     lukem 				/* use the indexes we saved up above */
   6203  1.1     lukem 				for (i=0; i < d->nidx; i++) {
   6204  1.1     lukem 					struct berval bv = *mvals++;
   6205  1.1     lukem 					if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
   6206  1.1     lukem 						bv.bv_val[0] == '{' ) {
   6207  1.1     lukem 						ptr = strchr( bv.bv_val, '}' ) + 1;
   6208  1.1     lukem 						bv.bv_len -= ptr - bv.bv_val;
   6209  1.1     lukem 						bv.bv_val = ptr;
   6210  1.1     lukem 					}
   6211  1.1     lukem 					ca->line = bv.bv_val;
   6212  1.3  christos 					ca->linelen = bv.bv_len;
   6213  1.1     lukem 					ca->valx = d->idx[i];
   6214  1.2  christos 					config_parse_vals(ct, ca, d->idx[i] );
   6215  1.1     lukem 					rc = config_del_vals( ct, ca );
   6216  1.1     lukem 					if ( rc != LDAP_SUCCESS ) break;
   6217  1.1     lukem 					if ( s )
   6218  1.1     lukem 						s->a_flags |= SLAP_ATTR_IXDEL;
   6219  1.1     lukem 					for (j=i+1; j < d->nidx; j++)
   6220  1.1     lukem 						if ( d->idx[j] >d->idx[i] )
   6221  1.1     lukem 							d->idx[j]--;
   6222  1.1     lukem 				}
   6223  1.1     lukem 			} else {
   6224  1.1     lukem 				ca->valx = -1;
   6225  1.1     lukem 				ca->line = NULL;
   6226  1.2  christos 				ca->argc = 1;
   6227  1.1     lukem 				rc = config_del_vals( ct, ca );
   6228  1.1     lukem 				if ( rc ) rc = LDAP_OTHER;
   6229  1.1     lukem 				if ( s )
   6230  1.1     lukem 					s->a_flags |= SLAP_ATTR_IXDEL;
   6231  1.1     lukem 			}
   6232  1.1     lukem 			if ( ml->sml_values ) {
   6233  1.1     lukem 				d = d->next;
   6234  1.1     lukem 				ch_free( dels );
   6235  1.1     lukem 				dels = d;
   6236  1.1     lukem 			}
   6237  1.1     lukem 			if ( ml->sml_op == LDAP_MOD_REPLACE ) {
   6238  1.1     lukem 				ml->sml_values = vals;
   6239  1.1     lukem 				ml->sml_nvalues = nvals;
   6240  1.1     lukem 			}
   6241  1.1     lukem 			if ( !vals || rc != LDAP_SUCCESS )
   6242  1.1     lukem 				break;
   6243  1.1     lukem 			}
   6244  1.1     lukem 			/* FALLTHRU: LDAP_MOD_REPLACE && vals */
   6245  1.1     lukem 
   6246  1.1     lukem 		case LDAP_MOD_ADD:
   6247  1.2  christos 			if ( !a )
   6248  1.2  christos 				break;
   6249  1.1     lukem 			for (i=0; ml->sml_values[i].bv_val; i++) {
   6250  1.1     lukem 				ca->line = ml->sml_values[i].bv_val;
   6251  1.3  christos 				ca->linelen = ml->sml_values[i].bv_len;
   6252  1.1     lukem 				ca->valx = -1;
   6253  1.1     lukem 				rc = config_modify_add( ct, ca, ml->sml_desc, i );
   6254  1.1     lukem 				if ( rc )
   6255  1.1     lukem 					goto out;
   6256  1.1     lukem 				a->a_flags |= SLAP_ATTR_IXADD;
   6257  1.1     lukem 			}
   6258  1.1     lukem 			break;
   6259  1.1     lukem 		}
   6260  1.1     lukem 	}
   6261  1.1     lukem 
   6262  1.4  christos 	/* Apply pending changes */
   6263  1.4  christos 	if ( rc == LDAP_SUCCESS && ca->num_cleanups ) {
   6264  1.4  christos 		rc = config_run_cleanup( ca );
   6265  1.4  christos 	}
   6266  1.4  christos 
   6267  1.1     lukem out:
   6268  1.1     lukem 	/* Undo for a failed operation */
   6269  1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   6270  1.1     lukem 		ConfigReply msg = ca->reply;
   6271  1.1     lukem 		for ( s = save_attrs; s; s = s->a_next ) {
   6272  1.1     lukem 			if ( s->a_flags & SLAP_ATTR_IXDEL ) {
   6273  1.1     lukem 				s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
   6274  1.1     lukem 				ct = config_find_table( colst, nocs, s->a_desc, ca );
   6275  1.1     lukem 				a = attr_find( e->e_attrs, s->a_desc );
   6276  1.1     lukem 				if ( a ) {
   6277  1.1     lukem 					/* clear the flag so the add check below will skip it */
   6278  1.1     lukem 					a->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
   6279  1.1     lukem 					ca->valx = -1;
   6280  1.1     lukem 					ca->line = NULL;
   6281  1.2  christos 					ca->argc = 1;
   6282  1.1     lukem 					config_del_vals( ct, ca );
   6283  1.1     lukem 				}
   6284  1.1     lukem 				for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) {
   6285  1.1     lukem 					ca->line = s->a_vals[i].bv_val;
   6286  1.3  christos 					ca->linelen = s->a_vals[i].bv_len;
   6287  1.1     lukem 					ca->valx = -1;
   6288  1.1     lukem 					config_modify_add( ct, ca, s->a_desc, i );
   6289  1.1     lukem 				}
   6290  1.1     lukem 			}
   6291  1.1     lukem 		}
   6292  1.1     lukem 		for ( a = e->e_attrs; a; a = a->a_next ) {
   6293  1.1     lukem 			if ( a->a_flags & SLAP_ATTR_IXADD ) {
   6294  1.1     lukem 				ct = config_find_table( colst, nocs, a->a_desc, ca );
   6295  1.1     lukem 				ca->valx = -1;
   6296  1.1     lukem 				ca->line = NULL;
   6297  1.2  christos 				ca->argc = 1;
   6298  1.1     lukem 				config_del_vals( ct, ca );
   6299  1.1     lukem 				s = attr_find( save_attrs, a->a_desc );
   6300  1.1     lukem 				if ( s ) {
   6301  1.1     lukem 					s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
   6302  1.1     lukem 					for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) {
   6303  1.1     lukem 						ca->line = s->a_vals[i].bv_val;
   6304  1.3  christos 						ca->linelen = s->a_vals[i].bv_len;
   6305  1.1     lukem 						ca->valx = -1;
   6306  1.1     lukem 						config_modify_add( ct, ca, s->a_desc, i );
   6307  1.1     lukem 					}
   6308  1.1     lukem 				}
   6309  1.1     lukem 			}
   6310  1.1     lukem 		}
   6311  1.4  christos 		if ( ca->num_cleanups ) {
   6312  1.4  christos 			ca->reply.err = rc;
   6313  1.4  christos 			config_run_cleanup( ca );
   6314  1.4  christos 		}
   6315  1.1     lukem 		ca->reply = msg;
   6316  1.1     lukem 	}
   6317  1.1     lukem out_noop:
   6318  1.1     lukem 	if ( rc == LDAP_SUCCESS ) {
   6319  1.1     lukem 		attrs_free( save_attrs );
   6320  1.2  christos 		rs->sr_text = NULL;
   6321  1.1     lukem 	} else {
   6322  1.1     lukem 		attrs_free( e->e_attrs );
   6323  1.1     lukem 		e->e_attrs = save_attrs;
   6324  1.1     lukem 	}
   6325  1.1     lukem 	ch_free( ca->argv );
   6326  1.1     lukem 	if ( colst ) ch_free( colst );
   6327  1.1     lukem 	while( dels ) {
   6328  1.1     lukem 		deltail = dels->next;
   6329  1.1     lukem 		ch_free( dels );
   6330  1.1     lukem 		dels = deltail;
   6331  1.1     lukem 	}
   6332  1.1     lukem 
   6333  1.1     lukem 	return rc;
   6334  1.1     lukem }
   6335  1.1     lukem 
   6336  1.1     lukem static int
   6337  1.1     lukem config_back_modify( Operation *op, SlapReply *rs )
   6338  1.1     lukem {
   6339  1.1     lukem 	CfBackInfo *cfb;
   6340  1.4  christos 	CfEntryInfo *ce, *last = NULL;
   6341  1.1     lukem 	Modifications *ml;
   6342  1.1     lukem 	ConfigArgs ca = {0};
   6343  1.1     lukem 	struct berval rdn;
   6344  1.1     lukem 	char *ptr;
   6345  1.1     lukem 	AttributeDescription *rad = NULL;
   6346  1.1     lukem 	int do_pause = 1;
   6347  1.1     lukem 
   6348  1.4  christos 	LDAPControl **preread_ctrl = NULL;
   6349  1.4  christos 	LDAPControl **postread_ctrl = NULL;
   6350  1.4  christos 	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
   6351  1.4  christos 	int num_ctrls = 0;
   6352  1.4  christos 
   6353  1.4  christos 	ctrls[num_ctrls] = NULL;
   6354  1.4  christos 
   6355  1.1     lukem 	cfb = (CfBackInfo *)op->o_bd->be_private;
   6356  1.1     lukem 
   6357  1.4  christos 	ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
   6358  1.1     lukem 	if ( !ce ) {
   6359  1.1     lukem 		if ( last )
   6360  1.1     lukem 			rs->sr_matched = last->ce_entry->e_name.bv_val;
   6361  1.1     lukem 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
   6362  1.1     lukem 		goto out;
   6363  1.1     lukem 	}
   6364  1.1     lukem 
   6365  1.4  christos 	/* global schema rejects all writes */
   6366  1.4  christos 	if ( ce->ce_type == Cft_Schema && ce->ce_parent->ce_type == Cft_Global ) {
   6367  1.4  christos 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6368  1.4  christos 		goto out;
   6369  1.4  christos 	}
   6370  1.4  christos 
   6371  1.1     lukem 	if ( !acl_check_modlist( op, ce->ce_entry, op->orm_modlist )) {
   6372  1.1     lukem 		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
   6373  1.1     lukem 		goto out;
   6374  1.1     lukem 	}
   6375  1.1     lukem 
   6376  1.1     lukem 	/* Get type of RDN */
   6377  1.1     lukem 	rdn = ce->ce_entry->e_nname;
   6378  1.1     lukem 	ptr = strchr( rdn.bv_val, '=' );
   6379  1.1     lukem 	rdn.bv_len = ptr - rdn.bv_val;
   6380  1.2  christos 	rs->sr_err = slap_bv2ad( &rdn, &rad, &rs->sr_text );
   6381  1.2  christos 	if ( rs->sr_err != LDAP_SUCCESS ) {
   6382  1.2  christos 		goto out;
   6383  1.2  christos 	}
   6384  1.1     lukem 
   6385  1.1     lukem 	/* Some basic validation... */
   6386  1.1     lukem 	for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
   6387  1.1     lukem 		/* Don't allow Modify of RDN; must use ModRdn for that. */
   6388  1.1     lukem 		if ( ml->sml_desc == rad ) {
   6389  1.1     lukem 			rs->sr_err = LDAP_NOT_ALLOWED_ON_RDN;
   6390  1.1     lukem 			rs->sr_text = "Use modrdn to change the entry name";
   6391  1.1     lukem 			goto out;
   6392  1.1     lukem 		}
   6393  1.1     lukem 		/* Internal update of contextCSN? */
   6394  1.1     lukem 		if ( ml->sml_desc == slap_schema.si_ad_contextCSN && op->o_conn->c_conn_idx == -1 ) {
   6395  1.1     lukem 			do_pause = 0;
   6396  1.1     lukem 			break;
   6397  1.1     lukem 		}
   6398  1.1     lukem 	}
   6399  1.1     lukem 
   6400  1.1     lukem 	slap_mods_opattrs( op, &op->orm_modlist, 1 );
   6401  1.1     lukem 
   6402  1.4  christos 	/* If we have a backend, it will handle the control */
   6403  1.4  christos 	if ( !cfb->cb_use_ldif && op->o_preread ) {
   6404  1.4  christos 		if ( preread_ctrl == NULL ) {
   6405  1.4  christos 			preread_ctrl = &ctrls[num_ctrls++];
   6406  1.4  christos 			ctrls[num_ctrls] = NULL;
   6407  1.4  christos 		}
   6408  1.4  christos 		if ( slap_read_controls( op, rs, ce->ce_entry,
   6409  1.4  christos 					&slap_pre_read_bv, preread_ctrl ) )
   6410  1.4  christos 		{
   6411  1.4  christos 			Debug( LDAP_DEBUG_ANY, "config_back_modify: "
   6412  1.4  christos 					"pre-read failed \"%s\"\n",
   6413  1.4  christos 					ce->ce_entry->e_name.bv_val );
   6414  1.4  christos 			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
   6415  1.4  christos 				/* FIXME: is it correct to abort
   6416  1.4  christos 				 * operation if control fails? */
   6417  1.4  christos 				goto out;
   6418  1.4  christos 			}
   6419  1.4  christos 		}
   6420  1.4  christos 	}
   6421  1.4  christos 
   6422  1.2  christos 	if ( do_pause ) {
   6423  1.4  christos 		/*
   6424  1.4  christos 		 * ITS#10045 Pre-check for abandon but be willing to handle that the
   6425  1.4  christos 		 * operation might be abandoned while waiting for the server to pause.
   6426  1.4  christos 		 */
   6427  1.2  christos 		if ( op->o_abandon ) {
   6428  1.2  christos 			rs->sr_err = SLAPD_ABANDON;
   6429  1.4  christos 			do_pause = 0;
   6430  1.2  christos 			goto out;
   6431  1.2  christos 		}
   6432  1.3  christos 		if ( slap_pause_server() < 0 )
   6433  1.3  christos 			do_pause = 0;
   6434  1.4  christos 		if ( op->o_abandon ) {
   6435  1.4  christos 			rs->sr_err = SLAPD_ABANDON;
   6436  1.4  christos 			goto unpause;
   6437  1.4  christos 		}
   6438  1.2  christos 	}
   6439  1.4  christos 	ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
   6440  1.1     lukem 
   6441  1.1     lukem 	/* Strategy:
   6442  1.1     lukem 	 * 1) perform the Modify on the cached Entry.
   6443  1.1     lukem 	 * 2) verify that the Entry still satisfies the schema.
   6444  1.1     lukem 	 * 3) perform the individual config operations.
   6445  1.1     lukem 	 * 4) store Modified entry in underlying LDIF backend.
   6446  1.1     lukem 	 */
   6447  1.1     lukem 	rs->sr_err = config_modify_internal( ce, op, rs, &ca );
   6448  1.1     lukem 	if ( rs->sr_err ) {
   6449  1.1     lukem 		rs->sr_text = ca.cr_msg;
   6450  1.1     lukem 	} else if ( cfb->cb_use_ldif ) {
   6451  1.1     lukem 		BackendDB *be = op->o_bd;
   6452  1.4  christos 		slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp;
   6453  1.1     lukem 		struct berval dn, ndn;
   6454  1.1     lukem 
   6455  1.1     lukem 		op->o_bd = &cfb->cb_db;
   6456  1.1     lukem 
   6457  1.1     lukem 		dn = op->o_dn;
   6458  1.1     lukem 		ndn = op->o_ndn;
   6459  1.1     lukem 		op->o_dn = op->o_bd->be_rootdn;
   6460  1.1     lukem 		op->o_ndn = op->o_bd->be_rootndn;
   6461  1.1     lukem 
   6462  1.1     lukem 		scp = op->o_callback;
   6463  1.1     lukem 		op->o_callback = &sc;
   6464  1.4  christos 		rs->sr_ctrls = NULL;
   6465  1.4  christos 
   6466  1.1     lukem 		op->o_bd->be_modify( op, rs );
   6467  1.1     lukem 		op->o_bd = be;
   6468  1.1     lukem 		op->o_callback = scp;
   6469  1.1     lukem 		op->o_dn = dn;
   6470  1.1     lukem 		op->o_ndn = ndn;
   6471  1.4  christos 
   6472  1.4  christos 		rs->sr_ctrls = sc.sc_private;
   6473  1.4  christos 		rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
   6474  1.4  christos 	} else if ( op->o_postread ) {
   6475  1.4  christos 		if ( postread_ctrl == NULL ) {
   6476  1.4  christos 			postread_ctrl = &ctrls[num_ctrls++];
   6477  1.4  christos 			ctrls[num_ctrls] = NULL;
   6478  1.4  christos 		}
   6479  1.4  christos 		if ( slap_read_controls( op, rs, ce->ce_entry,
   6480  1.4  christos 			&slap_post_read_bv, postread_ctrl ) )
   6481  1.4  christos 		{
   6482  1.4  christos 			Debug( LDAP_DEBUG_ANY, "config_back_modify: "
   6483  1.4  christos 				"post-read failed \"%s\"\n",
   6484  1.4  christos 				ce->ce_entry->e_name.bv_val );
   6485  1.4  christos 		}
   6486  1.1     lukem 	}
   6487  1.1     lukem 
   6488  1.4  christos 	ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
   6489  1.4  christos unpause:;
   6490  1.1     lukem 	if ( do_pause )
   6491  1.3  christos 		slap_unpause_server();
   6492  1.1     lukem out:
   6493  1.4  christos 	if ( num_ctrls ) rs->sr_ctrls = ctrls;
   6494  1.1     lukem 	send_ldap_result( op, rs );
   6495  1.1     lukem 	slap_graduate_commit_csn( op );
   6496  1.1     lukem 	return rs->sr_err;
   6497  1.1     lukem }
   6498  1.1     lukem 
   6499  1.1     lukem static int
   6500  1.1     lukem config_back_modrdn( Operation *op, SlapReply *rs )
   6501  1.1     lukem {
   6502  1.1     lukem 	CfBackInfo *cfb;
   6503  1.4  christos 	CfEntryInfo *ce, *last = NULL;
   6504  1.1     lukem 	struct berval rdn;
   6505  1.3  christos 	int ixold, ixnew, dopause = 1;
   6506  1.1     lukem 
   6507  1.4  christos 	LDAPControl **preread_ctrl = NULL;
   6508  1.4  christos 	LDAPControl **postread_ctrl = NULL;
   6509  1.4  christos 	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
   6510  1.4  christos 	int num_ctrls = 0;
   6511  1.4  christos 	char preread = op->o_preread, postread = op->o_postread;
   6512  1.4  christos 
   6513  1.4  christos 	ctrls[num_ctrls] = NULL;
   6514  1.4  christos 	op->o_preread = op->o_postread = SLAP_CONTROL_NONE;
   6515  1.4  christos 
   6516  1.1     lukem 	cfb = (CfBackInfo *)op->o_bd->be_private;
   6517  1.1     lukem 
   6518  1.4  christos 	ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
   6519  1.1     lukem 	if ( !ce ) {
   6520  1.1     lukem 		if ( last )
   6521  1.1     lukem 			rs->sr_matched = last->ce_entry->e_name.bv_val;
   6522  1.1     lukem 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
   6523  1.1     lukem 		goto out;
   6524  1.1     lukem 	}
   6525  1.1     lukem 	if ( !access_allowed( op, ce->ce_entry, slap_schema.si_ad_entry,
   6526  1.1     lukem 		NULL, ACL_WRITE, NULL )) {
   6527  1.1     lukem 		rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
   6528  1.1     lukem 		goto out;
   6529  1.1     lukem 	}
   6530  1.1     lukem 	{ Entry *parent;
   6531  1.1     lukem 		if ( ce->ce_parent )
   6532  1.1     lukem 			parent = ce->ce_parent->ce_entry;
   6533  1.1     lukem 		else
   6534  1.1     lukem 			parent = (Entry *)&slap_entry_root;
   6535  1.1     lukem 		if ( !access_allowed( op, parent, slap_schema.si_ad_children,
   6536  1.1     lukem 			NULL, ACL_WRITE, NULL )) {
   6537  1.1     lukem 			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
   6538  1.1     lukem 			goto out;
   6539  1.1     lukem 		}
   6540  1.1     lukem 	}
   6541  1.1     lukem 
   6542  1.1     lukem 	/* We don't allow moving objects to new parents.
   6543  1.1     lukem 	 * Generally we only allow reordering a set of ordered entries.
   6544  1.1     lukem 	 */
   6545  1.1     lukem 	if ( op->orr_newSup ) {
   6546  1.1     lukem 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6547  1.1     lukem 		goto out;
   6548  1.1     lukem 	}
   6549  1.1     lukem 
   6550  1.1     lukem 	/* If newRDN == oldRDN, quietly succeed */
   6551  1.1     lukem 	dnRdn( &op->o_req_ndn, &rdn );
   6552  1.1     lukem 	if ( dn_match( &rdn, &op->orr_nnewrdn )) {
   6553  1.1     lukem 		rs->sr_err = LDAP_SUCCESS;
   6554  1.1     lukem 		goto out;
   6555  1.1     lukem 	}
   6556  1.1     lukem 
   6557  1.1     lukem 	/* Current behavior, subject to change as needed:
   6558  1.1     lukem 	 *
   6559  1.1     lukem 	 * For backends and overlays, we only allow renumbering.
   6560  1.1     lukem 	 * For schema, we allow renaming with the same number.
   6561  1.1     lukem 	 * Otherwise, the op is not allowed.
   6562  1.1     lukem 	 */
   6563  1.1     lukem 
   6564  1.1     lukem 	if ( ce->ce_type == Cft_Schema ) {
   6565  1.1     lukem 		char *ptr1, *ptr2;
   6566  1.1     lukem 		int len;
   6567  1.1     lukem 
   6568  1.1     lukem 		/* Can't alter the main cn=schema entry */
   6569  1.1     lukem 		if ( ce->ce_parent->ce_type == Cft_Global ) {
   6570  1.1     lukem 			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6571  1.1     lukem 			rs->sr_text = "renaming not allowed for this entry";
   6572  1.1     lukem 			goto out;
   6573  1.1     lukem 		}
   6574  1.1     lukem 
   6575  1.1     lukem 		/* We could support this later if desired */
   6576  1.1     lukem 		ptr1 = ber_bvchr( &rdn, '}' );
   6577  1.1     lukem 		ptr2 = ber_bvchr( &op->orr_newrdn, '}' );
   6578  1.1     lukem 		len = ptr1 - rdn.bv_val;
   6579  1.1     lukem 		if ( len != ptr2 - op->orr_newrdn.bv_val ||
   6580  1.1     lukem 			strncmp( rdn.bv_val, op->orr_newrdn.bv_val, len )) {
   6581  1.1     lukem 			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6582  1.1     lukem 			rs->sr_text = "schema reordering not supported";
   6583  1.1     lukem 			goto out;
   6584  1.1     lukem 		}
   6585  1.1     lukem 	} else if ( ce->ce_type == Cft_Database ||
   6586  1.1     lukem 		ce->ce_type == Cft_Overlay ) {
   6587  1.1     lukem 		char *ptr1, *ptr2, *iptr1, *iptr2;
   6588  1.1     lukem 		int len1, len2;
   6589  1.1     lukem 
   6590  1.1     lukem 		iptr2 = ber_bvchr( &op->orr_newrdn, '=' ) + 1;
   6591  1.1     lukem 		if ( *iptr2 != '{' ) {
   6592  1.1     lukem 			rs->sr_err = LDAP_NAMING_VIOLATION;
   6593  1.1     lukem 			rs->sr_text = "new ordering index is required";
   6594  1.1     lukem 			goto out;
   6595  1.1     lukem 		}
   6596  1.1     lukem 		iptr2++;
   6597  1.1     lukem 		iptr1 = ber_bvchr( &rdn, '{' ) + 1;
   6598  1.1     lukem 		ptr1 = ber_bvchr( &rdn, '}' );
   6599  1.1     lukem 		ptr2 = ber_bvchr( &op->orr_newrdn, '}' );
   6600  1.1     lukem 		if ( !ptr2 ) {
   6601  1.1     lukem 			rs->sr_err = LDAP_NAMING_VIOLATION;
   6602  1.1     lukem 			rs->sr_text = "new ordering index is required";
   6603  1.1     lukem 			goto out;
   6604  1.1     lukem 		}
   6605  1.1     lukem 
   6606  1.1     lukem 		len1 = ptr1 - rdn.bv_val;
   6607  1.1     lukem 		len2 = ptr2 - op->orr_newrdn.bv_val;
   6608  1.1     lukem 
   6609  1.1     lukem 		if ( rdn.bv_len - len1 != op->orr_newrdn.bv_len - len2 ||
   6610  1.1     lukem 			strncmp( ptr1, ptr2, rdn.bv_len - len1 )) {
   6611  1.1     lukem 			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6612  1.1     lukem 			rs->sr_text = "changing database/overlay type not allowed";
   6613  1.1     lukem 			goto out;
   6614  1.1     lukem 		}
   6615  1.1     lukem 		ixold = strtol( iptr1, NULL, 0 );
   6616  1.1     lukem 		ixnew = strtol( iptr2, &ptr1, 0 );
   6617  1.1     lukem 		if ( ptr1 != ptr2 || ixold < 0 || ixnew < 0 ) {
   6618  1.1     lukem 			rs->sr_err = LDAP_NAMING_VIOLATION;
   6619  1.1     lukem 			goto out;
   6620  1.1     lukem 		}
   6621  1.1     lukem 		/* config DB is always 0, cannot be changed */
   6622  1.1     lukem 		if ( ce->ce_type == Cft_Database && ( ixold == 0 || ixnew == 0 )) {
   6623  1.1     lukem 			rs->sr_err = LDAP_CONSTRAINT_VIOLATION;
   6624  1.1     lukem 			goto out;
   6625  1.1     lukem 		}
   6626  1.1     lukem 	} else {
   6627  1.1     lukem 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6628  1.1     lukem 		rs->sr_text = "renaming not supported for this entry";
   6629  1.1     lukem 		goto out;
   6630  1.1     lukem 	}
   6631  1.1     lukem 
   6632  1.4  christos 	/* If we have a backend, it will handle the control */
   6633  1.4  christos 	if ( !cfb->cb_use_ldif && preread > SLAP_CONTROL_IGNORED ) {
   6634  1.4  christos 		if ( preread_ctrl == NULL ) {
   6635  1.4  christos 			preread_ctrl = &ctrls[num_ctrls++];
   6636  1.4  christos 			ctrls[num_ctrls] = NULL;
   6637  1.4  christos 		}
   6638  1.4  christos 		if ( slap_read_controls( op, rs, ce->ce_entry,
   6639  1.4  christos 					&slap_pre_read_bv, preread_ctrl ) )
   6640  1.4  christos 		{
   6641  1.4  christos 			Debug( LDAP_DEBUG_ANY, "config_back_modrdn: "
   6642  1.4  christos 					"pre-read failed \"%s\"\n",
   6643  1.4  christos 					ce->ce_entry->e_name.bv_val );
   6644  1.4  christos 			if ( op->o_preread & SLAP_CONTROL_CRITICAL ) {
   6645  1.4  christos 				/* FIXME: is it correct to abort
   6646  1.4  christos 				 * operation if control fails? */
   6647  1.4  christos 				goto out;
   6648  1.4  christos 			}
   6649  1.4  christos 		}
   6650  1.4  christos 	}
   6651  1.4  christos 
   6652  1.4  christos 	/*
   6653  1.4  christos 	 * ITS#10045 Pre-check for abandon but be willing to handle that the
   6654  1.4  christos 	 * operation might be abandoned while waiting for the server to pause.
   6655  1.4  christos 	 */
   6656  1.2  christos 	if ( op->o_abandon ) {
   6657  1.2  christos 		rs->sr_err = SLAPD_ABANDON;
   6658  1.4  christos 		dopause = 0;
   6659  1.2  christos 		goto out;
   6660  1.2  christos 	}
   6661  1.3  christos 	if ( slap_pause_server() < 0 )
   6662  1.3  christos 		dopause = 0;
   6663  1.4  christos 	if ( op->o_abandon ) {
   6664  1.4  christos 		rs->sr_err = SLAPD_ABANDON;
   6665  1.4  christos 		goto unpause;
   6666  1.4  christos 	}
   6667  1.4  christos 
   6668  1.4  christos 	ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
   6669  1.1     lukem 
   6670  1.1     lukem 	if ( ce->ce_type == Cft_Schema ) {
   6671  1.1     lukem 		req_modrdn_s modr = op->oq_modrdn;
   6672  1.1     lukem 		struct berval rdn;
   6673  1.1     lukem 		Attribute *a;
   6674  1.1     lukem 		rs->sr_err = config_rename_attr( rs, ce->ce_entry, &rdn, &a );
   6675  1.1     lukem 		if ( rs->sr_err == LDAP_SUCCESS ) {
   6676  1.4  christos 			op->o_preread = preread;
   6677  1.4  christos 			op->o_postread = postread;
   6678  1.1     lukem 			rs->sr_err = config_rename_one( op, rs, ce->ce_entry,
   6679  1.1     lukem 				ce->ce_parent, a, &op->orr_newrdn, &op->orr_nnewrdn,
   6680  1.1     lukem 				cfb->cb_use_ldif );
   6681  1.1     lukem 		}
   6682  1.1     lukem 		op->oq_modrdn = modr;
   6683  1.1     lukem 	} else {
   6684  1.3  christos 		CfEntryInfo *ce2, **cprev, **cbprev, *ceold;
   6685  1.1     lukem 		req_modrdn_s modr = op->oq_modrdn;
   6686  1.1     lukem 		int i;
   6687  1.1     lukem 
   6688  1.1     lukem 		/* Advance to first of this type */
   6689  1.1     lukem 		cprev = &ce->ce_parent->ce_kids;
   6690  1.1     lukem 		for ( ce2 = *cprev; ce2 && ce2->ce_type != ce->ce_type; ) {
   6691  1.1     lukem 			cprev = &ce2->ce_sibs;
   6692  1.1     lukem 			ce2 = ce2->ce_sibs;
   6693  1.1     lukem 		}
   6694  1.1     lukem 		/* Skip the -1 entry */
   6695  1.1     lukem 		if ( ce->ce_type == Cft_Database ) {
   6696  1.1     lukem 			cprev = &ce2->ce_sibs;
   6697  1.1     lukem 			ce2 = ce2->ce_sibs;
   6698  1.1     lukem 		}
   6699  1.1     lukem 		cbprev = cprev;
   6700  1.1     lukem 
   6701  1.1     lukem 		/* Remove from old slot */
   6702  1.1     lukem 		for ( ce2 = *cprev; ce2 && ce2 != ce; ce2 = ce2->ce_sibs )
   6703  1.1     lukem 			cprev = &ce2->ce_sibs;
   6704  1.1     lukem 		*cprev = ce->ce_sibs;
   6705  1.1     lukem 		ceold = ce->ce_sibs;
   6706  1.1     lukem 
   6707  1.1     lukem 		/* Insert into new slot */
   6708  1.1     lukem 		cprev = cbprev;
   6709  1.1     lukem 		for ( i=0; i<ixnew; i++ ) {
   6710  1.1     lukem 			ce2 = *cprev;
   6711  1.1     lukem 			if ( !ce2 )
   6712  1.1     lukem 				break;
   6713  1.1     lukem 			cprev = &ce2->ce_sibs;
   6714  1.1     lukem 		}
   6715  1.1     lukem 		ce->ce_sibs = *cprev;
   6716  1.1     lukem 		*cprev = ce;
   6717  1.1     lukem 
   6718  1.1     lukem 		ixnew = i;
   6719  1.1     lukem 
   6720  1.1     lukem 		/* NOTE: These should be encoded in the OC tables, not inline here */
   6721  1.1     lukem 		if ( ce->ce_type == Cft_Database )
   6722  1.1     lukem 			backend_db_move( ce->ce_be, ixnew );
   6723  1.1     lukem 		else if ( ce->ce_type == Cft_Overlay )
   6724  1.1     lukem 			overlay_move( ce->ce_be, (slap_overinst *)ce->ce_bi, ixnew );
   6725  1.4  christos 
   6726  1.4  christos 		op->o_preread = preread;
   6727  1.4  christos 		op->o_postread = postread;
   6728  1.1     lukem 		if ( ixold < ixnew ) {
   6729  1.1     lukem 			rs->sr_err = config_rename_del( op, rs, ce, ceold, ixold,
   6730  1.1     lukem 				cfb->cb_use_ldif );
   6731  1.1     lukem 		} else {
   6732  1.1     lukem 			rs->sr_err = config_rename_add( op, rs, ce, ixnew, 1,
   6733  1.1     lukem 				ixold - ixnew, cfb->cb_use_ldif );
   6734  1.1     lukem 		}
   6735  1.1     lukem 		op->oq_modrdn = modr;
   6736  1.1     lukem 	}
   6737  1.1     lukem 
   6738  1.4  christos 	if ( rs->sr_err == LDAP_SUCCESS && !cfb->cb_use_ldif &&
   6739  1.4  christos 			postread > SLAP_CONTROL_IGNORED ) {
   6740  1.4  christos 		if ( postread_ctrl == NULL ) {
   6741  1.4  christos 			postread_ctrl = &ctrls[num_ctrls++];
   6742  1.4  christos 			ctrls[num_ctrls] = NULL;
   6743  1.4  christos 		}
   6744  1.4  christos 		if ( slap_read_controls( op, rs, ce->ce_entry,
   6745  1.4  christos 			&slap_post_read_bv, postread_ctrl ) )
   6746  1.4  christos 		{
   6747  1.4  christos 			Debug( LDAP_DEBUG_ANY, "config_back_modrdn: "
   6748  1.4  christos 				"post-read failed \"%s\"\n",
   6749  1.4  christos 				ce->ce_entry->e_name.bv_val );
   6750  1.4  christos 		}
   6751  1.4  christos 	}
   6752  1.4  christos 
   6753  1.4  christos 	ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
   6754  1.4  christos 
   6755  1.4  christos unpause:
   6756  1.3  christos 	if ( dopause )
   6757  1.3  christos 		slap_unpause_server();
   6758  1.1     lukem out:
   6759  1.4  christos 	if ( num_ctrls ) rs->sr_ctrls = ctrls;
   6760  1.1     lukem 	send_ldap_result( op, rs );
   6761  1.1     lukem 	return rs->sr_err;
   6762  1.1     lukem }
   6763  1.1     lukem 
   6764  1.1     lukem static int
   6765  1.1     lukem config_back_delete( Operation *op, SlapReply *rs )
   6766  1.1     lukem {
   6767  1.2  christos #ifdef SLAP_CONFIG_DELETE
   6768  1.2  christos 	CfBackInfo *cfb;
   6769  1.4  christos 	CfEntryInfo *ce, *ce2, *last = NULL;
   6770  1.3  christos 	int dopause = 1;
   6771  1.2  christos 
   6772  1.4  christos 	LDAPControl **preread_ctrl = NULL;
   6773  1.4  christos 	LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS];
   6774  1.4  christos 	int num_ctrls = 0;
   6775  1.4  christos 
   6776  1.4  christos 	char preread = op->o_preread;
   6777  1.4  christos 
   6778  1.4  christos 	ctrls[num_ctrls] = NULL;
   6779  1.4  christos 	op->o_preread = SLAP_CONTROL_NONE;
   6780  1.4  christos 
   6781  1.2  christos 	cfb = (CfBackInfo *)op->o_bd->be_private;
   6782  1.2  christos 
   6783  1.4  christos 	/* If we have a backend, it will handle the control */
   6784  1.4  christos 	ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
   6785  1.4  christos 	if ( ce && !cfb->cb_use_ldif && preread ) {
   6786  1.4  christos 		if ( preread_ctrl == NULL ) {
   6787  1.4  christos 			preread_ctrl = &ctrls[num_ctrls++];
   6788  1.4  christos 			ctrls[num_ctrls] = NULL;
   6789  1.4  christos 		}
   6790  1.4  christos 		if ( slap_read_controls( op, rs, ce->ce_entry,
   6791  1.4  christos 					&slap_pre_read_bv, preread_ctrl ) )
   6792  1.4  christos 		{
   6793  1.4  christos 			Debug( LDAP_DEBUG_ANY, "config_back_delete: "
   6794  1.4  christos 					"pre-read failed \"%s\"\n",
   6795  1.4  christos 					ce->ce_entry->e_name.bv_val );
   6796  1.4  christos 			if ( preread & SLAP_CONTROL_CRITICAL ) {
   6797  1.4  christos 				/* FIXME: is it correct to abort
   6798  1.4  christos 				 * operation if control fails? */
   6799  1.4  christos 				goto out;
   6800  1.4  christos 			}
   6801  1.4  christos 		}
   6802  1.4  christos 	}
   6803  1.4  christos 
   6804  1.2  christos 	if ( !ce ) {
   6805  1.2  christos 		if ( last )
   6806  1.2  christos 			rs->sr_matched = last->ce_entry->e_name.bv_val;
   6807  1.2  christos 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
   6808  1.2  christos 	} else if ( ce->ce_kids ) {
   6809  1.2  christos 		rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF;
   6810  1.2  christos 	} else if ( op->o_abandon ) {
   6811  1.2  christos 		rs->sr_err = SLAPD_ABANDON;
   6812  1.2  christos 	} else if ( ce->ce_type == Cft_Overlay ||
   6813  1.2  christos 			ce->ce_type == Cft_Database ||
   6814  1.2  christos 			ce->ce_type == Cft_Misc ){
   6815  1.2  christos 		char *iptr;
   6816  1.2  christos 		int count, ixold;
   6817  1.2  christos 
   6818  1.3  christos 		if ( slap_pause_server() < 0 )
   6819  1.3  christos 			dopause = 0;
   6820  1.2  christos 
   6821  1.4  christos 		ldap_pvt_thread_rdwr_wlock( &cfb->cb_rwlock );
   6822  1.4  christos 
   6823  1.4  christos 		if ( op->o_abandon ) {
   6824  1.4  christos 			rs->sr_err = SLAPD_ABANDON;
   6825  1.4  christos 			goto out2;
   6826  1.4  christos 		}
   6827  1.4  christos 
   6828  1.2  christos 		if ( ce->ce_type == Cft_Overlay ){
   6829  1.2  christos 			overlay_remove( ce->ce_be, (slap_overinst *)ce->ce_bi, op );
   6830  1.2  christos 		} else if ( ce->ce_type == Cft_Misc ) {
   6831  1.2  christos 			/*
   6832  1.2  christos 			 * only Cft_Misc objects that have a co_lddel handler set in
   6833  1.2  christos 			 * the ConfigOCs struct can be deleted. This code also
   6834  1.2  christos 			 * assumes that the entry can be only have one objectclass
   6835  1.2  christos 			 * with co_type == Cft_Misc
   6836  1.2  christos 			 */
   6837  1.2  christos 			ConfigOCs co, *coptr;
   6838  1.2  christos 			Attribute *oc_at;
   6839  1.2  christos 			int i;
   6840  1.2  christos 
   6841  1.2  christos 			oc_at = attr_find( ce->ce_entry->e_attrs,
   6842  1.2  christos 					slap_schema.si_ad_objectClass );
   6843  1.2  christos 			if ( !oc_at ) {
   6844  1.2  christos 				rs->sr_err = LDAP_OTHER;
   6845  1.2  christos 				rs->sr_text = "objectclass not found";
   6846  1.4  christos 				goto out2;
   6847  1.2  christos 			}
   6848  1.2  christos 			for ( i=0; !BER_BVISNULL(&oc_at->a_nvals[i]); i++ ) {
   6849  1.2  christos 				co.co_name = &oc_at->a_nvals[i];
   6850  1.3  christos 				coptr = ldap_avl_find( CfOcTree, &co, CfOc_cmp );
   6851  1.2  christos 				if ( coptr == NULL || coptr->co_type != Cft_Misc ) {
   6852  1.2  christos 					continue;
   6853  1.2  christos 				}
   6854  1.2  christos 				if ( ! coptr->co_lddel || coptr->co_lddel( ce, op ) ){
   6855  1.2  christos 					rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6856  1.2  christos 					if ( ! coptr->co_lddel ) {
   6857  1.2  christos 						rs->sr_text = "No delete handler found";
   6858  1.2  christos 					} else {
   6859  1.2  christos 						rs->sr_err = LDAP_OTHER;
   6860  1.2  christos 						/* FIXME: We should return a helpful error message
   6861  1.2  christos 						 * here */
   6862  1.2  christos 					}
   6863  1.4  christos 					goto out2;
   6864  1.2  christos 				}
   6865  1.2  christos 				break;
   6866  1.2  christos 			}
   6867  1.2  christos 		} else if (ce->ce_type == Cft_Database ) {
   6868  1.2  christos 			if ( ce->ce_be == frontendDB || ce->ce_be == op->o_bd ){
   6869  1.2  christos 				rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6870  1.2  christos 				rs->sr_text = "Cannot delete config or frontend database";
   6871  1.4  christos 				goto out2;
   6872  1.2  christos 			}
   6873  1.2  christos 			if ( ce->ce_be->bd_info->bi_db_close ) {
   6874  1.2  christos 				ce->ce_be->bd_info->bi_db_close( ce->ce_be, NULL );
   6875  1.2  christos 			}
   6876  1.2  christos 			backend_destroy_one( ce->ce_be, 1);
   6877  1.2  christos 		}
   6878  1.2  christos 
   6879  1.2  christos 		/* remove CfEntryInfo from the siblings list */
   6880  1.2  christos 		if ( ce->ce_parent->ce_kids == ce ) {
   6881  1.2  christos 			ce->ce_parent->ce_kids = ce->ce_sibs;
   6882  1.2  christos 		} else {
   6883  1.2  christos 			for ( ce2 = ce->ce_parent->ce_kids ; ce2; ce2 = ce2->ce_sibs ) {
   6884  1.2  christos 				if ( ce2->ce_sibs == ce ) {
   6885  1.2  christos 					ce2->ce_sibs = ce->ce_sibs;
   6886  1.2  christos 					break;
   6887  1.2  christos 				}
   6888  1.2  christos 			}
   6889  1.2  christos 		}
   6890  1.2  christos 
   6891  1.2  christos 		/* remove from underlying database */
   6892  1.2  christos 		if ( cfb->cb_use_ldif ) {
   6893  1.2  christos 			BackendDB *be = op->o_bd;
   6894  1.4  christos 			slap_callback sc = { NULL, config_copy_controls, NULL, rs->sr_ctrls }, *scp;
   6895  1.2  christos 			struct berval dn, ndn, req_dn, req_ndn;
   6896  1.2  christos 
   6897  1.2  christos 			op->o_bd = &cfb->cb_db;
   6898  1.2  christos 
   6899  1.2  christos 			dn = op->o_dn;
   6900  1.2  christos 			ndn = op->o_ndn;
   6901  1.2  christos 			req_dn = op->o_req_dn;
   6902  1.2  christos 			req_ndn = op->o_req_ndn;
   6903  1.2  christos 
   6904  1.2  christos 			op->o_dn = op->o_bd->be_rootdn;
   6905  1.2  christos 			op->o_ndn = op->o_bd->be_rootndn;
   6906  1.2  christos 			op->o_req_dn = ce->ce_entry->e_name;
   6907  1.2  christos 			op->o_req_ndn = ce->ce_entry->e_nname;
   6908  1.2  christos 
   6909  1.2  christos 			scp = op->o_callback;
   6910  1.2  christos 			op->o_callback = &sc;
   6911  1.4  christos 			op->o_preread = preread;
   6912  1.4  christos 			rs->sr_ctrls = NULL;
   6913  1.4  christos 
   6914  1.2  christos 			op->o_bd->be_delete( op, rs );
   6915  1.2  christos 			op->o_bd = be;
   6916  1.2  christos 			op->o_callback = scp;
   6917  1.2  christos 			op->o_dn = dn;
   6918  1.2  christos 			op->o_ndn = ndn;
   6919  1.2  christos 			op->o_req_dn = req_dn;
   6920  1.2  christos 			op->o_req_ndn = req_ndn;
   6921  1.4  christos 
   6922  1.4  christos 			rs->sr_ctrls = sc.sc_private;
   6923  1.4  christos 			rs->sr_flags |= REP_CTRLS_MUSTBEFREED;
   6924  1.2  christos 		}
   6925  1.4  christos 		op->o_preread = SLAP_CONTROL_NONE;
   6926  1.2  christos 
   6927  1.2  christos 		/* renumber siblings */
   6928  1.2  christos 		iptr = ber_bvchr( &op->o_req_ndn, '{' ) + 1;
   6929  1.2  christos 		ixold = strtol( iptr, NULL, 0 );
   6930  1.2  christos 		for (ce2 = ce->ce_sibs, count=0; ce2; ce2=ce2->ce_sibs) {
   6931  1.2  christos 			config_renumber_one( op, rs, ce2->ce_parent, ce2->ce_entry,
   6932  1.2  christos 				count+ixold, 0, cfb->cb_use_ldif );
   6933  1.2  christos 			count++;
   6934  1.2  christos 		}
   6935  1.2  christos 
   6936  1.2  christos 		ce->ce_entry->e_private=NULL;
   6937  1.2  christos 		entry_free(ce->ce_entry);
   6938  1.2  christos 		ch_free(ce);
   6939  1.4  christos out2:
   6940  1.4  christos 		ldap_pvt_thread_rdwr_wunlock( &cfb->cb_rwlock );
   6941  1.3  christos 		if ( dopause ) slap_unpause_server();
   6942  1.2  christos 	} else {
   6943  1.2  christos 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6944  1.2  christos 	}
   6945  1.2  christos out:
   6946  1.4  christos 	if ( num_ctrls ) rs->sr_ctrls = ctrls;
   6947  1.2  christos #else
   6948  1.2  christos 	rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
   6949  1.2  christos #endif /* SLAP_CONFIG_DELETE */
   6950  1.2  christos 	send_ldap_result( op, rs );
   6951  1.1     lukem 	return rs->sr_err;
   6952  1.1     lukem }
   6953  1.1     lukem 
   6954  1.1     lukem static int
   6955  1.1     lukem config_back_search( Operation *op, SlapReply *rs )
   6956  1.1     lukem {
   6957  1.1     lukem 	CfBackInfo *cfb;
   6958  1.4  christos 	CfEntryInfo *ce, *last = NULL;
   6959  1.1     lukem 	slap_mask_t mask;
   6960  1.4  christos 	int paused = 0;
   6961  1.1     lukem 
   6962  1.1     lukem 	cfb = (CfBackInfo *)op->o_bd->be_private;
   6963  1.1     lukem 
   6964  1.4  christos 	if ( ldap_pvt_thread_pool_query( &connection_pool,
   6965  1.4  christos 			LDAP_PVT_THREAD_POOL_PARAM_PAUSED, &paused ) ) {
   6966  1.4  christos 		return -1;
   6967  1.4  christos 	}
   6968  1.4  christos 	if ( !paused ) {
   6969  1.4  christos 		ldap_pvt_thread_rdwr_rlock( &cfb->cb_rwlock );
   6970  1.4  christos 	}
   6971  1.4  christos 	ce = config_find_base( cfb->cb_root, &op->o_req_ndn, &last, op );
   6972  1.1     lukem 	if ( !ce ) {
   6973  1.1     lukem 		if ( last )
   6974  1.1     lukem 			rs->sr_matched = last->ce_entry->e_name.bv_val;
   6975  1.1     lukem 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
   6976  1.1     lukem 		goto out;
   6977  1.1     lukem 	}
   6978  1.1     lukem 	if ( !access_allowed_mask( op, ce->ce_entry, slap_schema.si_ad_entry, NULL,
   6979  1.1     lukem 		ACL_SEARCH, NULL, &mask ))
   6980  1.1     lukem 	{
   6981  1.1     lukem 		if ( !ACL_GRANT( mask, ACL_DISCLOSE )) {
   6982  1.1     lukem 			rs->sr_err = LDAP_NO_SUCH_OBJECT;
   6983  1.1     lukem 		} else {
   6984  1.1     lukem 			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
   6985  1.1     lukem 		}
   6986  1.1     lukem 		goto out;
   6987  1.1     lukem 	}
   6988  1.1     lukem 	switch ( op->ors_scope ) {
   6989  1.1     lukem 	case LDAP_SCOPE_BASE:
   6990  1.1     lukem 	case LDAP_SCOPE_SUBTREE:
   6991  1.2  christos 		rs->sr_err = config_send( op, rs, ce, 0 );
   6992  1.1     lukem 		break;
   6993  1.1     lukem 
   6994  1.1     lukem 	case LDAP_SCOPE_ONELEVEL:
   6995  1.1     lukem 		for (ce = ce->ce_kids; ce; ce=ce->ce_sibs) {
   6996  1.2  christos 			rs->sr_err = config_send( op, rs, ce, 1 );
   6997  1.2  christos 			if ( rs->sr_err ) {
   6998  1.2  christos 				break;
   6999  1.2  christos 			}
   7000  1.1     lukem 		}
   7001  1.1     lukem 		break;
   7002  1.1     lukem 	}
   7003  1.2  christos 
   7004  1.1     lukem out:
   7005  1.4  christos 	if ( !paused )
   7006  1.4  christos 		ldap_pvt_thread_rdwr_runlock( &cfb->cb_rwlock );
   7007  1.1     lukem 	send_ldap_result( op, rs );
   7008  1.2  christos 	return rs->sr_err;
   7009  1.1     lukem }
   7010  1.1     lukem 
   7011  1.1     lukem int config_entry_release(
   7012  1.1     lukem 	Operation *op,
   7013  1.1     lukem 	Entry *e,
   7014  1.1     lukem 	int rw )
   7015  1.1     lukem {
   7016  1.3  christos 	int rc = LDAP_SUCCESS;
   7017  1.3  christos 
   7018  1.1     lukem 	if ( !e->e_private ) {
   7019  1.3  christos 		BackendDB *be = op->o_bd;
   7020  1.3  christos 		CfBackInfo *cfb = be->be_private;
   7021  1.3  christos 		BackendInfo *bi = cfb->cb_db.bd_info;
   7022  1.3  christos 
   7023  1.3  christos 		if ( bi && bi->bi_entry_release_rw ) {
   7024  1.3  christos 			op->o_bd = &cfb->cb_db;
   7025  1.3  christos 			rc = bi->bi_entry_release_rw( op, e, rw );
   7026  1.3  christos 			op->o_bd = be;
   7027  1.3  christos 		} else {
   7028  1.3  christos 			entry_free( e );
   7029  1.3  christos 		}
   7030  1.4  christos 	} else {
   7031  1.4  christos 		entry_free( e );
   7032  1.1     lukem 	}
   7033  1.3  christos 	return rc;
   7034  1.1     lukem }
   7035  1.1     lukem 
   7036  1.1     lukem /* return LDAP_SUCCESS IFF we can retrieve the specified entry.
   7037  1.1     lukem  */
   7038  1.1     lukem int config_back_entry_get(
   7039  1.1     lukem 	Operation *op,
   7040  1.1     lukem 	struct berval *ndn,
   7041  1.1     lukem 	ObjectClass *oc,
   7042  1.1     lukem 	AttributeDescription *at,
   7043  1.1     lukem 	int rw,
   7044  1.1     lukem 	Entry **ent )
   7045  1.1     lukem {
   7046  1.1     lukem 	CfBackInfo *cfb;
   7047  1.4  christos 	CfEntryInfo *ce, *last = NULL;
   7048  1.4  christos 	Entry *e = NULL;
   7049  1.4  christos 	int paused = 0, rc = LDAP_NO_SUCH_OBJECT;
   7050  1.1     lukem 
   7051  1.1     lukem 	cfb = (CfBackInfo *)op->o_bd->be_private;
   7052  1.1     lukem 
   7053  1.4  christos 	if ( ldap_pvt_thread_pool_query( &connection_pool,
   7054  1.4  christos 			LDAP_PVT_THREAD_POOL_PARAM_PAUSED, &paused ) ) {
   7055  1.4  christos 		return -1;
   7056  1.4  christos 	}
   7057  1.4  christos 	if ( !paused ) {
   7058  1.4  christos 		ldap_pvt_thread_rdwr_rlock( &cfb->cb_rwlock );
   7059  1.4  christos 	}
   7060  1.4  christos 	ce = config_find_base( cfb->cb_root, ndn, &last, op );
   7061  1.1     lukem 	if ( ce ) {
   7062  1.4  christos 		e = ce->ce_entry;
   7063  1.4  christos 		if ( e ) {
   7064  1.1     lukem 			rc = LDAP_SUCCESS;
   7065  1.4  christos 			if ( oc && !is_entry_objectclass_or_sub( e, oc ) ) {
   7066  1.1     lukem 				rc = LDAP_NO_SUCH_ATTRIBUTE;
   7067  1.4  christos 				e = NULL;
   7068  1.1     lukem 			}
   7069  1.1     lukem 		}
   7070  1.1     lukem 	}
   7071  1.4  christos 	if ( e ) {
   7072  1.4  christos 		*ent = entry_dup( e );
   7073  1.4  christos 	}
   7074  1.4  christos 	if ( !paused )
   7075  1.4  christos 		ldap_pvt_thread_rdwr_runlock( &cfb->cb_rwlock );
   7076  1.1     lukem 
   7077  1.1     lukem 	return rc;
   7078  1.1     lukem }
   7079  1.1     lukem 
   7080  1.2  christos static int
   7081  1.1     lukem config_build_attrs( Entry *e, AttributeType **at, AttributeDescription *ad,
   7082  1.1     lukem 	ConfigTable *ct, ConfigArgs *c )
   7083  1.1     lukem {
   7084  1.1     lukem 	int i, rc;
   7085  1.1     lukem 
   7086  1.1     lukem 	for (; at && *at; at++) {
   7087  1.1     lukem 		/* Skip the naming attr */
   7088  1.1     lukem 		if ((*at)->sat_ad == ad || (*at)->sat_ad == slap_schema.si_ad_cn )
   7089  1.1     lukem 			continue;
   7090  1.1     lukem 		for (i=0;ct[i].name;i++) {
   7091  1.1     lukem 			if (ct[i].ad == (*at)->sat_ad) {
   7092  1.4  christos 				c->ca_desc = &ct[i];
   7093  1.1     lukem 				rc = config_get_vals(&ct[i], c);
   7094  1.1     lukem 				/* NOTE: tolerate that config_get_vals()
   7095  1.1     lukem 				 * returns success with no values */
   7096  1.1     lukem 				if (rc == LDAP_SUCCESS && c->rvalue_vals != NULL ) {
   7097  1.1     lukem 					if ( c->rvalue_nvals )
   7098  1.2  christos 						rc = attr_merge(e, ct[i].ad, c->rvalue_vals,
   7099  1.1     lukem 							c->rvalue_nvals);
   7100  1.2  christos 					else {
   7101  1.2  christos 						slap_syntax_validate_func *validate =
   7102  1.2  christos 							ct[i].ad->ad_type->sat_syntax->ssyn_validate;
   7103  1.2  christos 						if ( validate ) {
   7104  1.2  christos 							int j;
   7105  1.2  christos 							for ( j=0; c->rvalue_vals[j].bv_val; j++ ) {
   7106  1.2  christos 								rc = ordered_value_validate( ct[i].ad,
   7107  1.2  christos 									&c->rvalue_vals[j], LDAP_MOD_ADD );
   7108  1.2  christos 								if ( rc ) {
   7109  1.2  christos 									Debug( LDAP_DEBUG_ANY,
   7110  1.2  christos 										"config_build_attrs: error %d on %s value #%d\n",
   7111  1.2  christos 										rc, ct[i].ad->ad_cname.bv_val, j );
   7112  1.2  christos 									return rc;
   7113  1.2  christos 								}
   7114  1.2  christos 							}
   7115  1.2  christos 						}
   7116  1.2  christos 
   7117  1.2  christos 						rc = attr_merge_normalize(e, ct[i].ad,
   7118  1.1     lukem 							c->rvalue_vals, NULL);
   7119  1.2  christos 					}
   7120  1.1     lukem 					ber_bvarray_free( c->rvalue_nvals );
   7121  1.1     lukem 					ber_bvarray_free( c->rvalue_vals );
   7122  1.2  christos 					if ( rc ) {
   7123  1.2  christos 						Debug( LDAP_DEBUG_ANY,
   7124  1.2  christos 							"config_build_attrs: error %d on %s\n",
   7125  1.3  christos 							rc, ct[i].ad->ad_cname.bv_val );
   7126  1.2  christos 						return rc;
   7127  1.2  christos 					}
   7128  1.1     lukem 				}
   7129  1.1     lukem 				break;
   7130  1.1     lukem 			}
   7131  1.1     lukem 		}
   7132  1.1     lukem 	}
   7133  1.2  christos 	return 0;
   7134  1.1     lukem }
   7135  1.1     lukem 
   7136  1.2  christos /* currently (2010) does not access rs except possibly writing rs->sr_err */
   7137  1.2  christos 
   7138  1.1     lukem Entry *
   7139  1.1     lukem config_build_entry( Operation *op, SlapReply *rs, CfEntryInfo *parent,
   7140  1.1     lukem 	ConfigArgs *c, struct berval *rdn, ConfigOCs *main, ConfigOCs *extra )
   7141  1.1     lukem {
   7142  1.1     lukem 	Entry *e = entry_alloc();
   7143  1.1     lukem 	CfEntryInfo *ce = ch_calloc( 1, sizeof(CfEntryInfo) );
   7144  1.1     lukem 	AttributeDescription *ad = NULL;
   7145  1.2  christos 	int cnt, rc;
   7146  1.2  christos 	const char *text = "";
   7147  1.1     lukem 	Attribute *oc_at;
   7148  1.1     lukem 	struct berval pdn;
   7149  1.1     lukem 	ObjectClass *oc;
   7150  1.1     lukem 	CfEntryInfo *ceprev = NULL;
   7151  1.2  christos 	LDAPRDN rDN;
   7152  1.1     lukem 
   7153  1.3  christos 	Debug( LDAP_DEBUG_TRACE, "config_build_entry: \"%s\"\n", rdn->bv_val );
   7154  1.1     lukem 	e->e_private = ce;
   7155  1.1     lukem 	ce->ce_entry = e;
   7156  1.1     lukem 	ce->ce_type = main->co_type;
   7157  1.1     lukem 	ce->ce_parent = parent;
   7158  1.1     lukem 	if ( parent ) {
   7159  1.1     lukem 		pdn = parent->ce_entry->e_nname;
   7160  1.2  christos 		if ( parent->ce_kids && parent->ce_kids->ce_type <= ce->ce_type )
   7161  1.1     lukem 			for ( ceprev = parent->ce_kids; ceprev->ce_sibs &&
   7162  1.1     lukem 				ceprev->ce_type <= ce->ce_type;
   7163  1.1     lukem 				ceprev = ceprev->ce_sibs );
   7164  1.1     lukem 	} else {
   7165  1.1     lukem 		BER_BVZERO( &pdn );
   7166  1.1     lukem 	}
   7167  1.1     lukem 
   7168  1.1     lukem 	ce->ce_private = c->ca_private;
   7169  1.1     lukem 	ce->ce_be = c->be;
   7170  1.1     lukem 	ce->ce_bi = c->bi;
   7171  1.1     lukem 
   7172  1.1     lukem 	build_new_dn( &e->e_name, &pdn, rdn, NULL );
   7173  1.1     lukem 	ber_dupbv( &e->e_nname, &e->e_name );
   7174  1.1     lukem 
   7175  1.1     lukem 	attr_merge_normalize_one(e, slap_schema.si_ad_objectClass,
   7176  1.1     lukem 		main->co_name, NULL );
   7177  1.1     lukem 	if ( extra )
   7178  1.1     lukem 		attr_merge_normalize_one(e, slap_schema.si_ad_objectClass,
   7179  1.1     lukem 			extra->co_name, NULL );
   7180  1.2  christos 
   7181  1.3  christos 	rc = ldap_bv2rdn( rdn, &rDN, (char **)&text, LDAP_DN_FORMAT_LDAP );
   7182  1.1     lukem 	if ( rc ) {
   7183  1.2  christos 		goto fail;
   7184  1.2  christos 	}
   7185  1.2  christos 	for ( cnt = 0; rDN[cnt]; cnt++ ) {
   7186  1.2  christos 		LDAPAVA *ava = rDN[cnt];
   7187  1.2  christos 
   7188  1.2  christos 		ad = NULL;
   7189  1.2  christos 		rc = slap_bv2ad( &ava->la_attr, &ad, &text );
   7190  1.2  christos 		if ( rc ) {
   7191  1.2  christos 			break;
   7192  1.2  christos 		}
   7193  1.2  christos 		if ( !ad->ad_type->sat_equality ) {
   7194  1.2  christos 			rc = LDAP_CONSTRAINT_VIOLATION;
   7195  1.2  christos 			text = "attribute has no equality matching rule";
   7196  1.2  christos 			break;
   7197  1.2  christos 		}
   7198  1.2  christos 		if ( !ad->ad_type->sat_equality->smr_match ) {
   7199  1.2  christos 			rc = LDAP_CONSTRAINT_VIOLATION;
   7200  1.2  christos 			text = "attribute has unsupported equality matching rule";
   7201  1.2  christos 			break;
   7202  1.2  christos 		}
   7203  1.2  christos 		attr_merge_normalize_one(e, ad, &ava->la_value, NULL );
   7204  1.2  christos 	}
   7205  1.2  christos 	ldap_rdnfree( rDN );
   7206  1.2  christos 	if ( rc ) {
   7207  1.2  christos 		goto fail;
   7208  1.1     lukem 	}
   7209  1.1     lukem 
   7210  1.1     lukem 	oc = main->co_oc;
   7211  1.1     lukem 	c->table = main->co_type;
   7212  1.2  christos 	if ( oc->soc_required ) {
   7213  1.2  christos 		rc = config_build_attrs( e, oc->soc_required, ad, main->co_table, c );
   7214  1.2  christos 		if ( rc ) goto fail;
   7215  1.2  christos 	}
   7216  1.1     lukem 
   7217  1.2  christos 	if ( oc->soc_allowed ) {
   7218  1.2  christos 		rc = config_build_attrs( e, oc->soc_allowed, ad, main->co_table, c );
   7219  1.2  christos 		if ( rc ) goto fail;
   7220  1.2  christos 	}
   7221  1.1     lukem 
   7222  1.1     lukem 	if ( extra ) {
   7223  1.1     lukem 		oc = extra->co_oc;
   7224  1.1     lukem 		c->table = extra->co_type;
   7225  1.2  christos 		if ( oc->soc_required ) {
   7226  1.2  christos 			rc = config_build_attrs( e, oc->soc_required, ad, extra->co_table, c );
   7227  1.2  christos 			if ( rc ) goto fail;
   7228  1.2  christos 		}
   7229  1.1     lukem 
   7230  1.2  christos 		if ( oc->soc_allowed ) {
   7231  1.2  christos 			rc = config_build_attrs( e, oc->soc_allowed, ad, extra->co_table, c );
   7232  1.2  christos 			if ( rc ) goto fail;
   7233  1.2  christos 		}
   7234  1.1     lukem 	}
   7235  1.1     lukem 
   7236  1.1     lukem 	oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
   7237  1.1     lukem 	rc = structural_class(oc_at->a_vals, &oc, NULL, &text, c->cr_msg,
   7238  1.1     lukem 		sizeof(c->cr_msg), op ? op->o_tmpmemctx : NULL );
   7239  1.2  christos 	if ( rc != LDAP_SUCCESS ) {
   7240  1.2  christos fail:
   7241  1.2  christos 		Debug( LDAP_DEBUG_ANY,
   7242  1.2  christos 			"config_build_entry: build \"%s\" failed: \"%s\"\n",
   7243  1.3  christos 			rdn->bv_val, text );
   7244  1.2  christos 		return NULL;
   7245  1.2  christos 	}
   7246  1.1     lukem 	attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL );
   7247  1.1     lukem 	if ( op ) {
   7248  1.1     lukem 		op->ora_e = e;
   7249  1.1     lukem 		op->ora_modlist = NULL;
   7250  1.1     lukem 		slap_add_opattrs( op, NULL, NULL, 0, 0 );
   7251  1.1     lukem 		if ( !op->o_noop ) {
   7252  1.2  christos 			SlapReply rs2 = {REP_RESULT};
   7253  1.2  christos 			op->o_bd->be_add( op, &rs2 );
   7254  1.2  christos 			rs->sr_err = rs2.sr_err;
   7255  1.2  christos 			rs_assert_done( &rs2 );
   7256  1.2  christos 			if ( ( rs2.sr_err != LDAP_SUCCESS )
   7257  1.2  christos 					&& (rs2.sr_err != LDAP_ALREADY_EXISTS) ) {
   7258  1.2  christos 				goto fail;
   7259  1.1     lukem 			}
   7260  1.1     lukem 		}
   7261  1.1     lukem 	}
   7262  1.1     lukem 	if ( ceprev ) {
   7263  1.1     lukem 		ce->ce_sibs = ceprev->ce_sibs;
   7264  1.1     lukem 		ceprev->ce_sibs = ce;
   7265  1.1     lukem 	} else if ( parent ) {
   7266  1.1     lukem 		ce->ce_sibs = parent->ce_kids;
   7267  1.1     lukem 		parent->ce_kids = ce;
   7268  1.1     lukem 	}
   7269  1.1     lukem 
   7270  1.1     lukem 	return e;
   7271  1.1     lukem }
   7272  1.1     lukem 
   7273  1.1     lukem static int
   7274  1.1     lukem config_build_schema_inc( ConfigArgs *c, CfEntryInfo *ceparent,
   7275  1.1     lukem 	Operation *op, SlapReply *rs )
   7276  1.1     lukem {
   7277  1.1     lukem 	Entry *e;
   7278  1.1     lukem 	ConfigFile *cf = c->ca_private;
   7279  1.1     lukem 	char *ptr;
   7280  1.2  christos 	struct berval bv, rdn;
   7281  1.1     lukem 
   7282  1.1     lukem 	for (; cf; cf=cf->c_sibs, c->depth++) {
   7283  1.1     lukem 		if ( !cf->c_at_head && !cf->c_cr_head && !cf->c_oc_head &&
   7284  1.2  christos 			!cf->c_om_head && !cf->c_syn_head && !cf->c_kids ) continue;
   7285  1.1     lukem 		c->value_dn.bv_val = c->log;
   7286  1.1     lukem 		LUTIL_SLASHPATH( cf->c_file.bv_val );
   7287  1.1     lukem 		bv.bv_val = strrchr(cf->c_file.bv_val, LDAP_DIRSEP[0]);
   7288  1.1     lukem 		if ( !bv.bv_val ) {
   7289  1.1     lukem 			bv = cf->c_file;
   7290  1.1     lukem 		} else {
   7291  1.1     lukem 			bv.bv_val++;
   7292  1.1     lukem 			bv.bv_len = cf->c_file.bv_len - (bv.bv_val - cf->c_file.bv_val);
   7293  1.1     lukem 		}
   7294  1.1     lukem 		ptr = strchr( bv.bv_val, '.' );
   7295  1.1     lukem 		if ( ptr )
   7296  1.1     lukem 			bv.bv_len = ptr - bv.bv_val;
   7297  1.1     lukem 		c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=" SLAP_X_ORDERED_FMT, c->depth);
   7298  1.1     lukem 		if ( c->value_dn.bv_len >= sizeof( c->log ) ) {
   7299  1.1     lukem 			/* FIXME: how can indicate error? */
   7300  1.1     lukem 			return -1;
   7301  1.1     lukem 		}
   7302  1.1     lukem 		strncpy( c->value_dn.bv_val + c->value_dn.bv_len, bv.bv_val,
   7303  1.1     lukem 			bv.bv_len );
   7304  1.1     lukem 		c->value_dn.bv_len += bv.bv_len;
   7305  1.1     lukem 		c->value_dn.bv_val[c->value_dn.bv_len] ='\0';
   7306  1.2  christos 		if ( rdnNormalize( 0, NULL, NULL, &c->value_dn, &rdn, NULL )) {
   7307  1.2  christos 			Debug( LDAP_DEBUG_ANY,
   7308  1.2  christos 				"config_build_schema_inc: invalid schema name \"%s\"\n",
   7309  1.3  christos 				bv.bv_val );
   7310  1.2  christos 			return -1;
   7311  1.2  christos 		}
   7312  1.1     lukem 
   7313  1.1     lukem 		c->ca_private = cf;
   7314  1.2  christos 		e = config_build_entry( op, rs, ceparent, c, &rdn,
   7315  1.1     lukem 			&CFOC_SCHEMA, NULL );
   7316  1.2  christos 		ch_free( rdn.bv_val );
   7317  1.1     lukem 		if ( !e ) {
   7318  1.1     lukem 			return -1;
   7319  1.1     lukem 		} else if ( e && cf->c_kids ) {
   7320  1.1     lukem 			c->ca_private = cf->c_kids;
   7321  1.1     lukem 			config_build_schema_inc( c, e->e_private, op, rs );
   7322  1.1     lukem 		}
   7323  1.1     lukem 	}
   7324  1.1     lukem 	return 0;
   7325  1.1     lukem }
   7326  1.1     lukem 
   7327  1.1     lukem #ifdef SLAPD_MODULES
   7328  1.1     lukem 
   7329  1.1     lukem static int
   7330  1.1     lukem config_build_modules( ConfigArgs *c, CfEntryInfo *ceparent,
   7331  1.1     lukem 	Operation *op, SlapReply *rs )
   7332  1.1     lukem {
   7333  1.1     lukem 	int i;
   7334  1.1     lukem 	ModPaths *mp;
   7335  1.1     lukem 
   7336  1.1     lukem 	for (i=0, mp=&modpaths; mp; mp=mp->mp_next, i++) {
   7337  1.1     lukem 		if ( BER_BVISNULL( &mp->mp_path ) && !mp->mp_loads )
   7338  1.1     lukem 			continue;
   7339  1.1     lukem 		c->value_dn.bv_val = c->log;
   7340  1.1     lukem 		c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=module" SLAP_X_ORDERED_FMT, i);
   7341  1.1     lukem 		if ( c->value_dn.bv_len >= sizeof( c->log ) ) {
   7342  1.1     lukem 			/* FIXME: how can indicate error? */
   7343  1.1     lukem 			return -1;
   7344  1.1     lukem 		}
   7345  1.1     lukem 		c->ca_private = mp;
   7346  1.1     lukem 		if ( ! config_build_entry( op, rs, ceparent, c, &c->value_dn, &CFOC_MODULE, NULL )) {
   7347  1.1     lukem 			return -1;
   7348  1.1     lukem 		}
   7349  1.1     lukem 	}
   7350  1.1     lukem         return 0;
   7351  1.1     lukem }
   7352  1.1     lukem #endif
   7353  1.1     lukem 
   7354  1.1     lukem static int
   7355  1.1     lukem config_check_schema(Operation *op, CfBackInfo *cfb)
   7356  1.1     lukem {
   7357  1.1     lukem 	struct berval schema_dn = BER_BVC(SCHEMA_RDN "," CONFIG_RDN);
   7358  1.1     lukem 	ConfigArgs c = {0};
   7359  1.4  christos 	CfEntryInfo *ce, *last = NULL;
   7360  1.1     lukem 	Entry *e;
   7361  1.1     lukem 
   7362  1.1     lukem 	/* If there's no root entry, we must be in the midst of converting */
   7363  1.1     lukem 	if ( !cfb->cb_root )
   7364  1.1     lukem 		return 0;
   7365  1.1     lukem 
   7366  1.1     lukem 	/* Make sure the main schema entry exists */
   7367  1.4  christos 	ce = config_find_base( cfb->cb_root, &schema_dn, &last, op );
   7368  1.1     lukem 	if ( ce ) {
   7369  1.1     lukem 		Attribute *a;
   7370  1.1     lukem 		struct berval *bv;
   7371  1.1     lukem 
   7372  1.1     lukem 		e = ce->ce_entry;
   7373  1.1     lukem 
   7374  1.1     lukem 		/* Make sure it's up to date */
   7375  1.1     lukem 		if ( cf_om_tail != om_sys_tail ) {
   7376  1.1     lukem 			a = attr_find( e->e_attrs, cfAd_om );
   7377  1.1     lukem 			if ( a ) {
   7378  1.1     lukem 				if ( a->a_nvals != a->a_vals )
   7379  1.1     lukem 					ber_bvarray_free( a->a_nvals );
   7380  1.1     lukem 				ber_bvarray_free( a->a_vals );
   7381  1.1     lukem 				a->a_vals = NULL;
   7382  1.1     lukem 				a->a_nvals = NULL;
   7383  1.1     lukem 				a->a_numvals = 0;
   7384  1.1     lukem 			}
   7385  1.1     lukem 			oidm_unparse( &bv, NULL, NULL, 1 );
   7386  1.1     lukem 			attr_merge_normalize( e, cfAd_om, bv, NULL );
   7387  1.1     lukem 			ber_bvarray_free( bv );
   7388  1.1     lukem 			cf_om_tail = om_sys_tail;
   7389  1.1     lukem 		}
   7390  1.1     lukem 		if ( cf_at_tail != at_sys_tail ) {
   7391  1.1     lukem 			a = attr_find( e->e_attrs, cfAd_attr );
   7392  1.1     lukem 			if ( a ) {
   7393  1.1     lukem 				if ( a->a_nvals != a->a_vals )
   7394  1.1     lukem 					ber_bvarray_free( a->a_nvals );
   7395  1.1     lukem 				ber_bvarray_free( a->a_vals );
   7396  1.1     lukem 				a->a_vals = NULL;
   7397  1.1     lukem 				a->a_nvals = NULL;
   7398  1.1     lukem 				a->a_numvals = 0;
   7399  1.1     lukem 			}
   7400  1.1     lukem 			at_unparse( &bv, NULL, NULL, 1 );
   7401  1.1     lukem 			attr_merge_normalize( e, cfAd_attr, bv, NULL );
   7402  1.1     lukem 			ber_bvarray_free( bv );
   7403  1.1     lukem 			cf_at_tail = at_sys_tail;
   7404  1.1     lukem 		}
   7405  1.1     lukem 		if ( cf_oc_tail != oc_sys_tail ) {
   7406  1.1     lukem 			a = attr_find( e->e_attrs, cfAd_oc );
   7407  1.1     lukem 			if ( a ) {
   7408  1.1     lukem 				if ( a->a_nvals != a->a_vals )
   7409  1.1     lukem 					ber_bvarray_free( a->a_nvals );
   7410  1.1     lukem 				ber_bvarray_free( a->a_vals );
   7411  1.1     lukem 				a->a_vals = NULL;
   7412  1.1     lukem 				a->a_nvals = NULL;
   7413  1.1     lukem 				a->a_numvals = 0;
   7414  1.1     lukem 			}
   7415  1.1     lukem 			oc_unparse( &bv, NULL, NULL, 1 );
   7416  1.1     lukem 			attr_merge_normalize( e, cfAd_oc, bv, NULL );
   7417  1.1     lukem 			ber_bvarray_free( bv );
   7418  1.1     lukem 			cf_oc_tail = oc_sys_tail;
   7419  1.1     lukem 		}
   7420  1.2  christos 		if ( cf_syn_tail != syn_sys_tail ) {
   7421  1.2  christos 			a = attr_find( e->e_attrs, cfAd_syntax );
   7422  1.2  christos 			if ( a ) {
   7423  1.2  christos 				if ( a->a_nvals != a->a_vals )
   7424  1.2  christos 					ber_bvarray_free( a->a_nvals );
   7425  1.2  christos 				ber_bvarray_free( a->a_vals );
   7426  1.2  christos 				a->a_vals = NULL;
   7427  1.2  christos 				a->a_nvals = NULL;
   7428  1.2  christos 				a->a_numvals = 0;
   7429  1.2  christos 			}
   7430  1.2  christos 			syn_unparse( &bv, NULL, NULL, 1 );
   7431  1.2  christos 			attr_merge_normalize( e, cfAd_syntax, bv, NULL );
   7432  1.2  christos 			ber_bvarray_free( bv );
   7433  1.2  christos 			cf_syn_tail = syn_sys_tail;
   7434  1.2  christos 		}
   7435  1.1     lukem 	} else {
   7436  1.1     lukem 		SlapReply rs = {REP_RESULT};
   7437  1.1     lukem 		c.ca_private = NULL;
   7438  1.1     lukem 		e = config_build_entry( op, &rs, cfb->cb_root, &c, &schema_rdn,
   7439  1.1     lukem 			&CFOC_SCHEMA, NULL );
   7440  1.1     lukem 		if ( !e ) {
   7441  1.1     lukem 			return -1;
   7442  1.1     lukem 		}
   7443  1.1     lukem 		ce = e->e_private;
   7444  1.1     lukem 		ce->ce_private = cfb->cb_config;
   7445  1.1     lukem 		cf_at_tail = at_sys_tail;
   7446  1.1     lukem 		cf_oc_tail = oc_sys_tail;
   7447  1.1     lukem 		cf_om_tail = om_sys_tail;
   7448  1.2  christos 		cf_syn_tail = syn_sys_tail;
   7449  1.1     lukem 	}
   7450  1.1     lukem 	return 0;
   7451  1.1     lukem }
   7452  1.1     lukem 
   7453  1.1     lukem static const char *defacl[] = {
   7454  1.1     lukem 	NULL, "to", "*", "by", "*", "none", NULL
   7455  1.1     lukem };
   7456  1.1     lukem 
   7457  1.1     lukem static int
   7458  1.1     lukem config_back_db_open( BackendDB *be, ConfigReply *cr )
   7459  1.1     lukem {
   7460  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7461  1.1     lukem 	struct berval rdn;
   7462  1.3  christos 	Entry *e;
   7463  1.1     lukem 	CfEntryInfo *ce, *ceparent;
   7464  1.1     lukem 	int i, unsupp = 0;
   7465  1.1     lukem 	BackendInfo *bi;
   7466  1.1     lukem 	ConfigArgs c;
   7467  1.1     lukem 	Connection conn = {0};
   7468  1.1     lukem 	OperationBuffer opbuf;
   7469  1.1     lukem 	Operation *op;
   7470  1.1     lukem 	slap_callback cb = { NULL, slap_null_cb, NULL, NULL };
   7471  1.1     lukem 	SlapReply rs = {REP_RESULT};
   7472  1.1     lukem 	void *thrctx = NULL;
   7473  1.2  christos 	AccessControl *save_access;
   7474  1.1     lukem 
   7475  1.3  christos 	Debug( LDAP_DEBUG_TRACE, "config_back_db_open\n" );
   7476  1.1     lukem 
   7477  1.1     lukem 	/* If we have no explicitly configured ACLs, don't just use
   7478  1.1     lukem 	 * the global ACLs. Explicitly deny access to everything.
   7479  1.1     lukem 	 */
   7480  1.2  christos 	save_access = be->bd_self->be_acl;
   7481  1.2  christos 	be->bd_self->be_acl = NULL;
   7482  1.4  christos 	c.be = be->bd_self;
   7483  1.4  christos 	c.fname = "config_back_db_open";
   7484  1.4  christos 	c.lineno = 0;
   7485  1.4  christos 	c.argc = 6;
   7486  1.4  christos 	c.argv = (char **)defacl;
   7487  1.4  christos 	parse_acl( &c, 0 );
   7488  1.2  christos 	defacl_parsed = be->bd_self->be_acl;
   7489  1.2  christos 	if ( save_access ) {
   7490  1.2  christos 		be->bd_self->be_acl = save_access;
   7491  1.2  christos 	} else {
   7492  1.2  christos 		Debug( LDAP_DEBUG_CONFIG, "config_back_db_open: "
   7493  1.2  christos 				"No explicit ACL for back-config configured. "
   7494  1.3  christos 				"Using hardcoded default\n" );
   7495  1.1     lukem 	}
   7496  1.1     lukem 
   7497  1.1     lukem 	thrctx = ldap_pvt_thread_pool_context();
   7498  1.1     lukem 	connection_fake_init( &conn, &opbuf, thrctx );
   7499  1.1     lukem 	op = &opbuf.ob_op;
   7500  1.1     lukem 
   7501  1.1     lukem 	op->o_tag = LDAP_REQ_ADD;
   7502  1.1     lukem 	op->o_callback = &cb;
   7503  1.1     lukem 	op->o_bd = &cfb->cb_db;
   7504  1.1     lukem 	op->o_dn = op->o_bd->be_rootdn;
   7505  1.1     lukem 	op->o_ndn = op->o_bd->be_rootndn;
   7506  1.1     lukem 
   7507  1.1     lukem 	if ( !cfb->cb_use_ldif ) {
   7508  1.1     lukem 		op->o_noop = 1;
   7509  1.1     lukem 	}
   7510  1.1     lukem 
   7511  1.1     lukem 	/* If we read the config from back-ldif, do some quick sanity checks */
   7512  1.1     lukem 	if ( cfb->cb_got_ldif ) {
   7513  1.1     lukem 		return config_check_schema( op, cfb );
   7514  1.1     lukem 	}
   7515  1.1     lukem 
   7516  1.1     lukem 	/* create root of tree */
   7517  1.1     lukem 	rdn = config_rdn;
   7518  1.1     lukem 	c.ca_private = cfb->cb_config;
   7519  1.1     lukem 	c.be = frontendDB;
   7520  1.1     lukem 	e = config_build_entry( op, &rs, NULL, &c, &rdn, &CFOC_GLOBAL, NULL );
   7521  1.1     lukem 	if ( !e ) {
   7522  1.1     lukem 		return -1;
   7523  1.1     lukem 	}
   7524  1.1     lukem 	ce = e->e_private;
   7525  1.1     lukem 	cfb->cb_root = ce;
   7526  1.1     lukem 
   7527  1.1     lukem 	ceparent = ce;
   7528  1.1     lukem 
   7529  1.1     lukem #ifdef SLAPD_MODULES
   7530  1.1     lukem 	/* Create Module nodes... */
   7531  1.1     lukem 	if ( modpaths.mp_loads ) {
   7532  1.1     lukem 		if ( config_build_modules( &c, ceparent, op, &rs ) ){
   7533  1.1     lukem 			return -1;
   7534  1.1     lukem 		}
   7535  1.1     lukem 	}
   7536  1.1     lukem #endif
   7537  1.1     lukem 
   7538  1.1     lukem 	/* Create schema nodes... cn=schema will contain the hardcoded core
   7539  1.1     lukem 	 * schema, read-only. Child objects will contain runtime loaded schema
   7540  1.1     lukem 	 * files.
   7541  1.1     lukem 	 */
   7542  1.1     lukem 	rdn = schema_rdn;
   7543  1.1     lukem 	c.ca_private = NULL;
   7544  1.1     lukem 	e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_SCHEMA, NULL );
   7545  1.1     lukem 	if ( !e ) {
   7546  1.1     lukem 		return -1;
   7547  1.1     lukem 	}
   7548  1.1     lukem 	ce = e->e_private;
   7549  1.1     lukem 	ce->ce_private = cfb->cb_config;
   7550  1.1     lukem 	cf_at_tail = at_sys_tail;
   7551  1.1     lukem 	cf_oc_tail = oc_sys_tail;
   7552  1.1     lukem 	cf_om_tail = om_sys_tail;
   7553  1.2  christos 	cf_syn_tail = syn_sys_tail;
   7554  1.1     lukem 
   7555  1.1     lukem 	/* Create schema nodes for included schema... */
   7556  1.1     lukem 	if ( cfb->cb_config->c_kids ) {
   7557  1.2  christos 		int rc;
   7558  1.1     lukem 		c.depth = 0;
   7559  1.1     lukem 		c.ca_private = cfb->cb_config->c_kids;
   7560  1.2  christos 		rc = config_build_schema_inc( &c, ce, op, &rs );
   7561  1.2  christos 		if ( rc ) {
   7562  1.1     lukem 			return -1;
   7563  1.1     lukem 		}
   7564  1.1     lukem 	}
   7565  1.1     lukem 
   7566  1.1     lukem 	/* Create backend nodes. Skip if they don't provide a cf_table.
   7567  1.1     lukem 	 * There usually aren't any of these.
   7568  1.1     lukem 	 */
   7569  1.1     lukem 
   7570  1.1     lukem 	c.line = 0;
   7571  1.3  christos 	i = 0;
   7572  1.1     lukem 	LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next) {
   7573  1.1     lukem 		if (!bi->bi_cf_ocs) {
   7574  1.1     lukem 			/* If it only supports the old config mech, complain. */
   7575  1.1     lukem 			if ( bi->bi_config ) {
   7576  1.1     lukem 				Debug( LDAP_DEBUG_ANY,
   7577  1.1     lukem 					"WARNING: No dynamic config support for backend %s.\n",
   7578  1.3  christos 					bi->bi_type );
   7579  1.1     lukem 				unsupp++;
   7580  1.1     lukem 			}
   7581  1.1     lukem 			continue;
   7582  1.1     lukem 		}
   7583  1.3  christos 		if ( !bi->bi_private && !(bi->bi_flags & SLAP_BFLAG_STANDALONE) ) continue;
   7584  1.1     lukem 
   7585  1.1     lukem 		rdn.bv_val = c.log;
   7586  1.1     lukem 		rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ),
   7587  1.3  christos 			"%s=" SLAP_X_ORDERED_FMT "%s", cfAd_backend->ad_cname.bv_val,
   7588  1.3  christos 			i, bi->bi_type);
   7589  1.1     lukem 		if ( rdn.bv_len >= sizeof( c.log ) ) {
   7590  1.1     lukem 			/* FIXME: holler ... */ ;
   7591  1.1     lukem 		}
   7592  1.1     lukem 		c.bi = bi;
   7593  1.1     lukem 		e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_BACKEND,
   7594  1.1     lukem 			bi->bi_cf_ocs );
   7595  1.1     lukem 		if ( !e ) {
   7596  1.1     lukem 			return -1;
   7597  1.1     lukem 		}
   7598  1.3  christos 		if ( bi->bi_cf_ocs && bi->bi_cf_ocs->co_cfadd ) {
   7599  1.3  christos 			rs_reinit( &rs, REP_RESULT );
   7600  1.3  christos 			bi->bi_cf_ocs->co_cfadd( op, &rs, e, &c );
   7601  1.3  christos 		}
   7602  1.3  christos 		i++;
   7603  1.1     lukem 	}
   7604  1.1     lukem 
   7605  1.1     lukem 	/* Create database nodes... */
   7606  1.1     lukem 	frontendDB->be_cf_ocs = &CFOC_FRONTEND;
   7607  1.1     lukem 	LDAP_STAILQ_NEXT(frontendDB, be_next) = LDAP_STAILQ_FIRST(&backendDB);
   7608  1.1     lukem 	for ( i = -1, be = frontendDB ; be;
   7609  1.1     lukem 		i++, be = LDAP_STAILQ_NEXT( be, be_next )) {
   7610  1.1     lukem 		slap_overinfo *oi = NULL;
   7611  1.1     lukem 
   7612  1.1     lukem 		if ( overlay_is_over( be )) {
   7613  1.1     lukem 			oi = be->bd_info->bi_private;
   7614  1.1     lukem 			bi = oi->oi_orig;
   7615  1.1     lukem 		} else {
   7616  1.1     lukem 			bi = be->bd_info;
   7617  1.1     lukem 		}
   7618  1.1     lukem 
   7619  1.1     lukem 		/* If this backend supports the old config mechanism, but not
   7620  1.1     lukem 		 * the new mech, complain.
   7621  1.1     lukem 		 */
   7622  1.1     lukem 		if ( !be->be_cf_ocs && bi->bi_db_config ) {
   7623  1.1     lukem 			Debug( LDAP_DEBUG_ANY,
   7624  1.1     lukem 				"WARNING: No dynamic config support for database %s.\n",
   7625  1.3  christos 				bi->bi_type );
   7626  1.1     lukem 			unsupp++;
   7627  1.1     lukem 		}
   7628  1.1     lukem 		rdn.bv_val = c.log;
   7629  1.1     lukem 		rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ),
   7630  1.1     lukem 			"%s=" SLAP_X_ORDERED_FMT "%s", cfAd_database->ad_cname.bv_val,
   7631  1.1     lukem 			i, bi->bi_type);
   7632  1.1     lukem 		if ( rdn.bv_len >= sizeof( c.log ) ) {
   7633  1.1     lukem 			/* FIXME: holler ... */ ;
   7634  1.1     lukem 		}
   7635  1.1     lukem 		c.be = be;
   7636  1.1     lukem 		c.bi = bi;
   7637  1.1     lukem 		e = config_build_entry( op, &rs, ceparent, &c, &rdn, &CFOC_DATABASE,
   7638  1.1     lukem 			be->be_cf_ocs );
   7639  1.1     lukem 		if ( !e ) {
   7640  1.1     lukem 			return -1;
   7641  1.1     lukem 		}
   7642  1.1     lukem 		ce = e->e_private;
   7643  1.2  christos 		if ( be->be_cf_ocs && be->be_cf_ocs->co_cfadd ) {
   7644  1.2  christos 			rs_reinit( &rs, REP_RESULT );
   7645  1.1     lukem 			be->be_cf_ocs->co_cfadd( op, &rs, e, &c );
   7646  1.2  christos 		}
   7647  1.1     lukem 		/* Iterate through overlays */
   7648  1.1     lukem 		if ( oi ) {
   7649  1.1     lukem 			slap_overinst *on;
   7650  1.1     lukem 			Entry *oe;
   7651  1.1     lukem 			int j;
   7652  1.1     lukem 			voidList *vl, *v0 = NULL;
   7653  1.1     lukem 
   7654  1.1     lukem 			/* overlays are in LIFO order, must reverse stack */
   7655  1.1     lukem 			for (on=oi->oi_list; on; on=on->on_next) {
   7656  1.1     lukem 				vl = ch_malloc( sizeof( voidList ));
   7657  1.1     lukem 				vl->vl_next = v0;
   7658  1.1     lukem 				v0 = vl;
   7659  1.1     lukem 				vl->vl_ptr = on;
   7660  1.1     lukem 			}
   7661  1.1     lukem 			for (j=0; vl; j++,vl=v0) {
   7662  1.1     lukem 				on = vl->vl_ptr;
   7663  1.1     lukem 				v0 = vl->vl_next;
   7664  1.1     lukem 				ch_free( vl );
   7665  1.1     lukem 				if ( on->on_bi.bi_db_config && !on->on_bi.bi_cf_ocs ) {
   7666  1.1     lukem 					Debug( LDAP_DEBUG_ANY,
   7667  1.1     lukem 						"WARNING: No dynamic config support for overlay %s.\n",
   7668  1.3  christos 						on->on_bi.bi_type );
   7669  1.1     lukem 					unsupp++;
   7670  1.1     lukem 				}
   7671  1.1     lukem 				rdn.bv_val = c.log;
   7672  1.1     lukem 				rdn.bv_len = snprintf(rdn.bv_val, sizeof( c.log ),
   7673  1.1     lukem 					"%s=" SLAP_X_ORDERED_FMT "%s",
   7674  1.1     lukem 					cfAd_overlay->ad_cname.bv_val, j, on->on_bi.bi_type );
   7675  1.1     lukem 				if ( rdn.bv_len >= sizeof( c.log ) ) {
   7676  1.1     lukem 					/* FIXME: holler ... */ ;
   7677  1.1     lukem 				}
   7678  1.1     lukem 				c.be = be;
   7679  1.1     lukem 				c.bi = &on->on_bi;
   7680  1.1     lukem 				oe = config_build_entry( op, &rs, ce, &c, &rdn,
   7681  1.1     lukem 					&CFOC_OVERLAY, c.bi->bi_cf_ocs );
   7682  1.1     lukem 				if ( !oe ) {
   7683  1.1     lukem 					return -1;
   7684  1.1     lukem 				}
   7685  1.2  christos 				if ( c.bi->bi_cf_ocs && c.bi->bi_cf_ocs->co_cfadd ) {
   7686  1.2  christos 					rs_reinit( &rs, REP_RESULT );
   7687  1.1     lukem 					c.bi->bi_cf_ocs->co_cfadd( op, &rs, oe, &c );
   7688  1.2  christos 				}
   7689  1.1     lukem 			}
   7690  1.1     lukem 		}
   7691  1.1     lukem 	}
   7692  1.1     lukem 	if ( thrctx )
   7693  1.1     lukem 		ldap_pvt_thread_pool_context_reset( thrctx );
   7694  1.1     lukem 
   7695  1.1     lukem 	if ( unsupp  && cfb->cb_use_ldif ) {
   7696  1.1     lukem 		Debug( LDAP_DEBUG_ANY, "\nWARNING: The converted cn=config "
   7697  1.3  christos 			"directory is incomplete and may not work.\n\n" );
   7698  1.1     lukem 	}
   7699  1.1     lukem 
   7700  1.1     lukem 	return 0;
   7701  1.1     lukem }
   7702  1.1     lukem 
   7703  1.1     lukem static void
   7704  1.1     lukem cfb_free_cffile( ConfigFile *cf )
   7705  1.1     lukem {
   7706  1.1     lukem 	ConfigFile *next;
   7707  1.1     lukem 
   7708  1.1     lukem 	for (; cf; cf=next) {
   7709  1.1     lukem 		next = cf->c_sibs;
   7710  1.1     lukem 		if ( cf->c_kids )
   7711  1.1     lukem 			cfb_free_cffile( cf->c_kids );
   7712  1.1     lukem 		ch_free( cf->c_file.bv_val );
   7713  1.1     lukem 		ber_bvarray_free( cf->c_dseFiles );
   7714  1.1     lukem 		ch_free( cf );
   7715  1.1     lukem 	}
   7716  1.1     lukem }
   7717  1.1     lukem 
   7718  1.1     lukem static void
   7719  1.1     lukem cfb_free_entries( CfEntryInfo *ce )
   7720  1.1     lukem {
   7721  1.1     lukem 	CfEntryInfo *next;
   7722  1.1     lukem 
   7723  1.1     lukem 	for (; ce; ce=next) {
   7724  1.1     lukem 		next = ce->ce_sibs;
   7725  1.1     lukem 		if ( ce->ce_kids )
   7726  1.1     lukem 			cfb_free_entries( ce->ce_kids );
   7727  1.1     lukem 		ce->ce_entry->e_private = NULL;
   7728  1.1     lukem 		entry_free( ce->ce_entry );
   7729  1.1     lukem 		ch_free( ce );
   7730  1.1     lukem 	}
   7731  1.1     lukem }
   7732  1.1     lukem 
   7733  1.1     lukem static int
   7734  1.1     lukem config_back_db_close( BackendDB *be, ConfigReply *cr )
   7735  1.1     lukem {
   7736  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7737  1.1     lukem 
   7738  1.1     lukem 	cfb_free_entries( cfb->cb_root );
   7739  1.1     lukem 	cfb->cb_root = NULL;
   7740  1.1     lukem 
   7741  1.1     lukem 	if ( cfb->cb_db.bd_info ) {
   7742  1.1     lukem 		backend_shutdown( &cfb->cb_db );
   7743  1.1     lukem 	}
   7744  1.1     lukem 
   7745  1.2  christos 	if ( defacl_parsed && be->be_acl != defacl_parsed ) {
   7746  1.2  christos 		acl_free( defacl_parsed );
   7747  1.2  christos 		defacl_parsed = NULL;
   7748  1.2  christos 	}
   7749  1.2  christos 
   7750  1.1     lukem 	return 0;
   7751  1.1     lukem }
   7752  1.1     lukem 
   7753  1.1     lukem static int
   7754  1.1     lukem config_back_db_destroy( BackendDB *be, ConfigReply *cr )
   7755  1.1     lukem {
   7756  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7757  1.1     lukem 
   7758  1.1     lukem 	cfb_free_cffile( cfb->cb_config );
   7759  1.1     lukem 
   7760  1.1     lukem 	ch_free( cfdir.bv_val );
   7761  1.1     lukem 
   7762  1.4  christos 	ldap_pvt_thread_rdwr_destroy( &cfb->cb_rwlock );
   7763  1.4  christos 
   7764  1.3  christos 	ldap_avl_free( CfOcTree, NULL );
   7765  1.1     lukem 
   7766  1.1     lukem 	if ( cfb->cb_db.bd_info ) {
   7767  1.1     lukem 		cfb->cb_db.be_suffix = NULL;
   7768  1.1     lukem 		cfb->cb_db.be_nsuffix = NULL;
   7769  1.1     lukem 		BER_BVZERO( &cfb->cb_db.be_rootdn );
   7770  1.1     lukem 		BER_BVZERO( &cfb->cb_db.be_rootndn );
   7771  1.1     lukem 
   7772  1.1     lukem 		backend_destroy_one( &cfb->cb_db, 0 );
   7773  1.1     lukem 	}
   7774  1.1     lukem 
   7775  1.4  christos 	slap_loglevel_destroy();
   7776  1.1     lukem 
   7777  1.1     lukem 	return 0;
   7778  1.1     lukem }
   7779  1.1     lukem 
   7780  1.1     lukem static int
   7781  1.1     lukem config_back_db_init( BackendDB *be, ConfigReply* cr )
   7782  1.1     lukem {
   7783  1.1     lukem 	struct berval dn;
   7784  1.1     lukem 	CfBackInfo *cfb;
   7785  1.1     lukem 
   7786  1.1     lukem 	cfb = &cfBackInfo;
   7787  1.1     lukem 	cfb->cb_config = ch_calloc( 1, sizeof(ConfigFile));
   7788  1.1     lukem 	cfn = cfb->cb_config;
   7789  1.1     lukem 	be->be_private = cfb;
   7790  1.1     lukem 
   7791  1.1     lukem 	ber_dupbv( &be->be_rootdn, &config_rdn );
   7792  1.1     lukem 	ber_dupbv( &be->be_rootndn, &be->be_rootdn );
   7793  1.1     lukem 	ber_dupbv( &dn, &be->be_rootdn );
   7794  1.1     lukem 	ber_bvarray_add( &be->be_suffix, &dn );
   7795  1.1     lukem 	ber_dupbv( &dn, &be->be_rootdn );
   7796  1.1     lukem 	ber_bvarray_add( &be->be_nsuffix, &dn );
   7797  1.1     lukem 
   7798  1.4  christos 	ldap_pvt_thread_rdwr_init( &cfb->cb_rwlock );
   7799  1.4  christos 
   7800  1.1     lukem 	/* Hide from namingContexts */
   7801  1.1     lukem 	SLAP_BFLAGS(be) |= SLAP_BFLAG_CONFIG;
   7802  1.1     lukem 
   7803  1.2  christos 	/* Check ACLs on content of Adds by default */
   7804  1.2  christos 	SLAP_DBFLAGS(be) |= SLAP_DBFLAG_ACL_ADD;
   7805  1.2  christos 
   7806  1.1     lukem 	return 0;
   7807  1.1     lukem }
   7808  1.1     lukem 
   7809  1.1     lukem static int
   7810  1.1     lukem config_back_destroy( BackendInfo *bi )
   7811  1.1     lukem {
   7812  1.1     lukem 	ldif_must_b64_encode_release();
   7813  1.1     lukem 	return 0;
   7814  1.1     lukem }
   7815  1.1     lukem 
   7816  1.1     lukem static int
   7817  1.1     lukem config_tool_entry_open( BackendDB *be, int mode )
   7818  1.1     lukem {
   7819  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7820  1.1     lukem 	BackendInfo *bi = cfb->cb_db.bd_info;
   7821  1.1     lukem 
   7822  1.4  christos 	configDB = be;
   7823  1.1     lukem 	if ( bi && bi->bi_tool_entry_open )
   7824  1.1     lukem 		return bi->bi_tool_entry_open( &cfb->cb_db, mode );
   7825  1.1     lukem 	else
   7826  1.1     lukem 		return -1;
   7827  1.1     lukem 
   7828  1.1     lukem }
   7829  1.1     lukem 
   7830  1.1     lukem static int
   7831  1.1     lukem config_tool_entry_close( BackendDB *be )
   7832  1.1     lukem {
   7833  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7834  1.1     lukem 	BackendInfo *bi = cfb->cb_db.bd_info;
   7835  1.1     lukem 
   7836  1.1     lukem 	if ( bi && bi->bi_tool_entry_close )
   7837  1.1     lukem 		return bi->bi_tool_entry_close( &cfb->cb_db );
   7838  1.1     lukem 	else
   7839  1.1     lukem 		return -1;
   7840  1.1     lukem }
   7841  1.1     lukem 
   7842  1.1     lukem static ID
   7843  1.1     lukem config_tool_entry_first( BackendDB *be )
   7844  1.1     lukem {
   7845  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7846  1.1     lukem 	BackendInfo *bi = cfb->cb_db.bd_info;
   7847  1.1     lukem 
   7848  1.2  christos 	if ( bi && bi->bi_tool_entry_first ) {
   7849  1.1     lukem 		return bi->bi_tool_entry_first( &cfb->cb_db );
   7850  1.2  christos 	}
   7851  1.2  christos 	if ( bi && bi->bi_tool_entry_first_x ) {
   7852  1.2  christos 		return bi->bi_tool_entry_first_x( &cfb->cb_db,
   7853  1.2  christos 			NULL, LDAP_SCOPE_DEFAULT, NULL );
   7854  1.2  christos 	}
   7855  1.2  christos 	return NOID;
   7856  1.2  christos }
   7857  1.2  christos 
   7858  1.2  christos static ID
   7859  1.2  christos config_tool_entry_first_x(
   7860  1.2  christos 	BackendDB *be,
   7861  1.2  christos 	struct berval *base,
   7862  1.2  christos 	int scope,
   7863  1.2  christos 	Filter *f )
   7864  1.2  christos {
   7865  1.2  christos 	CfBackInfo *cfb = be->be_private;
   7866  1.2  christos 	BackendInfo *bi = cfb->cb_db.bd_info;
   7867  1.2  christos 
   7868  1.2  christos 	if ( bi && bi->bi_tool_entry_first_x ) {
   7869  1.2  christos 		return bi->bi_tool_entry_first_x( &cfb->cb_db, base, scope, f );
   7870  1.2  christos 	}
   7871  1.2  christos 	return NOID;
   7872  1.1     lukem }
   7873  1.1     lukem 
   7874  1.1     lukem static ID
   7875  1.1     lukem config_tool_entry_next( BackendDB *be )
   7876  1.1     lukem {
   7877  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7878  1.1     lukem 	BackendInfo *bi = cfb->cb_db.bd_info;
   7879  1.1     lukem 
   7880  1.1     lukem 	if ( bi && bi->bi_tool_entry_next )
   7881  1.1     lukem 		return bi->bi_tool_entry_next( &cfb->cb_db );
   7882  1.1     lukem 	else
   7883  1.1     lukem 		return NOID;
   7884  1.1     lukem }
   7885  1.1     lukem 
   7886  1.3  christos static ID
   7887  1.3  christos config_tool_dn2id_get( Backend *be, struct berval *dn )
   7888  1.3  christos {
   7889  1.3  christos 	CfBackInfo *cfb = be->be_private;
   7890  1.3  christos 	BackendInfo *bi = cfb->cb_db.bd_info;
   7891  1.3  christos 
   7892  1.3  christos 	if ( bi && bi->bi_tool_dn2id_get )
   7893  1.3  christos 		return bi->bi_tool_dn2id_get( &cfb->cb_db, dn );
   7894  1.3  christos 
   7895  1.3  christos 	return NOID;
   7896  1.3  christos }
   7897  1.3  christos 
   7898  1.1     lukem static Entry *
   7899  1.1     lukem config_tool_entry_get( BackendDB *be, ID id )
   7900  1.1     lukem {
   7901  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7902  1.1     lukem 	BackendInfo *bi = cfb->cb_db.bd_info;
   7903  1.1     lukem 
   7904  1.1     lukem 	if ( bi && bi->bi_tool_entry_get )
   7905  1.1     lukem 		return bi->bi_tool_entry_get( &cfb->cb_db, id );
   7906  1.1     lukem 	else
   7907  1.1     lukem 		return NULL;
   7908  1.1     lukem }
   7909  1.1     lukem 
   7910  1.1     lukem static int entry_put_got_frontend=0;
   7911  1.1     lukem static int entry_put_got_config=0;
   7912  1.1     lukem static ID
   7913  1.1     lukem config_tool_entry_put( BackendDB *be, Entry *e, struct berval *text )
   7914  1.1     lukem {
   7915  1.1     lukem 	CfBackInfo *cfb = be->be_private;
   7916  1.1     lukem 	BackendInfo *bi = cfb->cb_db.bd_info;
   7917  1.1     lukem 	int rc;
   7918  1.3  christos 	struct berval rdn;
   7919  1.1     lukem 	ConfigArgs ca;
   7920  1.1     lukem 	OperationBuffer opbuf;
   7921  1.1     lukem 	Entry *ce;
   7922  1.1     lukem 	Connection conn = {0};
   7923  1.1     lukem 	Operation *op = NULL;
   7924  1.1     lukem 	void *thrctx;
   7925  1.1     lukem 	int isFrontend = 0;
   7926  1.2  christos 	int isFrontendChild = 0;
   7927  1.1     lukem 
   7928  1.1     lukem 	/* Create entry for frontend database if it does not exist already */
   7929  1.1     lukem 	if ( !entry_put_got_frontend ) {
   7930  1.1     lukem 		if ( !strncmp( e->e_nname.bv_val, "olcDatabase",
   7931  1.1     lukem 				STRLENOF( "olcDatabase" ))) {
   7932  1.1     lukem 			if ( strncmp( e->e_nname.bv_val +
   7933  1.1     lukem 					STRLENOF( "olcDatabase" ), "={-1}frontend",
   7934  1.1     lukem 					STRLENOF( "={-1}frontend" )) &&
   7935  1.1     lukem 					strncmp( e->e_nname.bv_val +
   7936  1.1     lukem 					STRLENOF( "olcDatabase" ), "=frontend",
   7937  1.1     lukem 					STRLENOF( "=frontend" ))) {
   7938  1.1     lukem 				memset( &ca, 0, sizeof(ConfigArgs));
   7939  1.1     lukem 				ca.be = frontendDB;
   7940  1.1     lukem 				ca.bi = frontendDB->bd_info;
   7941  1.1     lukem 				ca.be->be_cf_ocs = &CFOC_FRONTEND;
   7942  1.1     lukem 				rdn.bv_val = ca.log;
   7943  1.1     lukem 				rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ),
   7944  1.1     lukem 					"%s=" SLAP_X_ORDERED_FMT "%s",
   7945  1.1     lukem 					cfAd_database->ad_cname.bv_val, -1,
   7946  1.1     lukem 					ca.bi->bi_type);
   7947  1.1     lukem 				ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn,
   7948  1.1     lukem 						&CFOC_DATABASE, ca.be->be_cf_ocs );
   7949  1.1     lukem 				thrctx = ldap_pvt_thread_pool_context();
   7950  1.1     lukem 				connection_fake_init2( &conn, &opbuf, thrctx,0 );
   7951  1.1     lukem 				op = &opbuf.ob_op;
   7952  1.1     lukem 				op->o_bd = &cfb->cb_db;
   7953  1.1     lukem 				op->o_tag = LDAP_REQ_ADD;
   7954  1.1     lukem 				op->ora_e = ce;
   7955  1.1     lukem 				op->o_dn = be->be_rootdn;
   7956  1.1     lukem 				op->o_ndn = be->be_rootndn;
   7957  1.1     lukem 				rc = slap_add_opattrs(op, NULL, NULL, 0, 0);
   7958  1.1     lukem 				if ( rc != LDAP_SUCCESS ) {
   7959  1.1     lukem 					text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed";
   7960  1.1     lukem 					text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
   7961  1.1     lukem 					return NOID;
   7962  1.1     lukem 				}
   7963  1.1     lukem 
   7964  1.1     lukem 				if ( ce && bi && bi->bi_tool_entry_put &&
   7965  1.1     lukem 						bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) {
   7966  1.1     lukem 					entry_put_got_frontend++;
   7967  1.1     lukem 				} else {
   7968  1.1     lukem 					text->bv_val = "autocreation of \"olcDatabase={-1}frontend\" failed";
   7969  1.1     lukem 					text->bv_len = STRLENOF("autocreation of \"olcDatabase={-1}frontend\" failed");
   7970  1.1     lukem 					return NOID;
   7971  1.1     lukem 				}
   7972  1.1     lukem 			} else {
   7973  1.1     lukem 				entry_put_got_frontend++;
   7974  1.1     lukem 				isFrontend = 1;
   7975  1.1     lukem 			}
   7976  1.1     lukem 		}
   7977  1.1     lukem 	}
   7978  1.2  christos 
   7979  1.2  christos 	/* Child entries of the frontend database, e.g. slapo-chain's back-ldap
   7980  1.2  christos 	 * instances, may appear before the config database entry in the ldif, skip
   7981  1.2  christos 	 * auto-creation of olcDatabase={0}config in such a case */
   7982  1.2  christos 	if ( !entry_put_got_config &&
   7983  1.2  christos 			!strncmp( e->e_nname.bv_val, "olcDatabase", STRLENOF( "olcDatabase" ))) {
   7984  1.2  christos 		struct berval pdn;
   7985  1.2  christos 		dnParent( &e->e_nname, &pdn );
   7986  1.2  christos 		while ( pdn.bv_len ) {
   7987  1.2  christos 			if ( !strncmp( pdn.bv_val, "olcDatabase",
   7988  1.2  christos 					STRLENOF( "olcDatabase" ))) {
   7989  1.2  christos 				if ( !strncmp( pdn.bv_val +
   7990  1.2  christos 						STRLENOF( "olcDatabase" ), "={-1}frontend",
   7991  1.2  christos 						STRLENOF( "={-1}frontend" )) ||
   7992  1.2  christos 						!strncmp( pdn.bv_val +
   7993  1.2  christos 						STRLENOF( "olcDatabase" ), "=frontend",
   7994  1.2  christos 						STRLENOF( "=frontend" ))) {
   7995  1.2  christos 
   7996  1.2  christos 					isFrontendChild = 1;
   7997  1.2  christos 					break;
   7998  1.2  christos 				}
   7999  1.2  christos 			}
   8000  1.2  christos 			dnParent( &pdn, &pdn );
   8001  1.2  christos 		}
   8002  1.2  christos 	}
   8003  1.2  christos 
   8004  1.1     lukem 	/* Create entry for config database if it does not exist already */
   8005  1.2  christos 	if ( !entry_put_got_config && !isFrontend && !isFrontendChild ) {
   8006  1.1     lukem 		if ( !strncmp( e->e_nname.bv_val, "olcDatabase",
   8007  1.1     lukem 				STRLENOF( "olcDatabase" ))) {
   8008  1.1     lukem 			if ( strncmp( e->e_nname.bv_val +
   8009  1.1     lukem 					STRLENOF( "olcDatabase" ), "={0}config",
   8010  1.1     lukem 					STRLENOF( "={0}config" )) &&
   8011  1.1     lukem 					strncmp( e->e_nname.bv_val +
   8012  1.1     lukem 					STRLENOF( "olcDatabase" ), "=config",
   8013  1.1     lukem 					STRLENOF( "=config" )) ) {
   8014  1.1     lukem 				memset( &ca, 0, sizeof(ConfigArgs));
   8015  1.1     lukem 				ca.be = LDAP_STAILQ_FIRST( &backendDB );
   8016  1.1     lukem 				ca.bi = ca.be->bd_info;
   8017  1.1     lukem 				rdn.bv_val = ca.log;
   8018  1.1     lukem 				rdn.bv_len = snprintf(rdn.bv_val, sizeof( ca.log ),
   8019  1.1     lukem 					"%s=" SLAP_X_ORDERED_FMT "%s",
   8020  1.1     lukem 					cfAd_database->ad_cname.bv_val, 0,
   8021  1.1     lukem 					ca.bi->bi_type);
   8022  1.1     lukem 				ce = config_build_entry( NULL, NULL, cfb->cb_root, &ca, &rdn, &CFOC_DATABASE,
   8023  1.1     lukem 						ca.be->be_cf_ocs );
   8024  1.1     lukem 				if ( ! op ) {
   8025  1.1     lukem 					thrctx = ldap_pvt_thread_pool_context();
   8026  1.1     lukem 					connection_fake_init2( &conn, &opbuf, thrctx,0 );
   8027  1.1     lukem 					op = &opbuf.ob_op;
   8028  1.1     lukem 					op->o_bd = &cfb->cb_db;
   8029  1.1     lukem 					op->o_tag = LDAP_REQ_ADD;
   8030  1.1     lukem 					op->o_dn = be->be_rootdn;
   8031  1.1     lukem 					op->o_ndn = be->be_rootndn;
   8032  1.1     lukem 				}
   8033  1.1     lukem 				op->ora_e = ce;
   8034  1.1     lukem 				rc = slap_add_opattrs(op, NULL, NULL, 0, 0);
   8035  1.1     lukem 				if ( rc != LDAP_SUCCESS ) {
   8036  1.1     lukem 					text->bv_val = "autocreation of \"olcDatabase={0}config\" failed";
   8037  1.1     lukem 					text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
   8038  1.1     lukem 					return NOID;
   8039  1.1     lukem 				}
   8040  1.1     lukem 				if (ce && bi && bi->bi_tool_entry_put &&
   8041  1.1     lukem 						bi->bi_tool_entry_put( &cfb->cb_db, ce, text ) != NOID ) {
   8042  1.1     lukem 					entry_put_got_config++;
   8043  1.1     lukem 				} else {
   8044  1.1     lukem 					text->bv_val = "autocreation of \"olcDatabase={0}config\" failed";
   8045  1.1     lukem 					text->bv_len = STRLENOF("autocreation of \"olcDatabase={0}config\" failed");
   8046  1.1     lukem 					return NOID;
   8047  1.1     lukem 				}
   8048  1.1     lukem 			} else {
   8049  1.1     lukem 				entry_put_got_config++;
   8050  1.1     lukem 			}
   8051  1.1     lukem 		}
   8052  1.1     lukem 	}
   8053  1.1     lukem 	if ( bi && bi->bi_tool_entry_put &&
   8054  1.1     lukem 		config_add_internal( cfb, e, &ca, NULL, NULL, NULL ) == 0 )
   8055  1.1     lukem 		return bi->bi_tool_entry_put( &cfb->cb_db, e, text );
   8056  1.3  christos 	else {
   8057  1.3  christos 		ber_str2bv( ca.cr_msg, 0, 0, text );
   8058  1.1     lukem 		return NOID;
   8059  1.3  christos 	}
   8060  1.3  christos }
   8061  1.3  christos 
   8062  1.3  christos static ID
   8063  1.3  christos config_tool_entry_modify( BackendDB *be, Entry *e, struct berval *text )
   8064  1.3  christos {
   8065  1.3  christos 	CfBackInfo *cfb = be->be_private;
   8066  1.3  christos 	BackendInfo *bi = cfb->cb_db.bd_info;
   8067  1.4  christos 	CfEntryInfo *ce, *last = NULL;
   8068  1.3  christos 
   8069  1.4  christos 	ce = config_find_base( cfb->cb_root, &e->e_nname, &last, NULL );
   8070  1.3  christos 
   8071  1.3  christos 	if ( ce && bi && bi->bi_tool_entry_modify )
   8072  1.3  christos 		return bi->bi_tool_entry_modify( &cfb->cb_db, e, text );
   8073  1.3  christos 
   8074  1.3  christos 	return NOID;
   8075  1.3  christos }
   8076  1.3  christos 
   8077  1.3  christos static int
   8078  1.3  christos config_tool_entry_delete( BackendDB *be, struct berval *ndn, struct berval *text )
   8079  1.3  christos {
   8080  1.3  christos 	CfBackInfo *cfb = be->be_private;
   8081  1.3  christos 	BackendInfo *bi = cfb->cb_db.bd_info;
   8082  1.4  christos 	CfEntryInfo *ce, *last = NULL;
   8083  1.3  christos 
   8084  1.4  christos 	ce = config_find_base( cfb->cb_root, ndn, &last, NULL );
   8085  1.3  christos 
   8086  1.3  christos 	if ( ce && bi && bi->bi_tool_entry_delete )
   8087  1.3  christos 		return bi->bi_tool_entry_delete( &cfb->cb_db, ndn, text );
   8088  1.3  christos 
   8089  1.3  christos 	return LDAP_OTHER;
   8090  1.1     lukem }
   8091  1.1     lukem 
   8092  1.1     lukem static struct {
   8093  1.1     lukem 	char *name;
   8094  1.1     lukem 	AttributeDescription **desc;
   8095  1.1     lukem } ads[] = {
   8096  1.1     lukem 	{ "attribute", &cfAd_attr },
   8097  1.1     lukem 	{ "backend", &cfAd_backend },
   8098  1.1     lukem 	{ "database", &cfAd_database },
   8099  1.1     lukem 	{ "include", &cfAd_include },
   8100  1.2  christos 	{ "ldapsyntax", &cfAd_syntax },
   8101  1.1     lukem 	{ "objectclass", &cfAd_oc },
   8102  1.1     lukem 	{ "objectidentifier", &cfAd_om },
   8103  1.1     lukem 	{ "overlay", &cfAd_overlay },
   8104  1.1     lukem 	{ NULL, NULL }
   8105  1.1     lukem };
   8106  1.1     lukem 
   8107  1.1     lukem /* Notes:
   8108  1.1     lukem  *   add / delete: all types that may be added or deleted must use an
   8109  1.1     lukem  * X-ORDERED attributeType for their RDN. Adding and deleting entries
   8110  1.1     lukem  * should automatically renumber the index of any siblings as needed,
   8111  1.1     lukem  * so that no gaps in the numbering sequence exist after the add/delete
   8112  1.1     lukem  * is completed.
   8113  1.1     lukem  *   What can be added:
   8114  1.1     lukem  *     schema objects
   8115  1.1     lukem  *     backend objects for backend-specific config directives
   8116  1.1     lukem  *     database objects
   8117  1.1     lukem  *     overlay objects
   8118  1.1     lukem  *
   8119  1.1     lukem  *   delete: probably no support this time around.
   8120  1.1     lukem  *
   8121  1.1     lukem  *   modrdn: generally not done. Will be invoked automatically by add/
   8122  1.1     lukem  * delete to update numbering sequence. Perform as an explicit operation
   8123  1.1     lukem  * so that the renumbering effect may be replicated. Subtree rename must
   8124  1.1     lukem  * be supported, since renumbering a database will affect all its child
   8125  1.1     lukem  * overlays.
   8126  1.1     lukem  *
   8127  1.1     lukem  *  modify: must be fully supported.
   8128  1.1     lukem  */
   8129  1.1     lukem 
   8130  1.1     lukem int
   8131  1.1     lukem config_back_initialize( BackendInfo *bi )
   8132  1.1     lukem {
   8133  1.1     lukem 	ConfigTable		*ct = config_back_cf_table;
   8134  1.1     lukem 	ConfigArgs ca;
   8135  1.1     lukem 	char			*argv[4];
   8136  1.1     lukem 	int			i;
   8137  1.1     lukem 	AttributeDescription	*ad = NULL;
   8138  1.1     lukem 	const char		*text;
   8139  1.1     lukem 	static char		*controls[] = {
   8140  1.1     lukem 		LDAP_CONTROL_MANAGEDSAIT,
   8141  1.4  christos 		LDAP_CONTROL_PRE_READ,
   8142  1.4  christos 		LDAP_CONTROL_POST_READ,
   8143  1.1     lukem 		NULL
   8144  1.1     lukem 	};
   8145  1.1     lukem 
   8146  1.1     lukem 	/* Make sure we don't exceed the bits reserved for userland */
   8147  1.1     lukem 	config_check_userland( CFG_LAST );
   8148  1.1     lukem 
   8149  1.1     lukem 	bi->bi_controls = controls;
   8150  1.1     lukem 
   8151  1.1     lukem 	bi->bi_open = 0;
   8152  1.1     lukem 	bi->bi_close = 0;
   8153  1.1     lukem 	bi->bi_config = 0;
   8154  1.1     lukem 	bi->bi_destroy = config_back_destroy;
   8155  1.1     lukem 
   8156  1.1     lukem 	bi->bi_db_init = config_back_db_init;
   8157  1.1     lukem 	bi->bi_db_config = 0;
   8158  1.1     lukem 	bi->bi_db_open = config_back_db_open;
   8159  1.1     lukem 	bi->bi_db_close = config_back_db_close;
   8160  1.1     lukem 	bi->bi_db_destroy = config_back_db_destroy;
   8161  1.1     lukem 
   8162  1.1     lukem 	bi->bi_op_bind = config_back_bind;
   8163  1.1     lukem 	bi->bi_op_unbind = 0;
   8164  1.1     lukem 	bi->bi_op_search = config_back_search;
   8165  1.1     lukem 	bi->bi_op_compare = 0;
   8166  1.1     lukem 	bi->bi_op_modify = config_back_modify;
   8167  1.1     lukem 	bi->bi_op_modrdn = config_back_modrdn;
   8168  1.1     lukem 	bi->bi_op_add = config_back_add;
   8169  1.1     lukem 	bi->bi_op_delete = config_back_delete;
   8170  1.1     lukem 	bi->bi_op_abandon = 0;
   8171  1.1     lukem 
   8172  1.1     lukem 	bi->bi_extended = 0;
   8173  1.1     lukem 
   8174  1.1     lukem 	bi->bi_chk_referrals = 0;
   8175  1.1     lukem 
   8176  1.1     lukem 	bi->bi_access_allowed = slap_access_allowed;
   8177  1.1     lukem 
   8178  1.1     lukem 	bi->bi_connection_init = 0;
   8179  1.1     lukem 	bi->bi_connection_destroy = 0;
   8180  1.1     lukem 
   8181  1.1     lukem 	bi->bi_entry_release_rw = config_entry_release;
   8182  1.1     lukem 	bi->bi_entry_get_rw = config_back_entry_get;
   8183  1.1     lukem 
   8184  1.1     lukem 	bi->bi_tool_entry_open = config_tool_entry_open;
   8185  1.1     lukem 	bi->bi_tool_entry_close = config_tool_entry_close;
   8186  1.1     lukem 	bi->bi_tool_entry_first = config_tool_entry_first;
   8187  1.2  christos 	bi->bi_tool_entry_first_x = config_tool_entry_first_x;
   8188  1.1     lukem 	bi->bi_tool_entry_next = config_tool_entry_next;
   8189  1.3  christos 	bi->bi_tool_dn2id_get = config_tool_dn2id_get;
   8190  1.1     lukem 	bi->bi_tool_entry_get = config_tool_entry_get;
   8191  1.1     lukem 	bi->bi_tool_entry_put = config_tool_entry_put;
   8192  1.3  christos 	bi->bi_tool_entry_modify = config_tool_entry_modify;
   8193  1.3  christos 	bi->bi_tool_entry_delete = config_tool_entry_delete;
   8194  1.1     lukem 
   8195  1.1     lukem 	ca.argv = argv;
   8196  1.1     lukem 	argv[ 0 ] = "slapd";
   8197  1.1     lukem 	ca.argv = argv;
   8198  1.1     lukem 	ca.argc = 3;
   8199  1.1     lukem 	ca.fname = argv[0];
   8200  1.1     lukem 
   8201  1.1     lukem 	argv[3] = NULL;
   8202  1.1     lukem 	for (i=0; OidMacros[i].name; i++ ) {
   8203  1.1     lukem 		argv[1] = OidMacros[i].name;
   8204  1.1     lukem 		argv[2] = OidMacros[i].oid;
   8205  1.1     lukem 		parse_oidm( &ca, 0, NULL );
   8206  1.1     lukem 	}
   8207  1.1     lukem 
   8208  1.1     lukem 	bi->bi_cf_ocs = cf_ocs;
   8209  1.1     lukem 
   8210  1.1     lukem 	i = config_register_schema( ct, cf_ocs );
   8211  1.1     lukem 	if ( i ) return i;
   8212  1.1     lukem 
   8213  1.2  christos 	i = slap_str2ad( "olcDatabase", &olcDatabaseDummy[0].ad, &text );
   8214  1.2  christos 	if ( i ) return i;
   8215  1.2  christos 
   8216  1.1     lukem 	/* setup olcRootPW to be base64-encoded when written in LDIF form;
   8217  1.1     lukem 	 * basically, we don't care if it fails */
   8218  1.1     lukem 	i = slap_str2ad( "olcRootPW", &ad, &text );
   8219  1.1     lukem 	if ( i ) {
   8220  1.1     lukem 		Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
   8221  1.1     lukem 			"warning, unable to get \"olcRootPW\" "
   8222  1.1     lukem 			"attribute description: %d: %s\n",
   8223  1.3  christos 			i, text );
   8224  1.1     lukem 	} else {
   8225  1.1     lukem 		(void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
   8226  1.1     lukem 			ad->ad_type->sat_oid );
   8227  1.1     lukem 	}
   8228  1.1     lukem 
   8229  1.1     lukem 	/* set up the notable AttributeDescriptions */
   8230  1.1     lukem 	i = 0;
   8231  1.1     lukem 	for (;ct->name;ct++) {
   8232  1.1     lukem 		if (strcmp(ct->name, ads[i].name)) continue;
   8233  1.1     lukem 		*ads[i].desc = ct->ad;
   8234  1.1     lukem 		i++;
   8235  1.1     lukem 		if (!ads[i].name) break;
   8236  1.1     lukem 	}
   8237  1.1     lukem 
   8238  1.1     lukem 	return 0;
   8239  1.1     lukem }
   8240