/* * Create a new protocol instance. */ Repl_Protocol * prot_new(Repl_Agmt *agmt, int protocol_state) { Slapi_DN *replarea_sdn = NULL; Repl_Protocol *rp = (Repl_Protocol *)slapi_ch_calloc(1, sizeof(Repl_Protocol)); rp->prp_incremental = rp->prp_total = rp->prp_active_protocol = NULL; if (protocol_state == STATE_PERFORMING_TOTAL_UPDATE) { rp->state = STATE_PERFORMING_TOTAL_UPDATE; } else { rp->state = STATE_PERFORMING_INCREMENTAL_UPDATE; } rp->next_state = STATE_PERFORMING_INCREMENTAL_UPDATE; if ((rp->lock = PR_NewLock()) == NULL) { goto loser; } rp->agmt = agmt; rp->conn = NULL; /* Acquire the local replica object */ replarea_sdn = agmt_get_replarea(agmt); rp->replica_object = replica_get_replica_from_dn(replarea_sdn); if (NULL == rp->replica_object) { /* Whoa, no local replica!?!? */ slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "prot_new - %s: Unable to locate replica object for local replica %s\n", agmt_get_long_name(agmt), slapi_sdn_get_dn(replarea_sdn)); goto loser; } if (get_agmt_agreement_type(agmt) == REPLICA_TYPE_MULTIMASTER) { rp->prp_incremental = private_protocol_factory(rp, PROTOCOL_5_INCREMENTAL); rp->prp_total = private_protocol_factory(rp, PROTOCOL_5_TOTAL); rp->delete_conn = conn_delete; } else if (get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS) { rp->prp_incremental = private_protocol_factory(rp, PROTOCOL_WINDOWS_INCREMENTAL); rp->prp_total = private_protocol_factory(rp, PROTOCOL_WINDOWS_TOTAL); rp->delete_conn = windows_conn_delete; } /* XXXggood register callback handlers for entries updated, and schedule window enter/leave. */ goto done; loser: prot_delete(&rp); done: slapi_sdn_free(&replarea_sdn); return rp; }
static int agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry *e, int *returncode, char *returntext, void *arg) { int i; Slapi_DN *sdn = NULL; int start_initialize = 0, stop_initialize = 0, cancel_initialize = 0; int update_the_schedule = 0; /* do we need to update the repl sched? */ Repl_Agmt *agmt = NULL; LDAPMod **mods; char buff [SLAPI_DSE_RETURNTEXT_SIZE]; char *errortext = returntext ? returntext : buff; int rc = SLAPI_DSE_CALLBACK_OK; Slapi_Operation *op; void *identity; *returncode = LDAP_SUCCESS; /* just let internal operations originated from replication plugin to go through */ slapi_pblock_get (pb, SLAPI_OPERATION, &op); slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity); if (operation_is_flag_set(op, OP_FLAG_INTERNAL) && (identity == repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION))) { goto done; } slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn); if (NULL == sdn) { slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmtlist_modify_callback: NULL target dn\n"); goto done; } agmt = agmtlist_get_by_agmt_name(sdn); if (NULL == agmt) { slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmtlist_modify_callback: received " "a modification for unknown replication agreement \"%s\"\n", slapi_sdn_get_dn(sdn)); goto done; } slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); for (i = 0; NULL != mods && NULL != mods[i]; i++) { if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaInitialize)) { /* we don't allow delete attribute operations unless it was issued by the replication plugin - handled above */ if (mods[i]->mod_op & LDAP_MOD_DELETE) { if(strcasecmp (mods[i]->mod_type, type_nsds5ReplicaCleanRUVnotified) == 0){ /* allow the deletion of cleanallruv agmt attr */ continue; } slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "deletion of %s attribute is not allowed\n", type_nsds5ReplicaInitialize); *returncode = LDAP_UNWILLING_TO_PERFORM; rc = SLAPI_DSE_CALLBACK_ERROR; break; } else { char *val; if (mods[i]->mod_bvalues && mods[i]->mod_bvalues[0]) val = slapi_berval_get_string_copy (mods[i]->mod_bvalues[0]); else { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "no value provided for %s attribute\n", type_nsds5ReplicaInitialize); *returncode = LDAP_UNWILLING_TO_PERFORM; rc = SLAPI_DSE_CALLBACK_ERROR; break; } /* Start replica initialization */ if (val == NULL) { PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "No value supplied for attr (%s)", mods[i]->mod_type); slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: %s\n", errortext); *returncode = LDAP_UNWILLING_TO_PERFORM; rc = SLAPI_DSE_CALLBACK_ERROR; break; } if (strcasecmp (val, "start") == 0) { start_initialize = 1; } else if (strcasecmp (val, "stop") == 0) { stop_initialize = 1; } else if (strcasecmp (val, "cancel") == 0) { cancel_initialize = 1; } else { PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "Invalid value (%s) value supplied for attr (%s)", val, mods[i]->mod_type); slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: %s\n", errortext); } slapi_ch_free ((void**)&val); } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaUpdateSchedule)) { /* * Request to update the replication schedule. Set a flag so * we know to update the schedule later. */ update_the_schedule = 1; } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaCredentials)) { /* New replica credentials */ if (agmt_set_credentials_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update credentials for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaTimeout)) { /* New replica timeout */ if (agmt_set_timeout_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update timeout for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaBusyWaitTime)) { /* New replica busywaittime */ if (agmt_set_busywaittime_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update busy wait time for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaSessionPauseTime)) { /* New replica pausetime */ if (agmt_set_pausetime_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update session pause time for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaBindDN)) { /* New replica Bind DN */ if (agmt_set_binddn_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update bind DN for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaPort)) { /* New replica port */ if (agmt_set_port_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update port for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5TransportInfo)) { /* New Transport info */ if (agmt_set_transportinfo_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update transport info for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaBindMethod)) { if (agmt_set_bind_method_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update bind method for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicatedAttributeList)) { char **denied_attrs = NULL; /* New set of excluded attributes */ if (agmt_set_replicated_attributes_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update replicated attributes for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } /* Check that there are no verboten attributes in the exclude list */ denied_attrs = agmt_validate_replicated_attributes(agmt, 0 /* incremental */); if (denied_attrs) { /* Report the error to the client */ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "attempt to exclude an illegal attribute in a fractional agreement"); slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "attempt to exclude an illegal attribute in a fractional agreement\n"); *returncode = LDAP_UNWILLING_TO_PERFORM; rc = SLAPI_DSE_CALLBACK_ERROR; /* Free the deny list if we got one */ slapi_ch_array_free(denied_attrs); break; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicatedAttributeListTotal)) { char **denied_attrs = NULL; /* New set of excluded attributes */ if (agmt_set_replicated_attributes_total_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update total update replicated attributes for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } /* Check that there are no verboten attributes in the exclude list */ denied_attrs = agmt_validate_replicated_attributes(agmt, 1 /* total */); if (denied_attrs) { /* Report the error to the client */ PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE, "attempt to exclude an illegal total update " "attribute in a fractional agreement"); slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "attempt to exclude an illegal total update attribute in a fractional agreement\n"); *returncode = LDAP_UNWILLING_TO_PERFORM; rc = SLAPI_DSE_CALLBACK_ERROR; /* Free the deny list if we got one */ slapi_ch_array_free(denied_attrs); break; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, "nsds5debugreplicatimeout")) { char *val = slapi_entry_attr_get_charptr(e, "nsds5debugreplicatimeout"); repl5_set_debug_timeout(val); slapi_ch_free_string(&val); } else if (strcasecmp (mods[i]->mod_type, "modifytimestamp") == 0 || strcasecmp (mods[i]->mod_type, "modifiersname") == 0 || strcasecmp (mods[i]->mod_type, "description") == 0) { /* ignore modifier's name and timestamp attributes and the description. */ continue; } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaEnabled)) { if(agmt_set_enabled_from_entry(agmt, e, returntext) != 0){ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to set replica agmt state \"enabled/disabled\" for %s\n",agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (slapi_attr_types_equivalent(mods[i]->mod_type, type_nsds5ReplicaStripAttrs)) { if(agmt_set_attrs_to_strip(agmt, e) != 0){ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to set replica agmt attributes to strip for %s\n",agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (0 == windows_handle_modify_agreement(agmt, mods[i]->mod_type, e)) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "modification of %s attribute is not allowed\n", mods[i]->mod_type); *returncode = LDAP_UNWILLING_TO_PERFORM; rc = SLAPI_DSE_CALLBACK_ERROR; break; } } if (stop_initialize) { agmt_stop (agmt); } else if (start_initialize) { if (agmt_initialize_replica(agmt) != 0) { /* The suffix/repl agmt is disabled */ agmt_set_last_init_status(agmt, 0, NSDS50_REPL_DISABLED, NULL); if(agmt_is_enabled(agmt)){ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Suffix is disabled"); } else { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "Replication agreement is disabled"); } *returncode = LDAP_UNWILLING_TO_PERFORM; rc = SLAPI_DSE_CALLBACK_ERROR; } } else if (cancel_initialize) { agmt_replica_init_done(agmt); } if (update_the_schedule) { if (agmt_set_schedule_from_entry(agmt, e) != 0) { slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " "failed to update replication schedule for agreement %s\n", agmt_get_long_name(agmt)); *returncode = LDAP_OPERATIONS_ERROR; rc = SLAPI_DSE_CALLBACK_ERROR; } } done: if (NULL != agmt) { agmtlist_release_agmt(agmt); } return rc; }