CFG_MIRRORMODE,
CFG_HIDDEN,
CFG_MONITORING,
+ CFG_SERVERID,
CFG_LAST
};
{ "OLcfgBkOc", "OLcfgOc:1" },
{ "OLcfgDbOc", "OLcfgOc:2" },
{ "OLcfgOvOc", "OLcfgOc:3" },
+
+ /* Syntaxes. We should just start using the standard names and
+ * document that they are predefined and available for users
+ * to reference in their own schema. Defining schema without
+ * OID macros is for masochists...
+ */
{ "OMsyn", "1.3.6.1.4.1.1466.115.121.1" },
{ "OMsBoolean", "OMsyn:7" },
{ "OMsDN", "OMsyn:12" },
&global_idletimeout, "( OLcfgGlAt:18 NAME 'olcIdleTimeout' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
{ "include", "file", 2, 2, 0, ARG_MAGIC,
- &config_include, "( OLcfgGlAt:19 NAME 'olcInclude' "
- "SUP labeledURI )", NULL, NULL },
+ &config_include, NULL, NULL, NULL },
{ "index_substr_if_minlen", "min", 2, 2, 0, ARG_INT|ARG_NONZERO|ARG_MAGIC|CFG_SSTR_IF_MIN,
&config_generic, "( OLcfgGlAt:20 NAME 'olcIndexSubstrIfMinLen' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
&config_security, "( OLcfgGlAt:59 NAME 'olcSecurity' "
"EQUALITY caseIgnoreMatch "
"SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "serverID", "number> <[URI]", 2, 3, 0, ARG_MAGIC|CFG_SERVERID,
+ &config_generic, "( OLcfgGlAt:81 NAME 'olcServerID' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
{ "sizelimit", "limit", 2, 0, 0, ARG_MAY_DB|ARG_MAGIC,
&config_sizelimit, "( OLcfgGlAt:60 NAME 'olcSizeLimit' "
"SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
"SYNTAX OMsDN )", NULL, NULL },
{ "syncrepl", NULL, 0, 0, 0, ARG_DB|ARG_MAGIC,
&syncrepl_config, "( OLcfgDbAt:0.11 NAME 'olcSyncrepl' "
- "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString X-ORDERED 'VALUES' )", NULL, NULL },
{ "threads", "count", 2, 2, 0,
#ifdef NO_THREADS
ARG_IGNORED, NULL,
};
/* Routines to check if a child can be added to this type */
-static ConfigLDAPadd cfAddSchema, cfAddInclude, cfAddDatabase,
+static ConfigLDAPadd cfAddSchema, cfAddDatabase,
cfAddBackend, cfAddModule, cfAddOverlay;
/* NOTE: be careful when defining array members
#define CFOC_BACKEND cf_ocs[3]
#define CFOC_DATABASE cf_ocs[4]
#define CFOC_OVERLAY cf_ocs[5]
-#define CFOC_INCLUDE cf_ocs[6]
-#define CFOC_FRONTEND cf_ocs[7]
+#define CFOC_FRONTEND cf_ocs[6]
#ifdef SLAPD_MODULES
-#define CFOC_MODULE cf_ocs[8]
+#define CFOC_MODULE cf_ocs[7]
#endif /* SLAPD_MODULES */
static ConfigOCs cf_ocs[] = {
"olcReplogFile $ olcRequires $ olcRestrict $ olcReverseLookup $ "
"olcRootDSE $ "
"olcSaslHost $ olcSaslRealm $ olcSaslSecProps $ "
- "olcSecurity $ olcSizeLimit $ "
+ "olcSecurity $ olcServerID $ olcSizeLimit $ "
"olcSockbufMaxIncoming $ olcSockbufMaxIncomingAuth $ "
"olcThreads $ olcTimeLimit $ olcTLSCACertificateFile $ "
"olcTLSCACertificatePath $ olcTLSCertificateFile $ "
"DESC 'OpenLDAP Overlay-specific options' "
"SUP olcConfig STRUCTURAL "
"MUST olcOverlay )", Cft_Overlay, NULL, cfAddOverlay },
- { "( OLcfgGlOc:6 "
- "NAME 'olcIncludeFile' "
- "DESC 'OpenLDAP configuration include file' "
- "SUP olcConfig STRUCTURAL "
- "MUST olcInclude "
- "MAY ( cn $ olcRootDSE ) )",
- Cft_Include, NULL, cfAddInclude },
/* This should be STRUCTURAL like all the other database classes, but
* that would mean inheriting all of the olcDatabaseConfig attributes,
* which causes them to be merged twice in config_build_entry.
{ NULL, 0, NULL }
};
+typedef struct ServerID {
+ struct ServerID *si_next;
+ struct berval si_url;
+ int si_num;
+} ServerID;
+
+static ServerID *sid_list;
+
static int
config_generic(ConfigArgs *c) {
int i;
}
}
break;
+ case CFG_SERVERID:
+ if ( sid_list ) {
+ ServerID *si;
+ struct berval bv;
+ char *ptr;
+
+ for ( si = sid_list; si; si=si->si_next ) {
+ if ( !BER_BVISEMPTY( &si->si_url )) {
+ bv.bv_len = si->si_url.bv_len + 6;
+ bv.bv_val = ch_malloc( bv.bv_len );
+ sprintf( bv.bv_val, "%d %s", si->si_num,
+ si->si_url.bv_val );
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ } else {
+ char buf[5];
+ bv.bv_val = buf;
+ bv.bv_len = sprintf( buf, "%d", si->si_num );
+ value_add_one( &c->rvalue_vals, &bv );
+ }
+ }
+ } else {
+ rc = 1;
+ }
+ break;
case CFG_LOGFILE:
if ( logfileName )
c->value_string = ch_strdup( logfileName );
logfileName = NULL;
break;
+ case CFG_SERVERID: {
+ int i;
+ ServerID *si, **sip;
+
+ for ( i=0, si = sid_list, sip = &sid_list;
+ si; si = *sip, i++ ) {
+ if ( c->valx == -1 || i == c->valx ) {
+ *sip = si->si_next;
+ ch_free( si );
+ if ( c->valx >= 0 )
+ break;
+ } else {
+ sip = &si->si_next;
+ }
+ }
+ }
+ break;
case CFG_HIDDEN:
c->be->be_flags &= ~SLAP_DBFLAG_HIDDEN;
break;
}
break;
+ case CFG_SERVERID:
+ {
+ ServerID *si, **sip;
+ LDAPURLDesc *lud;
+ int num = atoi( c->argv[1] );
+ if ( num < 0 || num > SLAP_SYNC_SID_MAX ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "<%s> illegal server ID", c->argv[0] );
+ Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+ c->log, c->msg, c->argv[1] );
+ return 1;
+ }
+ /* only one value allowed if no URL is given */
+ if ( c->argc > 2 ) {
+ int len;
+
+ if ( sid_list && BER_BVISEMPTY( &sid_list->si_url )) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "<%s> only one server ID allowed now", c->argv[0] );
+ Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+ c->log, c->msg, c->argv[1] );
+ return 1;
+ }
+
+ if ( ldap_url_parse( c->argv[2], &lud )) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "<%s> invalid URL", c->argv[0] );
+ Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+ c->log, c->msg, c->argv[2] );
+ return 1;
+ }
+ len = strlen( c->argv[2] );
+ si = ch_malloc( sizeof(ServerID) + len + 1 );
+ si->si_url.bv_val = (char *)(si+1);
+ si->si_url.bv_len = len;
+ strcpy( si->si_url.bv_val, c->argv[2] );
+ } else {
+ if ( sid_list ) {
+ snprintf( c->msg, sizeof( c->msg ),
+ "<%s> unqualified server ID not allowed now", c->argv[0] );
+ Debug(LDAP_DEBUG_ANY, "%s: %s %s\n",
+ c->log, c->msg, c->argv[1] );
+ return 1;
+ }
+ si = ch_malloc( sizeof(ServerID) );
+ slap_serverID = num;
+ }
+ si->si_next = NULL;
+ si->si_num = num;
+ for ( sip = &sid_list; *sip; sip = &(*sip)->si_next );
+ *sip = si;
+
+ if (( slapMode & SLAP_SERVER_MODE ) && c->argc > 2 ) {
+ /* If hostname is empty, or is localhost, or matches
+ * our hostname, this serverID refers to this host.
+ * Compare it against listeners and ports.
+ */
+ if ( !lud->lud_host || !lud->lud_host[0] ||
+ !strncasecmp("localhost", lud->lud_host,
+ STRLENOF("localhost")) ||
+ !strcasecmp( global_host, lud->lud_host )) {
+ Listener **l = slapd_get_listeners();
+ int i;
+
+ for ( i=0; l[i]; i++ ) {
+ LDAPURLDesc *lu2;
+ int isMe = 0;
+ ldap_url_parse( l[i]->sl_url.bv_val, &lu2 );
+ do {
+ if ( strcasecmp( lud->lud_scheme,
+ lu2->lud_scheme ))
+ break;
+ if ( lud->lud_port != lu2->lud_port )
+ break;
+ /* Listener on ANY address */
+ if ( !lu2->lud_host || !lu2->lud_host[0] ) {
+ isMe = 1;
+ break;
+ }
+ /* URL on ANY address */
+ if ( !lud->lud_host || !lud->lud_host[0] ) {
+ isMe = 1;
+ break;
+ }
+ /* Listener has specific host, must
+ * match it
+ */
+ if ( !strcasecmp( lud->lud_host,
+ lu2->lud_host )) {
+ isMe = 1;
+ break;
+ }
+ } while(0);
+ ldap_free_urldesc( lu2 );
+ if ( isMe ) {
+ slap_serverID = si->si_num;
+ break;
+ }
+ }
+ }
+ }
+ if ( c->argc > 2 )
+ ldap_free_urldesc( lud );
+ }
+ break;
case CFG_LOGFILE: {
FILE *logfile;
if ( logfileName ) ch_free( logfileName );
ConfigFile *cf;
ConfigFile *cfsave = cfn;
ConfigFile *cf2 = NULL;
- if (c->op == SLAP_CONFIG_EMIT) {
- if (c->private) {
- ConfigFile *cf = c->private;
- value_add_one( &c->rvalue_vals, &cf->c_file );
- return 0;
- }
- return 1;
- } else if ( c->op == LDAP_MOD_DELETE ) {
- }
+
+ /* No dynamic config for include files */
cf = ch_calloc( 1, sizeof(ConfigFile));
if ( cfn->c_kids ) {
for (cf2=cfn->c_kids; cf2 && cf2->c_sibs; cf2=cf2->c_sibs) ;
if ( use_ldif ) {
CfBackInfo *cfb = (CfBackInfo *)op->o_bd->be_private;
BackendDB *be = op->o_bd;
- slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+ slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
struct berval dn, ndn, xdn, xndn;
op->o_bd = &cfb->cb_db;
op->o_req_dn = odn;
op->o_req_ndn = ondn;
- sc.sc_next = op->o_callback;
+ scp = op->o_callback;
op->o_callback = ≻
op->orr_newrdn = *newrdn;
op->orr_nnewrdn = *nnewrdn;
+ op->orr_newSup = NULL;
+ op->orr_nnewSup = NULL;
op->orr_deleteoldrdn = 1;
op->orr_modlist = NULL;
slap_modrdn2mods( op, rs );
+ slap_mods_opattrs( op, &op->orr_modlist, 1 );
rc = op->o_bd->be_modrdn( op, rs );
slap_mods_free( op->orr_modlist, 1 );
op->o_bd = be;
- op->o_callback = sc.sc_next;
+ op->o_callback = scp;
op->o_dn = dn;
op->o_ndn = ndn;
op->o_req_dn = xdn;
if ( ce_type == Cft_Global ) return 0;
if ( ce_type == Cft_Schema && parent->ce_type == Cft_Global ) return 0;
- if ( ce_type == Cft_Include || ce_type == Cft_Module )
+ if ( ce_type == Cft_Module )
tailindex = 1;
/* See if the rdn has an index already */
}
}
- if ( !isfrontend && index == -1 )
- index = 0;
-
/* count related kids */
for (nsibs=0, ce=parent->ce_kids; ce; ce=ce->ce_sibs) {
if ( ce->ce_type == ce_type ) nsibs++;
}
+ /* account for -1 frontend */
+ if ( ce_type == Cft_Database )
+ nsibs--;
+
if ( index != nsibs ) {
if ( gotindex ) {
if ( index < nsibs ) {
if ( tailindex ) return LDAP_NAMING_VIOLATION;
/* Siblings need to be renumbered */
- renumber = 1;
+ if ( index != -1 || !isfrontend )
+ renumber = 1;
}
}
+ if ( !isfrontend && index == -1 ) {
+ index = nsibs;
+ }
+
/* just make index = nsibs */
if ( !renumber ) {
rc = config_renumber_one( NULL, rs, parent, e, index, tailindex, 0 );
return colst;
}
-static int
-cfAddInclude( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
-{
- if ( p->ce_type != Cft_Global && p->ce_type != Cft_Include )
- return LDAP_CONSTRAINT_VIOLATION;
-
- /* If we're reading from a configdir, don't parse this entry */
- if ( ca->lineno )
- return LDAP_COMPARE_TRUE;
-
- cfn = p->ce_private;
- ca->private = cfn;
- return LDAP_SUCCESS;
-}
-
static int
cfAddSchema( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
{
return LDAP_SUCCESS;
}
+static void
+schema_destroy_one( ConfigArgs *ca, ConfigOCs **colst, int nocs,
+ CfEntryInfo *p )
+{
+ ConfigTable *ct;
+ ConfigFile *cfo;
+ AttributeDescription *ad;
+ const char *text;
+
+ ca->valx = -1;
+ ca->line = NULL;
+ if ( cfn->c_cr_head ) {
+ struct berval bv = BER_BVC("olcDitContentRules");
+ ad = NULL;
+ slap_bv2ad( &bv, &ad, &text );
+ ct = config_find_table( colst, nocs, ad );
+ config_del_vals( ct, ca );
+ }
+ if ( cfn->c_oc_head ) {
+ struct berval bv = BER_BVC("olcObjectClasses");
+ ad = NULL;
+ slap_bv2ad( &bv, &ad, &text );
+ ct = config_find_table( colst, nocs, ad );
+ config_del_vals( ct, ca );
+ }
+ if ( cfn->c_at_head ) {
+ struct berval bv = BER_BVC("olcAttributeTypes");
+ ad = NULL;
+ slap_bv2ad( &bv, &ad, &text );
+ ct = config_find_table( colst, nocs, ad );
+ config_del_vals( ct, ca );
+ }
+ if ( cfn->c_om_head ) {
+ struct berval bv = BER_BVC("olcObjectIdentifier");
+ ad = NULL;
+ slap_bv2ad( &bv, &ad, &text );
+ ct = config_find_table( colst, nocs, ad );
+ config_del_vals( ct, ca );
+ }
+ cfo = p->ce_private;
+ cfo->c_kids = cfn->c_sibs;
+ ch_free( cfn );
+}
+
/* Parse an LDAP entry into config directives */
static int
config_add_internal( CfBackInfo *cfb, Entry *e, ConfigArgs *ca, SlapReply *rs,
ConfigTable *ct;
char *ptr;
+ memset( ca, 0, sizeof(ConfigArgs));
+
/* Make sure parent exists and entry does not. But allow
- * Databases and Overlays to be inserted.
+ * Databases and Overlays to be inserted. Don't do any
+ * auto-renumbering if manageDSAit control is present.
*/
ce = config_find_base( cfb->cb_root, &e->e_nname, &last );
- if ( ce && ce->ce_type != Cft_Database &&
- ce->ce_type != Cft_Overlay )
+ if ( ce ) {
+ if (( op && op->o_managedsait ) ||
+ ( ce->ce_type != Cft_Database && ce->ce_type != Cft_Overlay &&
+ ce->ce_type != Cft_Module ))
return LDAP_ALREADY_EXISTS;
+ }
dnParent( &e->e_nname, &pdn );
oc_at = attr_find( e->e_attrs, slap_schema.si_ad_objectClass );
if ( !oc_at ) return LDAP_OBJECT_CLASS_VIOLATION;
- memset( ca, 0, sizeof(ConfigArgs));
-
/* Fake the coordinates based on whether we're part of an
* LDAP Add or if reading the config dir
*/
ca->fname = cfdir.bv_val;
ca->lineno = 1;
}
+ ca->ca_op = op;
colst = count_ocs( oc_at, &nocs );
}
if ( rc != LDAP_SUCCESS )
- goto done;
+ goto done_noop;
/* Parse all the values and check for simple syntax errors before
* performing any set actions.
rc = check_name_index( last, colst[0]->co_type, e, rs, renum,
&ibase );
if ( rc ) {
- goto done;
+ goto done_noop;
}
if ( renum && *renum && colst[0]->co_type != Cft_Database &&
colst[0]->co_type != Cft_Overlay ) {
snprintf( ca->msg, sizeof( ca->msg ),
"operation requires sibling renumbering" );
rc = LDAP_UNWILLING_TO_PERFORM;
- goto done;
+ goto done_noop;
}
}
ct = config_find_table( colst, nocs, a->a_desc );
if ( !ct ) continue; /* user data? */
rc = check_vals( ct, ca, a, 1 );
- if ( rc ) goto done;
+ if ( rc ) goto done_noop;
}
/* Basic syntax checks are OK. Do the actual settings. */
/* Advance to first of this type */
cprev = &last->ce_kids;
- for ( c2 = *cprev; c2 && c2->ce_type != ce->ce_type; ) {
+ for ( c2 = *cprev; c2 && c2->ce_type < ce->ce_type; ) {
cprev = &c2->ce_sibs;
c2 = c2->ce_sibs;
}
backend_destroy_one( ca->be, 1 );
} else if ( (colst[0]->co_type == Cft_Overlay) && ca->bi ) {
overlay_destroy_one( ca->be, (slap_overinst *)ca->bi );
+ } else if ( colst[0]->co_type == Cft_Schema ) {
+ schema_destroy_one( ca, colst, nocs, last );
}
}
+done_noop:
ch_free( ca->argv );
if ( colst ) ch_free( colst );
cfb = (CfBackInfo *)op->o_bd->be_private;
+ /* add opattrs for syncprov */
+ {
+ char textbuf[SLAP_TEXT_BUFLEN];
+ size_t textlen = sizeof textbuf;
+ rs->sr_err = entry_schema_check(op, op->ora_e, NULL, 0, 1,
+ &rs->sr_text, textbuf, sizeof( textbuf ) );
+ if ( rs->sr_err != LDAP_SUCCESS )
+ goto out;
+ rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 );
+ if ( rs->sr_err != LDAP_SUCCESS ) {
+ Debug( LDAP_DEBUG_TRACE,
+ LDAP_XSTRING(config_back_add) ": entry failed op attrs add: "
+ "%s (%d)\n", rs->sr_text, rs->sr_err, 0 );
+ goto out;
+ }
+ }
+
ldap_pvt_thread_pool_pause( &connection_pool );
/* Strategy:
if ( cfb->cb_use_ldif ) {
BackendDB *be = op->o_bd;
- slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+ slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
struct berval dn, ndn;
op->o_bd = &cfb->cb_db;
op->o_dn = op->o_bd->be_rootdn;
op->o_ndn = op->o_bd->be_rootndn;
- sc.sc_next = op->o_callback;
+ scp = op->o_callback;
op->o_callback = ≻
op->o_bd->be_add( op, rs );
op->o_bd = be;
- op->o_callback = sc.sc_next;
+ op->o_callback = scp;
op->o_dn = dn;
op->o_ndn = ndn;
}
out:;
send_ldap_result( op, rs );
+ slap_graduate_commit_csn( op );
return rs->sr_err;
}
int idx[1];
} delrec;
+static int
+config_modify_add( ConfigTable *ct, ConfigArgs *ca, AttributeDescription *ad,
+ int i )
+{
+ int rc;
+
+ if (ad->ad_type->sat_flags & SLAP_AT_ORDERED &&
+ ca->line[0] == '{' )
+ {
+ char *ptr = strchr( ca->line + 1, '}' );
+ if ( ptr ) {
+ char *next;
+
+ ca->valx = strtol( ca->line + 1, &next, 0 );
+ if ( next == ca->line + 1 || next[ 0 ] != '}' ) {
+ return LDAP_OTHER;
+ }
+ ca->line = ptr+1;
+ }
+ }
+ rc = config_parse_add( ct, ca, i );
+ if ( rc ) {
+ rc = LDAP_OTHER;
+ }
+ return rc;
+}
+
static int
config_modify_internal( CfEntryInfo *ce, Operation *op, SlapReply *rs,
ConfigArgs *ca )
int rc = LDAP_UNWILLING_TO_PERFORM;
Modifications *ml;
Entry *e = ce->ce_entry;
- Attribute *save_attrs = e->e_attrs, *oc_at;
+ Attribute *save_attrs = e->e_attrs, *oc_at, *s, *a;
ConfigTable *ct;
ConfigOCs **colst;
int i, nocs;
colst = count_ocs( oc_at, &nocs );
+ /* make sure add/del flags are clear; should always be true */
+ for ( s = save_attrs; s; s = s->a_next ) {
+ s->a_flags &= ~(SLAP_ATTR_IXADD|SLAP_ATTR_IXDEL);
+ }
+
e->e_attrs = attrs_dup( e->e_attrs );
init_config_argv( ca );
ca->private = ce->ce_private;
ca->ca_entry = e;
ca->fname = "slapd";
+ ca->ca_op = op;
strcpy( ca->log, "back-config" );
for (ml = op->orm_modlist; ml; ml=ml->sml_next) {
rc = LDAP_OTHER;
snprintf(ca->msg, sizeof(ca->msg), "cannot delete %s",
ml->sml_desc->ad_cname.bv_val );
- goto out;
+ goto out_noop;
}
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
vals = ml->sml_values;
rc = LDAP_OTHER;
snprintf(ca->msg, sizeof(ca->msg), "cannot insert %s",
ml->sml_desc->ad_cname.bv_val );
- goto out;
+ goto out_noop;
}
}
rc = check_vals( ct, ca, ml, 0 );
- if ( rc ) goto out;
+ if ( rc ) goto out_noop;
}
}
rc = modify_add_values(e, &ml->sml_mod,
if(rc != LDAP_SUCCESS) break;
}
- if(rc == LDAP_SUCCESS) {
+ if ( rc == LDAP_SUCCESS) {
/* check that the entry still obeys the schema */
rc = entry_schema_check(op, e, NULL, 0, 0,
&rs->sr_text, ca->msg, sizeof(ca->msg) );
+ if ( rc ) goto out_noop;
}
- if ( rc == LDAP_SUCCESS ) {
- /* Basic syntax checks are OK. Do the actual settings. */
- for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
- ct = config_find_table( colst, nocs, ml->sml_desc );
- if ( !ct ) continue;
-
- switch (ml->sml_op) {
- case LDAP_MOD_DELETE:
- case LDAP_MOD_REPLACE: {
- BerVarray vals = NULL, nvals = NULL;
- Attribute *a;
- delrec *d = NULL;
-
- a = attr_find( e->e_attrs, ml->sml_desc );
-
- if ( ml->sml_op == LDAP_MOD_REPLACE ) {
- vals = ml->sml_values;
- nvals = ml->sml_nvalues;
- ml->sml_values = NULL;
- ml->sml_nvalues = NULL;
- }
+ /* Basic syntax checks are OK. Do the actual settings. */
+ for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) {
+ ct = config_find_table( colst, nocs, ml->sml_desc );
+ if ( !ct ) continue;
- if ( ml->sml_values )
- d = dels;
+ s = attr_find( save_attrs, ml->sml_desc );
+ a = attr_find( e->e_attrs, ml->sml_desc );
- /* If we didn't delete the whole attribute */
- if ( ml->sml_values && a ) {
- struct berval *mvals;
- int j;
+ switch (ml->sml_op) {
+ case LDAP_MOD_DELETE:
+ case LDAP_MOD_REPLACE: {
+ BerVarray vals = NULL, nvals = NULL;
+ delrec *d = NULL;
- if ( ml->sml_nvalues )
- mvals = ml->sml_nvalues;
- else
- mvals = ml->sml_values;
-
- /* use the indexes we saved up above */
- for (i=0; i < d->nidx; i++) {
- struct berval bv = *mvals++;
- if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
- bv.bv_val[0] == '{' ) {
- ptr = strchr( bv.bv_val, '}' ) + 1;
- bv.bv_len -= ptr - bv.bv_val;
- bv.bv_val = ptr;
- }
- ca->line = bv.bv_val;
- ca->valx = d->idx[i];
- rc = config_del_vals( ct, ca );
- if ( rc != LDAP_SUCCESS ) break;
- for (j=i+1; j < d->nidx; j++)
- if ( d->idx[j] >d->idx[i] )
- d->idx[j]--;
+ if ( ml->sml_op == LDAP_MOD_REPLACE ) {
+ vals = ml->sml_values;
+ nvals = ml->sml_nvalues;
+ ml->sml_values = NULL;
+ ml->sml_nvalues = NULL;
+ }
+
+ if ( ml->sml_values )
+ d = dels;
+
+ /* If we didn't delete the whole attribute */
+ if ( ml->sml_values && a ) {
+ struct berval *mvals;
+ int j;
+
+ if ( ml->sml_nvalues )
+ mvals = ml->sml_nvalues;
+ else
+ mvals = ml->sml_values;
+
+ /* use the indexes we saved up above */
+ for (i=0; i < d->nidx; i++) {
+ struct berval bv = *mvals++;
+ if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
+ bv.bv_val[0] == '{' ) {
+ ptr = strchr( bv.bv_val, '}' ) + 1;
+ bv.bv_len -= ptr - bv.bv_val;
+ bv.bv_val = ptr;
}
- } else {
- ca->valx = -1;
- ca->line = NULL;
+ ca->line = bv.bv_val;
+ ca->valx = d->idx[i];
rc = config_del_vals( ct, ca );
- if ( rc ) rc = LDAP_OTHER;
- }
- if ( ml->sml_values ) {
- d = d->next;
- ch_free( dels );
- dels = d;
- }
- if ( ml->sml_op == LDAP_MOD_REPLACE ) {
- ml->sml_values = vals;
- ml->sml_nvalues = nvals;
- }
- if ( !vals || rc != LDAP_SUCCESS )
- break;
+ if ( rc != LDAP_SUCCESS ) break;
+ if ( s )
+ s->a_flags |= SLAP_ATTR_IXDEL;
+ for (j=i+1; j < d->nidx; j++)
+ if ( d->idx[j] >d->idx[i] )
+ d->idx[j]--;
}
- /* FALLTHRU: LDAP_MOD_REPLACE && vals */
+ } else {
+ ca->valx = -1;
+ ca->line = NULL;
+ rc = config_del_vals( ct, ca );
+ if ( rc ) rc = LDAP_OTHER;
+ if ( s )
+ s->a_flags |= SLAP_ATTR_IXDEL;
+ }
+ if ( ml->sml_values ) {
+ d = d->next;
+ ch_free( dels );
+ dels = d;
+ }
+ if ( ml->sml_op == LDAP_MOD_REPLACE ) {
+ ml->sml_values = vals;
+ ml->sml_nvalues = nvals;
+ }
+ if ( !vals || rc != LDAP_SUCCESS )
+ break;
+ }
+ /* FALLTHRU: LDAP_MOD_REPLACE && vals */
+
+ case LDAP_MOD_ADD:
+ for (i=0; ml->sml_values[i].bv_val; i++) {
+ ca->line = ml->sml_values[i].bv_val;
+ ca->valx = -1;
+ rc = config_modify_add( ct, ca, ml->sml_desc, i );
+ if ( rc )
+ goto out;
+ a->a_flags |= SLAP_ATTR_IXADD;
+ }
+ break;
+ }
+ }
- case LDAP_MOD_ADD:
- for (i=0; ml->sml_values[i].bv_val; i++) {
- ca->line = ml->sml_values[i].bv_val;
+out:
+ /* Undo for a failed operation */
+ if ( rc != LDAP_SUCCESS ) {
+ for ( s = save_attrs; s; s = s->a_next ) {
+ if ( s->a_flags & SLAP_ATTR_IXDEL ) {
+ s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
+ ct = config_find_table( colst, nocs, s->a_desc );
+ a = attr_find( e->e_attrs, s->a_desc );
+ if ( a ) {
+ /* clear the flag so the add check below will skip it */
+ a->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
ca->valx = -1;
- if ( ml->sml_desc->ad_type->sat_flags & SLAP_AT_ORDERED &&
- ca->line[0] == '{' )
- {
- ptr = strchr( ca->line + 1, '}' );
- if ( ptr ) {
- char *next;
-
- ca->valx = strtol( ca->line + 1, &next, 0 );
- if ( next == ca->line + 1 || next[ 0 ] != '}' ) {
- rc = LDAP_OTHER;
- goto out;
- }
- ca->line = ptr+1;
- }
- }
- rc = config_parse_add( ct, ca, i );
- if ( rc ) {
- rc = LDAP_OTHER;
- goto out;
+ ca->line = NULL;
+ config_del_vals( ct, ca );
+ }
+ for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) {
+ ca->line = s->a_vals[i].bv_val;
+ ca->valx = -1;
+ config_modify_add( ct, ca, s->a_desc, i );
+ }
+ }
+ }
+ for ( a = e->e_attrs; a; a = a->a_next ) {
+ if ( a->a_flags & SLAP_ATTR_IXADD ) {
+ ct = config_find_table( colst, nocs, a->a_desc );
+ ca->valx = -1;
+ ca->line = NULL;
+ config_del_vals( ct, ca );
+ s = attr_find( save_attrs, a->a_desc );
+ if ( s ) {
+ s->a_flags &= ~(SLAP_ATTR_IXDEL|SLAP_ATTR_IXADD);
+ for ( i=0; !BER_BVISNULL( &s->a_vals[i] ); i++ ) {
+ ca->line = s->a_vals[i].bv_val;
+ ca->valx = -1;
+ config_modify_add( ct, ca, s->a_desc, i );
}
}
-
- break;
}
}
}
-out:
if ( ca->cleanup )
ca->cleanup( ca );
+out_noop:
if ( rc == LDAP_SUCCESS ) {
attrs_free( save_attrs );
} else {
}
}
- ldap_pvt_thread_pool_pause( &connection_pool );
+ slap_mods_opattrs( op, &op->orm_modlist, 1 );
+
+ if ( !slapd_shutdown )
+ ldap_pvt_thread_pool_pause( &connection_pool );
/* Strategy:
* 1) perform the Modify on the cached Entry.
rs->sr_text = ca.msg;
} else if ( cfb->cb_use_ldif ) {
BackendDB *be = op->o_bd;
- slap_callback sc = { NULL, slap_null_cb, NULL, NULL };
+ slap_callback sc = { NULL, slap_null_cb, NULL, NULL }, *scp;
struct berval dn, ndn;
op->o_bd = &cfb->cb_db;
op->o_dn = op->o_bd->be_rootdn;
op->o_ndn = op->o_bd->be_rootndn;
- sc.sc_next = op->o_callback;
+ scp = op->o_callback;
op->o_callback = ≻
op->o_bd->be_modify( op, rs );
op->o_bd = be;
- op->o_callback = sc.sc_next;
+ op->o_callback = scp;
op->o_dn = dn;
op->o_ndn = ndn;
}
- ldap_pvt_thread_pool_resume( &connection_pool );
+ if ( !slapd_shutdown )
+ ldap_pvt_thread_pool_resume( &connection_pool );
out:
send_ldap_result( op, rs );
+ slap_graduate_commit_csn( op );
return rs->sr_err;
}
return 0;
}
+/* no-op, we never free entries */
+int config_entry_release(
+ Operation *op,
+ Entry *e,
+ int rw )
+{
+ return LDAP_SUCCESS;
+}
+
+/* return LDAP_SUCCESS IFF we can retrieve the specified entry.
+ */
+int config_back_entry_get(
+ Operation *op,
+ struct berval *ndn,
+ ObjectClass *oc,
+ AttributeDescription *at,
+ int rw,
+ Entry **ent )
+{
+ CfBackInfo *cfb;
+ CfEntryInfo *ce, *last;
+
+ cfb = (CfBackInfo *)op->o_bd->be_private;
+
+ ce = config_find_base( cfb->cb_root, ndn, &last );
+ if ( ce ) {
+ *ent = ce->ce_entry;
+ if ( *ent && oc && !is_entry_objectclass_or_sub( *ent, oc ) ) {
+ *ent = NULL;
+ }
+ }
+
+ return ( *ent == NULL ? 1 : 0 );
+}
+
static void
config_build_attrs( Entry *e, AttributeType **at, AttributeDescription *ad,
ConfigTable *ct, ConfigArgs *c )
Debug( LDAP_DEBUG_TRACE, "config_build_entry: \"%s\"\n", rdn->bv_val, 0, 0);
e->e_private = ce;
ce->ce_entry = e;
+ ce->ce_type = main->co_type;
ce->ce_parent = parent;
if ( parent ) {
pdn = parent->ce_entry->e_nname;
if ( parent->ce_kids )
- for ( ceprev = parent->ce_kids; ceprev->ce_sibs;
+ for ( ceprev = parent->ce_kids; ceprev->ce_sibs &&
+ ceprev->ce_type <= ce->ce_type;
ceprev = ceprev->ce_sibs );
} else {
BER_BVZERO( &pdn );
}
- ce->ce_type = main->co_type;
ce->ce_private = c->private;
ce->ce_be = c->be;
ce->ce_bi = c->bi;
attr_merge_normalize_one(e, slap_schema.si_ad_structuralObjectClass, &oc->soc_cname, NULL );
if ( op && !op->o_noop ) {
op->ora_e = e;
+ op->ora_modlist = NULL;
op->o_bd->be_add( op, rs );
if ( ( rs->sr_err != LDAP_SUCCESS )
&& (rs->sr_err != LDAP_ALREADY_EXISTS) ) {
}
}
if ( ceprev ) {
+ ce->ce_sibs = ceprev->ce_sibs;
ceprev->ce_sibs = ce;
} else if ( parent ) {
+ ce->ce_sibs = parent->ce_kids;
parent->ce_kids = ce;
}
return 0;
}
-static int
-config_build_includes( ConfigArgs *c, CfEntryInfo *ceparent,
- Operation *op, SlapReply *rs )
-{
- Entry *e;
- int i;
- ConfigFile *cf = c->private;
-
- for (i=0; cf; cf=cf->c_sibs, i++) {
- c->value_dn.bv_val = c->log;
- c->value_dn.bv_len = snprintf(c->value_dn.bv_val, sizeof( c->log ), "cn=include" SLAP_X_ORDERED_FMT, i);
- if ( c->value_dn.bv_len >= sizeof( c->log ) ) {
- /* FIXME: how can indicate error? */
- return -1;
- }
- c->private = cf;
- e = config_build_entry( op, rs, ceparent, c, &c->value_dn,
- &CFOC_INCLUDE, NULL );
- if ( ! e ) {
- return -1;
- } else if ( e && cf->c_kids ) {
- c->private = cf->c_kids;
- config_build_includes( c, e->e_private, op, rs );
- }
- }
- return 0;
-}
-
#ifdef SLAPD_MODULES
static int
parent = e;
ceparent = ce;
- /* Create includeFile nodes */
- if ( cfb->cb_config->c_kids ) {
- c.depth = 0;
- c.private = cfb->cb_config->c_kids;
- if ( config_build_includes( &c, ceparent, op, &rs ) ) {
- return -1;
- }
- }
-
#ifdef SLAPD_MODULES
/* Create Module nodes... */
if ( modpaths.mp_loads ) {
bi->bi_connection_init = 0;
bi->bi_connection_destroy = 0;
+ bi->bi_entry_release_rw = config_entry_release;
+ bi->bi_entry_get_rw = config_back_entry_get;
+
bi->bi_tool_entry_open = config_tool_entry_open;
bi->bi_tool_entry_close = config_tool_entry_close;
bi->bi_tool_entry_first = config_tool_entry_first;