Branch '389-ds-base-1.3.1' - ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5.h | 1
ldap/servers/plugins/replication/repl5_replica_config.c | 314 +++++++++-------
ldap/servers/plugins/replication/repl_extop.c | 53 --
3 files changed, 188 insertions(+), 180 deletions(-)
New commits:
commit b80706245e0a04e34d2c532ea4acf758886e3037
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Sep 17 10:53:12 2013 -0400
Ticket 47509 - CLEANALLRUV doesnt run across all replicas
Bug Description: If one of the replicas in the environment is older and does not support
cleanallruv, then this would cause the cleanallruv task to never complete.
Fix Description: Several issues are addressed with this fix:
- Corrected error handling of replicas that do not support cleanallruv(prevent task hanging)
- Created helper function to get local maxcsn: replica_cleanallruv_get_local_maxcsn().
This code was taken from the extended op "multimaster_extop_cleanruv_get_maxcsn".
- Improved replica_cleanallruv_find_maxcsn() to also include the local maxcsn, and not just the remote replicas.
- Improved abort task processing. Abort task now waits for the cleanallruv task to be aborted before continuing.
- Improved task configuration cleanup. Removed places where the config attribute value was manually created.
Now we search for the exact value to delete.
https://fedorahosted.org/389/ticket/47509
Reviewed by: richm(Thanks!!)
(cherry picked from commit 26253234c7b1c69286d8cde8f5e000bae946b6a5)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 6752ac8..5bec1c7 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -656,6 +656,7 @@ void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root, int sk
int is_pre_cleaned_rid(ReplicaId rid);
void set_cleaned_rid(ReplicaId rid);
void cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...);
+char * replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn);
#define CLEANRIDSIZ 4 /* maximum number for concurrent CLEANALLRUV tasks */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index 79ac5b0..fb0b746 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1834,7 +1834,7 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
int rc = -1;
if((conn = conn_new(agmt)) == NULL){
- return -1;
+ return rc;
}
if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
payload = create_cleanruv_payload(filter);
@@ -1848,7 +1848,10 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
char *response = NULL;
decode_cleanruv_payload(retsdata, &response);
- if(response && strcmp(response,CLEANRUV_FINISHED) == 0){
+ if(response == NULL){
+ /* this replica does not support cleanallruv */
+ rc = 0;
+ } else if(strcmp(response,CLEANRUV_FINISHED) == 0){
/* finished cleaning */
rc = 0;
}
@@ -1858,8 +1861,6 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
slapi_ch_free_string(&retoid);
}
}
- } else {
- rc = -1;
}
conn_delete_internal_ext(conn);
if(payload)
@@ -2114,16 +2115,16 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data)
val.bv_val = data;
mods[0] = &mod;
mods[1] = NULL;
- repl_dn = slapi_create_dn_string("cn=replica,cn=%s,cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn));
+ repl_dn = slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn));
/*
* Add task to remote replica
*/
rc = ldap_modify_ext_s( ld, repl_dn, mods, NULL, NULL);
if(rc != LDAP_SUCCESS){
- cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task replica "
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task (%s) to replica "
"(%s). You will need to manually run the CLEANRUV task on this replica (%s) error (%d)",
- agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc);
+ repl_dn, agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc);
}
slapi_ch_free_string(&repl_dn);
slapi_sdn_free(&sdn);
@@ -2349,7 +2350,6 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
} else {
/* only remove the config, leave the in-memory rid */
dn = replica_get_dn(r);
- pb = slapi_pblock_new();
data = PR_smprintf("%d:%s", (int)rid, repl_root);
mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
@@ -2362,6 +2362,7 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
mods[0] = &mod;
mods[1] = NULL;
+ pb = slapi_pblock_new();
slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
slapi_modify_internal_pb (pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
@@ -2381,40 +2382,29 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
static void
delete_cleaned_rid_config(cleanruv_data *clean_data)
{
- Slapi_PBlock *pb;
+ Slapi_PBlock *pb, *modpb;
Slapi_Entry **entries = NULL;
LDAPMod *mods[2];
LDAPMod mod;
- struct berval *vals[2];
- struct berval val;
- char data[CSN_STRSIZE + 15];
- char *csnstr = NULL;
+ struct berval *vals[5]= {0, 0, 0, 0, 0}; /* maximum of 4 tasks */
+ struct berval val[5];
char *iter = NULL;
- char *dn;
- int found = 0, i;
- int rc, ret, rid;
+ char *dn = NULL;
+ int i, ii;
+ int rc = -1, ret, rid;
if(clean_data == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "delete_cleaned_rid_config: cleanruv data is NULL, "
- "failed to clean the config.\n");
+ cleanruv_log(NULL, CLEANALLRUV_ID, "delete_cleaned_rid_config: cleanruv data is NULL, "
+ "failed to clean the config.");
return;
}
/*
- * If there is no maxcsn, set the proper csnstr
- */
- csnstr = csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr);
- if ((csnstr == NULL) || (csn_get_replicaid(clean_data->maxcsn) == 0)) {
- slapi_ch_free_string(&csnstr); /* no problem to pass NULL */
- csnstr = slapi_ch_strdup("00000000000000000000");
- }
- /*
* Search the config for the exact attribute value to delete
*/
pb = slapi_pblock_new();
if(clean_data->replica){
dn = replica_get_dn(clean_data->replica);
} else {
- rc = -1;
goto bail;
}
@@ -2424,72 +2414,81 @@ delete_cleaned_rid_config(cleanruv_data *clean_data)
slapi_search_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
if (ret != LDAP_SUCCESS){
- /*
- * Search failed, manually build the attr value
- */
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
- (int)clean_data->rid, csnstr, clean_data->force);
- slapi_pblock_destroy(pb);
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: internal search failed(%d).",ret);
+ goto bail;
} else {
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
if (entries == NULL || entries[0] == NULL){
/*
- * Entry not found, manually build the attr value
+ * No matching entries!
*/
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
- (int)clean_data->rid, csnstr, clean_data->force);
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: failed to find any "
+ "entries with nsds5ReplicaCleanRUV under (%s)", dn);
+ goto bail;
} else {
- char **attr_val = slapi_entry_attr_get_charray(entries[0], "nsds5ReplicaCleanRUV");
-
- for (i = 0; attr_val && attr_val[i] && !found; i++){
- /* make a copy to retain the full value after toking */
- char *aval = slapi_ch_strdup(attr_val[i]);
-
- rid = atoi(ldap_utf8strtok_r(attr_val[i], ":", &iter));
- if(rid == clean_data->rid){
- /* found it */
- found = 1;
- val.bv_len = PR_snprintf(data, sizeof(data), "%s", aval);
+ /*
+ * Clean all the matching entries
+ */
+ for(i = 0; entries[i] != NULL;i++){
+ char **attr_val = slapi_entry_attr_get_charray(entries[i], type_replicaCleanRUV);
+ char *edn = slapi_entry_get_dn(entries[i]);
+ int count = 0;
+
+ for (ii = 0; attr_val && attr_val[ii] && i < 5; ii++){
+ /* make a copy to retain the full value after toking */
+ char *aval = slapi_ch_strdup(attr_val[ii]);
+
+ rid = atoi(ldap_utf8strtok_r(attr_val[ii], ":", &iter));
+ if(rid == clean_data->rid){
+ val[count].bv_len = strlen(aval);
+ val[count].bv_val = aval;
+ vals[count] = &val[count];
+ count++;
+ } else {
+ slapi_ch_free_string(&aval);
+ }
}
- slapi_ch_free_string(&aval);
- }
- if(!found){
+ slapi_ch_array_free(attr_val);
+
/*
- * No match, manually build the attr value
+ * Now delete the attribute
*/
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
- (int)clean_data->rid, csnstr, clean_data->force);
+ vals[5] = NULL;
+ mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
+ mod.mod_type = (char *)type_replicaCleanRUV;
+ mod.mod_bvalues = vals;
+ mods[0] = &mod;
+ mods[1] = NULL;
+
+ modpb = slapi_pblock_new();
+ slapi_modify_internal_set_pb(modpb, edn, mods, NULL, NULL,
+ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_modify_internal_pb (modpb);
+ slapi_pblock_get(modpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ slapi_pblock_destroy(modpb);
+
+ /* free the attr vals */
+ for (ii = 0; ii < count; ii++){
+ slapi_ch_free_string(&val[ii].bv_val);
+ }
+
+ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove task data "
+ "from (%s) error (%d), rid (%d)", edn, rc, clean_data->rid);
+ goto bail;
+ }
}
- slapi_ch_array_free(attr_val);
}
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
}
- /*
- * Now delete the attribute
- */
- mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
- mod.mod_type = (char *)type_replicaCleanRUV;
- mod.mod_bvalues = vals;
- vals [0] = &val;
- vals [1] = NULL;
- val.bv_val = data;
- mods[0] = &mod;
- mods[1] = NULL;
- pb = slapi_pblock_new();
- slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
-
bail:
if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config "
- "(%d), rid (%d)\n", rc, clean_data->rid);
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove replica config "
+ "(%d), rid (%d)", rc, clean_data->rid);
}
+ slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
slapi_ch_free_string(&dn);
- slapi_ch_free_string(&csnstr);
}
/*
@@ -2694,6 +2693,7 @@ replica_abort_task_thread(void *arg)
int agmt_not_notified = 1;
int interval = 10;
int release_it = 0;
+ int count = 0, rc = 0;
cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid);
@@ -2772,6 +2772,20 @@ done:
cleanruv_log(data->task, ABORT_CLEANALLRUV_ID,"Abort task failed, will resume the task at the next server startup.");
} else {
/*
+ * Wait for this server to stop its cleanallruv task(which removes the rid from the cleaned list)
+ */
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Waiting for CleanAllRUV task to abort...");
+ while(is_cleaned_rid(data->rid)){
+ DS_Sleep(PR_SecondsToInterval(1));
+ count++;
+ if(count == 60){ /* it should not take this long */
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "CleanAllRUV task failed to abort. You might need to "
+ "rerun the task.");
+ rc = -1;
+ break;
+ }
+ }
+ /*
* Clean up the config
*/
delete_aborted_rid(data->replica, data->rid, data->repl_root, 1); /* delete just the config, leave rid in memory */
@@ -2779,8 +2793,13 @@ done:
check_replicas_are_done_aborting(data);
}
delete_aborted_rid(data->replica, data->rid, data->repl_root, 0); /* remove the in-memory aborted rid */
- cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid);
+ if(rc == 0){
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid);
+ } else {
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Failed to abort task for rid(%d)",data->rid);
+ }
}
+
if(data->task){
slapi_task_finish(data->task, agmt_not_notified);
}
@@ -2858,6 +2877,7 @@ replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int che
* add the CLEANRUV task to the replica.
*/
replica_send_cleanruv_task(ra, clean_data);
+ rc = 0;
}
if (NULL != retsdata)
ber_bvfree(retsdata);
@@ -2881,72 +2901,49 @@ replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn)
{
Object *agmt_obj;
Repl_Agmt *agmt;
- char *rid_text;
CSN *maxcsn = NULL, *topcsn = NULL;
- int done = 1, found = 0;
- int interval = 10;
+ char *rid_text = slapi_ch_smprintf("%d", rid);
+ char *csnstr = NULL;
- rid_text = slapi_ch_smprintf("%d", rid);
+ /* start with the local maxcsn */
+ csnstr = replica_cleanallruv_get_local_maxcsn(rid, basedn);
+ if(csnstr){
+ topcsn = csn_new();
+ csn_init_by_string(topcsn, csnstr);
+ slapi_ch_free_string(&csnstr);
+ }
- while(done && !is_task_aborted(rid) && !slapi_is_shutting_down()){
- agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
- if(agmt_obj == NULL){
- break;
+ agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
+ if(agmt_obj == NULL){ /* no agreements */
+ goto done;
+ }
+ while (agmt_obj && !slapi_is_shutting_down()){
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ continue;
}
- while (agmt_obj && !slapi_is_shutting_down()){
- agmt = (Repl_Agmt*)object_get_data (agmt_obj);
- if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
+ if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){
+ if(maxcsn == NULL){
agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
- done = 0;
continue;
}
- if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){
- if(maxcsn == NULL){
- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
- continue;
- }
- found = 1;
- if(topcsn == NULL){
+ if(topcsn == NULL){
+ topcsn = maxcsn;
+ } else {
+ if(csn_compare(topcsn, maxcsn) < 0){
+ csn_free(&topcsn);
topcsn = maxcsn;
} else {
- if(csn_compare(topcsn, maxcsn) < 0){
- csn_free(&topcsn);
- topcsn = maxcsn;
- } else {
- csn_free(&maxcsn);
- }
+ csn_free(&maxcsn);
}
- done = 0;
- } else {
- done = 1;
- break;
}
- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
- } /* agmt while */
- if(done == 0 || is_task_aborted(rid) ){
- break;
- }
- if(!found){
- /* we could not find any maxcsn's - already cleaned? */
- return NULL;
- }
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: "
- "Not all replicas online, retrying in %d seconds\n", interval);
- PR_Lock( notify_lock );
- PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) );
- PR_Unlock( notify_lock );
-
- if(interval < 14400){ /* 4 hour max */
- interval = interval * 2;
- } else {
- interval = 14400;
}
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
}
- slapi_ch_free_string(&rid_text);
- if(is_task_aborted(rid)){
- return NULL;
- }
+done:
+ slapi_ch_free_string(&rid_text);
return topcsn;
}
@@ -3229,3 +3226,64 @@ cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...)
va_end(ap4);
}
+char *
+replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn)
+{
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL;
+ char **ruv_elements = NULL;
+ char *maxcsn = NULL;
+ char *filter = NULL;
+ char *ridstr = NULL;
+ char *iter = NULL;
+ char *attrs[2];
+ char *ruv_part = NULL;
+ int part_count = 0;
+ int res, i;
+
+ /*
+ * Get the maxruv from the database tombstone entry
+ */
+ filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))";
+ attrs[0] = "nsds50ruv";
+ attrs[1] = NULL;
+ ridstr = slapi_ch_smprintf("{replica %d ldap", rid);
+
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_search_internal_pb (search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
+
+ if ( LDAP_SUCCESS == res ) {
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if (NULL == entries || entries[0] == NULL) {
+ /* Hmmm, no tombstone! Error out */
+ } else {
+ /* find the right ruv element, and find the maxcsn */
+ ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]);
+ for(i = 0; ruv_elements && ruv_elements[i] ; i++){
+ if(strstr(ruv_elements[i], ridstr)){
+ /* get the max csn */
+ ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter);
+ for(part_count = 1; ruv_part && part_count < 5; part_count++){
+ ruv_part = ldap_utf8strtok_r(iter, " ", &iter);
+ }
+ if(part_count == 5 && ruv_part){/* we have the maxcsn */
+ maxcsn = slapi_ch_strdup(ruv_part);
+ break;
+ }
+ }
+ }
+ slapi_ch_array_free(ruv_elements);
+ }
+ } else {
+ /* internal search failed */
+ cleanruv_log(NULL, CLEANALLRUV_ID, "replica_cleanallruv_get_local_maxcsn: internal search failed (%d)\n", res);
+ }
+
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+ slapi_ch_free_string(&ridstr);
+
+ return maxcsn;
+}
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index f41cc7d..57249a6 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -1784,26 +1784,16 @@ free_and_return:
int
multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
{
- Slapi_PBlock *search_pb = NULL;
- Slapi_Entry **entries = NULL;
struct berval *resp_bval = NULL;
struct berval *extop_payload;
BerElement *resp_bere = NULL;
- char **ruv_elements = NULL;
char *extop_oid = NULL;
- char *ruv_part = NULL;
char *base_dn = NULL;
char *payload = NULL;
char *maxcsn = NULL;
- char *filter = NULL;
- char *ridstr = NULL;
char *iter = NULL;
- char *attrs[2];
- int part_count = 0;
int rid = 0;
- int res = 0;
int rc = LDAP_OPERATIONS_ERROR;
- int i = 0;
slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload);
@@ -1822,45 +1812,7 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
}
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
base_dn = ldap_utf8strtok_r(iter, ":", &iter);
- /*
- * Get the maxruv from the database tombstone entry
- */
- filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))";
- attrs[0] = "nsds50ruv";
- attrs[1] = NULL;
- ridstr = slapi_ch_smprintf("{replica %d ldap", rid);
-
- search_pb = slapi_pblock_new();
- slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_search_internal_pb (search_pb);
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
-
- if ( LDAP_SUCCESS == res ) {
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (NULL == entries || entries[0] == NULL) {
- /* Hmmm, no tombstpne! Error out */
- } else {
- /* find the right ruv element, and find the maxcsn */
- ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]);
- for(i = 0; ruv_elements && ruv_elements[i] ; i++){
- if(strstr(ruv_elements[i], ridstr)){
- /* get the max csn */
- ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter);
- for(part_count = 1; ruv_part && part_count < 5; part_count++){
- ruv_part = ldap_utf8strtok_r(iter, " ", &iter);
- }
- if(part_count == 5 && ruv_part){/* we have the maxcsn */
- maxcsn = slapi_ch_strdup(ruv_part);
- break;
- }
- }
- }
- slapi_ch_array_free(ruv_elements);
- }
- } else {
- /* internal search failed */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Get MaxCSN Task: internal search failed (%d)\n", res);
- }
+ maxcsn = replica_cleanallruv_get_local_maxcsn(rid, base_dn);
if(maxcsn == NULL){
maxcsn = slapi_ch_strdup(CLEANRUV_NO_MAXCSN);
}
@@ -1889,11 +1841,8 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
}
free_and_return:
- slapi_free_search_results_internal(search_pb);
- slapi_pblock_destroy(search_pb);
slapi_ch_free_string(&payload);
slapi_ch_free_string(&maxcsn);
- slapi_ch_free_string(&ridstr);
return rc;
}
10 years, 7 months
ldap/servers
by Mark Reynolds
ldap/servers/plugins/replication/repl5.h | 1
ldap/servers/plugins/replication/repl5_replica_config.c | 314 +++++++++-------
ldap/servers/plugins/replication/repl_extop.c | 53 --
3 files changed, 188 insertions(+), 180 deletions(-)
New commits:
commit 26253234c7b1c69286d8cde8f5e000bae946b6a5
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Sep 17 10:53:12 2013 -0400
Ticket 47509 - CLEANALLRUV doesnt run across all replicas
Bug Description: If one of the replicas in the environment is older and does not support
cleanallruv, then this would cause the cleanallruv task to never complete.
Fix Description: Several issues are addressed with this fix:
- Corrected error handling of replicas that do not support cleanallruv(prevent task hanging)
- Created helper function to get local maxcsn: replica_cleanallruv_get_local_maxcsn().
This code was taken from the extended op "multimaster_extop_cleanruv_get_maxcsn".
- Improved replica_cleanallruv_find_maxcsn() to also include the local maxcsn, and not just the remote replicas.
- Improved abort task processing. Abort task now waits for the cleanallruv task to be aborted before continuing.
- Improved task configuration cleanup. Removed places where the config attribute value was manually created.
Now we search for the exact value to delete.
https://fedorahosted.org/389/ticket/47509
Reviewed by: richm(Thanks!!)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index fc11232..19fed0c 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -661,6 +661,7 @@ void delete_aborted_rid(Replica *replica, ReplicaId rid, char *repl_root, int sk
int is_pre_cleaned_rid(ReplicaId rid);
void set_cleaned_rid(ReplicaId rid);
void cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...);
+char * replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn);
#define CLEANRIDSIZ 4 /* maximum number for concurrent CLEANALLRUV tasks */
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index b6a2d72..f0c9e14 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -1909,7 +1909,7 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
int rc = -1;
if((conn = conn_new(agmt)) == NULL){
- return -1;
+ return rc;
}
if(conn_connect(conn) == CONN_OPERATION_SUCCESS){
payload = create_cleanruv_payload(filter);
@@ -1923,7 +1923,10 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
char *response = NULL;
decode_cleanruv_payload(retsdata, &response);
- if(response && strcmp(response,CLEANRUV_FINISHED) == 0){
+ if(response == NULL){
+ /* this replica does not support cleanallruv */
+ rc = 0;
+ } else if(strcmp(response,CLEANRUV_FINISHED) == 0){
/* finished cleaning */
rc = 0;
}
@@ -1933,8 +1936,6 @@ replica_cleanallruv_is_finished(Repl_Agmt *agmt, char *filter, Slapi_Task *task)
slapi_ch_free_string(&retoid);
}
}
- } else {
- rc = -1;
}
conn_delete_internal_ext(conn);
if(payload)
@@ -2189,16 +2190,16 @@ replica_send_cleanruv_task(Repl_Agmt *agmt, cleanruv_data *clean_data)
val.bv_val = data;
mods[0] = &mod;
mods[1] = NULL;
- repl_dn = slapi_create_dn_string("cn=replica,cn=%s,cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn));
+ repl_dn = slapi_create_dn_string("cn=replica,cn=\"%s\",cn=mapping tree,cn=config", slapi_sdn_get_dn(sdn));
/*
* Add task to remote replica
*/
rc = ldap_modify_ext_s( ld, repl_dn, mods, NULL, NULL);
if(rc != LDAP_SUCCESS){
- cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task replica "
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "Failed to add CLEANRUV task (%s) to replica "
"(%s). You will need to manually run the CLEANRUV task on this replica (%s) error (%d)",
- agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc);
+ repl_dn, agmt_get_long_name(agmt), agmt_get_hostname(agmt), rc);
}
slapi_ch_free_string(&repl_dn);
slapi_sdn_free(&sdn);
@@ -2424,7 +2425,6 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
} else {
/* only remove the config, leave the in-memory rid */
dn = replica_get_dn(r);
- pb = slapi_pblock_new();
data = PR_smprintf("%d:%s", (int)rid, repl_root);
mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
@@ -2437,6 +2437,7 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
mods[0] = &mod;
mods[1] = NULL;
+ pb = slapi_pblock_new();
slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
slapi_modify_internal_pb (pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
@@ -2456,40 +2457,29 @@ delete_aborted_rid(Replica *r, ReplicaId rid, char *repl_root, int skip){
static void
delete_cleaned_rid_config(cleanruv_data *clean_data)
{
- Slapi_PBlock *pb;
+ Slapi_PBlock *pb, *modpb;
Slapi_Entry **entries = NULL;
LDAPMod *mods[2];
LDAPMod mod;
- struct berval *vals[2];
- struct berval val;
- char data[CSN_STRSIZE + 15];
- char *csnstr = NULL;
+ struct berval *vals[5]= {0, 0, 0, 0, 0}; /* maximum of 4 tasks */
+ struct berval val[5];
char *iter = NULL;
- char *dn;
- int found = 0, i;
- int rc, ret, rid;
+ char *dn = NULL;
+ int i, ii;
+ int rc = -1, ret, rid;
if(clean_data == NULL){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "delete_cleaned_rid_config: cleanruv data is NULL, "
- "failed to clean the config.\n");
+ cleanruv_log(NULL, CLEANALLRUV_ID, "delete_cleaned_rid_config: cleanruv data is NULL, "
+ "failed to clean the config.");
return;
}
/*
- * If there is no maxcsn, set the proper csnstr
- */
- csnstr = csn_as_string(clean_data->maxcsn, PR_FALSE, csnstr);
- if ((csnstr == NULL) || (csn_get_replicaid(clean_data->maxcsn) == 0)) {
- slapi_ch_free_string(&csnstr); /* no problem to pass NULL */
- csnstr = slapi_ch_strdup("00000000000000000000");
- }
- /*
* Search the config for the exact attribute value to delete
*/
pb = slapi_pblock_new();
if(clean_data->replica){
dn = replica_get_dn(clean_data->replica);
} else {
- rc = -1;
goto bail;
}
@@ -2498,72 +2488,81 @@ delete_cleaned_rid_config(cleanruv_data *clean_data)
slapi_search_internal_pb(pb);
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
if (ret != LDAP_SUCCESS){
- /*
- * Search failed, manually build the attr value
- */
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
- (int)clean_data->rid, csnstr, clean_data->force);
- slapi_pblock_destroy(pb);
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: internal search failed(%d).",ret);
+ goto bail;
} else {
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
if (entries == NULL || entries[0] == NULL){
/*
- * Entry not found, manually build the attr value
+ * No matching entries!
*/
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
- (int)clean_data->rid, csnstr, clean_data->force);
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID,"delete_cleaned_rid_config: failed to find any "
+ "entries with nsds5ReplicaCleanRUV under (%s)", dn);
+ goto bail;
} else {
- char **attr_val = slapi_entry_attr_get_charray(entries[0], "nsds5ReplicaCleanRUV");
-
- for (i = 0; attr_val && attr_val[i] && !found; i++){
- /* make a copy to retain the full value after toking */
- char *aval = slapi_ch_strdup(attr_val[i]);
-
- rid = atoi(ldap_utf8strtok_r(attr_val[i], ":", &iter));
- if(rid == clean_data->rid){
- /* found it */
- found = 1;
- val.bv_len = PR_snprintf(data, sizeof(data), "%s", aval);
+ /*
+ * Clean all the matching entries
+ */
+ for(i = 0; entries[i] != NULL;i++){
+ char **attr_val = slapi_entry_attr_get_charray(entries[i], type_replicaCleanRUV);
+ char *edn = slapi_entry_get_dn(entries[i]);
+ int count = 0;
+
+ for (ii = 0; attr_val && attr_val[ii] && i < 5; ii++){
+ /* make a copy to retain the full value after toking */
+ char *aval = slapi_ch_strdup(attr_val[ii]);
+
+ rid = atoi(ldap_utf8strtok_r(attr_val[ii], ":", &iter));
+ if(rid == clean_data->rid){
+ val[count].bv_len = strlen(aval);
+ val[count].bv_val = aval;
+ vals[count] = &val[count];
+ count++;
+ } else {
+ slapi_ch_free_string(&aval);
+ }
}
- slapi_ch_free_string(&aval);
- }
- if(!found){
+ slapi_ch_array_free(attr_val);
+
/*
- * No match, manually build the attr value
+ * Now delete the attribute
*/
- val.bv_len = PR_snprintf(data, sizeof(data), "%d:%s:%s",
- (int)clean_data->rid, csnstr, clean_data->force);
+ vals[5] = NULL;
+ mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
+ mod.mod_type = (char *)type_replicaCleanRUV;
+ mod.mod_bvalues = vals;
+ mods[0] = &mod;
+ mods[1] = NULL;
+
+ modpb = slapi_pblock_new();
+ slapi_modify_internal_set_pb(modpb, edn, mods, NULL, NULL,
+ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_modify_internal_pb (modpb);
+ slapi_pblock_get(modpb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ slapi_pblock_destroy(modpb);
+
+ /* free the attr vals */
+ for (ii = 0; ii < count; ii++){
+ slapi_ch_free_string(&val[ii].bv_val);
+ }
+
+ if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove task data "
+ "from (%s) error (%d), rid (%d)", edn, rc, clean_data->rid);
+ goto bail;
+ }
}
- slapi_ch_array_free(attr_val);
}
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
}
- /*
- * Now delete the attribute
- */
- mod.mod_op = LDAP_MOD_DELETE|LDAP_MOD_BVALUES;
- mod.mod_type = (char *)type_replicaCleanRUV;
- mod.mod_bvalues = vals;
- vals [0] = &val;
- vals [1] = NULL;
- val.bv_val = data;
- mods[0] = &mod;
- mods[1] = NULL;
- pb = slapi_pblock_new();
- slapi_modify_internal_set_pb(pb, dn, mods, NULL, NULL, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
-
bail:
if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: failed to remove replica config "
- "(%d), rid (%d)\n", rc, clean_data->rid);
+ cleanruv_log(clean_data->task, CLEANALLRUV_ID, "delete_cleaned_rid_config: failed to remove replica config "
+ "(%d), rid (%d)", rc, clean_data->rid);
}
+ slapi_free_search_results_internal(pb);
slapi_pblock_destroy(pb);
slapi_ch_free_string(&dn);
- slapi_ch_free_string(&csnstr);
}
/*
@@ -2768,6 +2767,7 @@ replica_abort_task_thread(void *arg)
int agmt_not_notified = 1;
int interval = 10;
int release_it = 0;
+ int count = 0, rc = 0;
cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Aborting task for rid(%d)...",data->rid);
@@ -2846,6 +2846,20 @@ done:
cleanruv_log(data->task, ABORT_CLEANALLRUV_ID,"Abort task failed, will resume the task at the next server startup.");
} else {
/*
+ * Wait for this server to stop its cleanallruv task(which removes the rid from the cleaned list)
+ */
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Waiting for CleanAllRUV task to abort...");
+ while(is_cleaned_rid(data->rid)){
+ DS_Sleep(PR_SecondsToInterval(1));
+ count++;
+ if(count == 60){ /* it should not take this long */
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "CleanAllRUV task failed to abort. You might need to "
+ "rerun the task.");
+ rc = -1;
+ break;
+ }
+ }
+ /*
* Clean up the config
*/
delete_aborted_rid(data->replica, data->rid, data->repl_root, 1); /* delete just the config, leave rid in memory */
@@ -2853,8 +2867,13 @@ done:
check_replicas_are_done_aborting(data);
}
delete_aborted_rid(data->replica, data->rid, data->repl_root, 0); /* remove the in-memory aborted rid */
- cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid);
+ if(rc == 0){
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Successfully aborted task for rid(%d)", data->rid);
+ } else {
+ cleanruv_log(data->task, ABORT_CLEANALLRUV_ID, "Failed to abort task for rid(%d)",data->rid);
+ }
}
+
if(data->task){
slapi_task_finish(data->task, agmt_not_notified);
}
@@ -2932,6 +2951,7 @@ replica_cleanallruv_send_extop(Repl_Agmt *ra, cleanruv_data *clean_data, int che
* add the CLEANRUV task to the replica.
*/
replica_send_cleanruv_task(ra, clean_data);
+ rc = 0;
}
if (NULL != retsdata)
ber_bvfree(retsdata);
@@ -2955,72 +2975,49 @@ replica_cleanallruv_find_maxcsn(Replica *replica, ReplicaId rid, char *basedn)
{
Object *agmt_obj;
Repl_Agmt *agmt;
- char *rid_text;
CSN *maxcsn = NULL, *topcsn = NULL;
- int done = 1, found = 0;
- int interval = 10;
+ char *rid_text = slapi_ch_smprintf("%d", rid);
+ char *csnstr = NULL;
- rid_text = slapi_ch_smprintf("%d", rid);
+ /* start with the local maxcsn */
+ csnstr = replica_cleanallruv_get_local_maxcsn(rid, basedn);
+ if(csnstr){
+ topcsn = csn_new();
+ csn_init_by_string(topcsn, csnstr);
+ slapi_ch_free_string(&csnstr);
+ }
- while(done && !is_task_aborted(rid) && !slapi_is_shutting_down()){
- agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
- if(agmt_obj == NULL){
- break;
+ agmt_obj = agmtlist_get_first_agreement_for_replica (replica);
+ if(agmt_obj == NULL){ /* no agreements */
+ goto done;
+ }
+ while (agmt_obj && !slapi_is_shutting_down()){
+ agmt = (Repl_Agmt*)object_get_data (agmt_obj);
+ if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
+ continue;
}
- while (agmt_obj && !slapi_is_shutting_down()){
- agmt = (Repl_Agmt*)object_get_data (agmt_obj);
- if(!agmt_is_enabled(agmt) || get_agmt_agreement_type(agmt) == REPLICA_TYPE_WINDOWS){
+ if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){
+ if(maxcsn == NULL){
agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
- done = 0;
continue;
}
- if(replica_cleanallruv_get_replica_maxcsn(agmt, rid_text, basedn, &maxcsn) == 0){
- if(maxcsn == NULL){
- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
- continue;
- }
- found = 1;
- if(topcsn == NULL){
+ if(topcsn == NULL){
+ topcsn = maxcsn;
+ } else {
+ if(csn_compare(topcsn, maxcsn) < 0){
+ csn_free(&topcsn);
topcsn = maxcsn;
} else {
- if(csn_compare(topcsn, maxcsn) < 0){
- csn_free(&topcsn);
- topcsn = maxcsn;
- } else {
- csn_free(&maxcsn);
- }
+ csn_free(&maxcsn);
}
- done = 0;
- } else {
- done = 1;
- break;
}
- agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
- } /* agmt while */
- if(done == 0 || is_task_aborted(rid) ){
- break;
- }
- if(!found){
- /* we could not find any maxcsn's - already cleaned? */
- return NULL;
- }
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Task: replica_cleanallruv_find_maxcsn: "
- "Not all replicas online, retrying in %d seconds\n", interval);
- PR_Lock( notify_lock );
- PR_WaitCondVar( notify_cvar, PR_SecondsToInterval(interval) );
- PR_Unlock( notify_lock );
-
- if(interval < 14400){ /* 4 hour max */
- interval = interval * 2;
- } else {
- interval = 14400;
}
+ agmt_obj = agmtlist_get_next_agreement_for_replica (replica, agmt_obj);
}
- slapi_ch_free_string(&rid_text);
- if(is_task_aborted(rid)){
- return NULL;
- }
+done:
+ slapi_ch_free_string(&rid_text);
return topcsn;
}
@@ -3303,3 +3300,64 @@ cleanruv_log(Slapi_Task *task, char *task_type, char *fmt, ...)
va_end(ap4);
}
+char *
+replica_cleanallruv_get_local_maxcsn(ReplicaId rid, char *base_dn)
+{
+ Slapi_PBlock *search_pb = NULL;
+ Slapi_Entry **entries = NULL;
+ char **ruv_elements = NULL;
+ char *maxcsn = NULL;
+ char *filter = NULL;
+ char *ridstr = NULL;
+ char *iter = NULL;
+ char *attrs[2];
+ char *ruv_part = NULL;
+ int part_count = 0;
+ int res, i;
+
+ /*
+ * Get the maxruv from the database tombstone entry
+ */
+ filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))";
+ attrs[0] = "nsds50ruv";
+ attrs[1] = NULL;
+ ridstr = slapi_ch_smprintf("{replica %d ldap", rid);
+
+ search_pb = slapi_pblock_new();
+ slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_search_internal_pb (search_pb);
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
+
+ if ( LDAP_SUCCESS == res ) {
+ slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if (NULL == entries || entries[0] == NULL) {
+ /* Hmmm, no tombstone! Error out */
+ } else {
+ /* find the right ruv element, and find the maxcsn */
+ ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]);
+ for(i = 0; ruv_elements && ruv_elements[i] ; i++){
+ if(strstr(ruv_elements[i], ridstr)){
+ /* get the max csn */
+ ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter);
+ for(part_count = 1; ruv_part && part_count < 5; part_count++){
+ ruv_part = ldap_utf8strtok_r(iter, " ", &iter);
+ }
+ if(part_count == 5 && ruv_part){/* we have the maxcsn */
+ maxcsn = slapi_ch_strdup(ruv_part);
+ break;
+ }
+ }
+ }
+ slapi_ch_array_free(ruv_elements);
+ }
+ } else {
+ /* internal search failed */
+ cleanruv_log(NULL, CLEANALLRUV_ID, "replica_cleanallruv_get_local_maxcsn: internal search failed (%d)\n", res);
+ }
+
+ slapi_free_search_results_internal(search_pb);
+ slapi_pblock_destroy(search_pb);
+ slapi_ch_free_string(&ridstr);
+
+ return maxcsn;
+}
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index f41cc7d..57249a6 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -1784,26 +1784,16 @@ free_and_return:
int
multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
{
- Slapi_PBlock *search_pb = NULL;
- Slapi_Entry **entries = NULL;
struct berval *resp_bval = NULL;
struct berval *extop_payload;
BerElement *resp_bere = NULL;
- char **ruv_elements = NULL;
char *extop_oid = NULL;
- char *ruv_part = NULL;
char *base_dn = NULL;
char *payload = NULL;
char *maxcsn = NULL;
- char *filter = NULL;
- char *ridstr = NULL;
char *iter = NULL;
- char *attrs[2];
- int part_count = 0;
int rid = 0;
- int res = 0;
int rc = LDAP_OPERATIONS_ERROR;
- int i = 0;
slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &extop_oid);
slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_payload);
@@ -1822,45 +1812,7 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
}
rid = atoi(ldap_utf8strtok_r(payload, ":", &iter));
base_dn = ldap_utf8strtok_r(iter, ":", &iter);
- /*
- * Get the maxruv from the database tombstone entry
- */
- filter = "(&(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff)(objectclass=nstombstone))";
- attrs[0] = "nsds50ruv";
- attrs[1] = NULL;
- ridstr = slapi_ch_smprintf("{replica %d ldap", rid);
-
- search_pb = slapi_pblock_new();
- slapi_search_internal_set_pb(search_pb, base_dn, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_search_internal_pb (search_pb);
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
-
- if ( LDAP_SUCCESS == res ) {
- slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (NULL == entries || entries[0] == NULL) {
- /* Hmmm, no tombstpne! Error out */
- } else {
- /* find the right ruv element, and find the maxcsn */
- ruv_elements = slapi_entry_attr_get_charray(entries[0],attrs[0]);
- for(i = 0; ruv_elements && ruv_elements[i] ; i++){
- if(strstr(ruv_elements[i], ridstr)){
- /* get the max csn */
- ruv_part = ldap_utf8strtok_r(ruv_elements[i], " ", &iter);
- for(part_count = 1; ruv_part && part_count < 5; part_count++){
- ruv_part = ldap_utf8strtok_r(iter, " ", &iter);
- }
- if(part_count == 5 && ruv_part){/* we have the maxcsn */
- maxcsn = slapi_ch_strdup(ruv_part);
- break;
- }
- }
- }
- slapi_ch_array_free(ruv_elements);
- }
- } else {
- /* internal search failed */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "CleanAllRUV Get MaxCSN Task: internal search failed (%d)\n", res);
- }
+ maxcsn = replica_cleanallruv_get_local_maxcsn(rid, base_dn);
if(maxcsn == NULL){
maxcsn = slapi_ch_strdup(CLEANRUV_NO_MAXCSN);
}
@@ -1889,11 +1841,8 @@ multimaster_extop_cleanruv_get_maxcsn(Slapi_PBlock *pb)
}
free_and_return:
- slapi_free_search_results_internal(search_pb);
- slapi_pblock_destroy(search_pb);
slapi_ch_free_string(&payload);
slapi_ch_free_string(&maxcsn);
- slapi_ch_free_string(&ridstr);
return rc;
}
10 years, 7 months
ldap/admin
by Mark Reynolds
ldap/admin/src/logconv.pl | 201 +++++++++++++++++++++++++---------------------
1 file changed, 110 insertions(+), 91 deletions(-)
New commits:
commit 8b153e999ac6dc4869498a78da103a07db49d28e
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Sep 23 11:32:16 2013 -0400
Ticket 47520 - Fix various issues with logconv.pl
Bug Description: When testing an access log that contains "internal" connections/ops, many
warning messages are created. Other warnings are generated because the
DB_File arrays need to have thier elements checked before comparing to other
strings.
Fix Description: Improve value checking. Add support for connection numbers that are words (Internal),
and negative values for op ids(-1).
https://fedorahosted.org/389/ticket/47520
Reviewed by: richm(Thanks!)
diff --git a/ldap/admin/src/logconv.pl b/ldap/admin/src/logconv.pl
index ec0fdf5..3a6fa01 100755
--- a/ldap/admin/src/logconv.pl
+++ b/ldap/admin/src/logconv.pl
@@ -102,6 +102,7 @@ my $fdds = 0;
my $reportBinds = "no";
my $rootDN = "";
my $needCleanup = 0;
+my @scopeTxt = ("0 (base)", "1 (one)", "2 (subtree)");
GetOptions(
'd|rootDN=s' => \$rootDN,
@@ -653,6 +654,7 @@ print "Entire Search Base Queries: $objectclassTopCount\n";
print "Paged Searches: $pagedSearchCount\n";
print "Unindexed Searches: $unindexedSrchCountNotesA\n";
print "Unindexed Components: $unindexedSrchCountNotesU\n";
+
if ($verb eq "yes" || $usage =~ /u/){
if ($unindexedSrchCountNotesA > 0){
my $conn_hash = $hashes->{conn_hash};
@@ -670,11 +672,12 @@ if ($verb eq "yes" || $usage =~ /u/){
my $filter_val = $arrays->{filterval};
my $filter_conn = $arrays->{filterconn};
my $filter_op = $arrays->{filterop};
-
my $notesCount = "1";
my $unindexedIp;
+
for (my $n = 0; $n < scalar(@{$notesEtime}); $n++){
- if($conn_hash->{$notesConn->[$n]} eq ""){
+ if(!$notesConn->[$n] || $notesConn->[$n] eq "" ||
+ !$conn_hash->{$notesConn->[$n]} || $conn_hash->{$notesConn->[$n]} eq ""){
$unindexedIp = "?";
} else {
$unindexedIp = $conn_hash->{$notesConn->[$n]};
@@ -688,18 +691,21 @@ if ($verb eq "yes" || $usage =~ /u/){
print " - IP Address: $unindexedIp\n";
for (my $nnn = 0; $nnn < $baseCount; $nnn++){
+ if(!$base_conn->[$nnn] || !$base_op->[$nnn]){ next; }
if ($notesConn->[$n] eq $base_conn->[$nnn] && $notesOp->[$n] eq $base_op->[$nnn]){
print " - Search Base: $base_val->[$nnn]\n";
last;
}
}
for (my $nnn = 0; $nnn < $scopeCount; $nnn++){
+ if(!$scope_conn->[$nnn] || !$scope_op->[$nnn]){ next; }
if ($notesConn->[$n] eq $scope_conn->[$nnn] && $notesOp->[$n] eq $scope_op->[$nnn]){
print " - Search Scope: $scope_val->[$nnn]\n";
last;
}
}
for (my $nnn = 0; $nnn < $filterCount; $nnn++){
+ if(!$filter_conn->[$nnn] || !$filter_op->[$nnn]){ next; }
if ($notesConn->[$n] eq $filter_conn->[$nnn] && $notesOp->[$n] eq $filter_op->[$nnn]){
print " - Search Filter: $filter_val->[$nnn]\n";
last;
@@ -727,7 +733,8 @@ if ($verb eq "yes" || $usage =~ /u/){
my $notesCount = "1";
my $unindexedIp;
for (my $n = 0; $n < scalar(@{$notesEtime}); $n++){
- if($conn_hash->{$notesConn->[$n]} eq ""){
+ if(!$notesConn->[$n] || $notesConn->[$n] eq "" ||
+ !$conn_hash->{$notesConn->[$n]} || $conn_hash->{$notesConn->[$n]} eq ""){
$unindexedIp = "?";
} else {
$unindexedIp = $conn_hash->{$notesConn->[$n]};
@@ -741,18 +748,21 @@ if ($verb eq "yes" || $usage =~ /u/){
print " - IP Address: $unindexedIp\n";
for (my $nnn = 0; $nnn < $baseCount; $nnn++){
+ if(!$base_conn->[$nnn] || !$base_op->[$nnn]){ next; }
if ($notesConn->[$n] eq $base_conn->[$nnn] && $notesOp->[$n] eq $base_op->[$nnn]){
print " - Search Base: $base_val->[$nnn]\n";
last;
}
}
for (my $nnn = 0; $nnn < $scopeCount; $nnn++){
+ if(!$scope_conn->[$nnn] || !$scope_op->[$nnn]){ next; }
if ($notesConn->[$n] eq $scope_conn->[$nnn] && $notesOp->[$n] eq $scope_op->[$nnn]){
print " - Search Scope: $scope_val->[$nnn]\n";
last;
}
}
for (my $nnn = 0; $nnn < $filterCount; $nnn++){
+ if(!$filter_conn->[$nnn] || !$filter_op->[$nnn]){ next; }
if ($notesConn->[$n] eq $filter_conn->[$nnn] && $notesOp->[$n] eq $filter_op->[$nnn]){
print " - Search Filter: $filter_val->[$nnn]\n";
last;
@@ -772,13 +782,12 @@ if ($brokenPipeCount > 0){
my @etext;
foreach my $key (sort { $rc->{$b} <=> $rc->{$a} } keys %{$rc}) {
if ($rc->{$key} > 0){
- if ($conn{$key} eq ""){$conn{$key} = "**Unknown**";}
- push @etext, sprintf " - %-4s (%2s) %-40s\n",$rc->{$key},$conn{$key},$connmsg{$key
-};
- }
- }
- print @etext;
- print "\n";
+ if ($conn{$key} eq ""){$conn{$key} = "**Unknown**";}
+ push @etext, sprintf " - %-4s (%2s) %-40s\n",$rc->{$key},$conn{$key},$connmsg{$key};
+ }
+ }
+ print @etext;
+ print "\n";
}
print "Connections Reset By Peer: $connResetByPeerCount\n";
@@ -787,12 +796,11 @@ if ($connResetByPeerCount > 0){
my @retext;
foreach my $key (sort { $src->{$b} <=> $src->{$a} } keys %{$src}) {
if ($src->{$key} > 0){
- if ($conn{$key} eq ""){$conn{$key} = "**Unknown**";}
- push @retext, sprintf " - %-4s (%2s) %-40s\n",$src->{$key},$conn{$key},$connmsg{$key
-};
- }
- }
- print @retext;
+ if ($conn{$key} eq ""){$conn{$key} = "**Unknown**";}
+ push @retext, sprintf " - %-4s (%2s) %-40s\n",$src->{$key},$conn{$key},$connmsg{$key};
+ }
+ }
+ print @retext;
print "\n";
}
@@ -802,9 +810,9 @@ if ($resourceUnavailCount > 0){
my @rtext;
foreach my $key (sort { $rsrc->{$b} <=> $rsrc->{$a} } keys %{$rsrc}) {
if ($rsrc->{$key} > 0){
- if ($conn{$key} eq ""){$conn{$key} = "**Resource Issue**";}
- push @rtext, sprintf " - %-4s (%2s) %-40s\n",$rsrc->{$key},$conn{$key},$connmsg{$key};
- }
+ if ($conn{$key} eq ""){$conn{$key} = "**Resource Issue**";}
+ push @rtext, sprintf " - %-4s (%2s) %-40s\n",$rsrc->{$key},$conn{$key},$connmsg{$key};
+ }
}
print @rtext;
}
@@ -1244,48 +1252,57 @@ if ($usage =~ /g/i || $verb eq "yes"){
my $op = $arrays->{targetop}->[$g];
my $msgid = $arrays->{msgid}->[$g];
for (my $sc = 0; $sc < $srchCount; $sc++){
- if ($arrays->{srchconn}->[$sc] eq $conn && $arrays->{srchop}->[$sc] eq $op ){
+ if (($arrays->{srchconn}->[$sc] && $arrays->{srchop}->[$sc]) &&
+ ($arrays->{srchconn}->[$sc] eq $conn && $arrays->{srchop}->[$sc] eq $op )){
print " - SRCH conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $dc = 0; $dc < $delCount; $dc++){
- if ($arrays->{delconn}->[$dc] eq $conn && $arrays->{delop}->[$dc] eq $op){
- print " - DEL conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
+ if (($arrays->{delconn}->[$dc] && $arrays->{delop}->[$dc]) &&
+ ($arrays->{delconn}->[$dc] eq $conn && $arrays->{delop}->[$dc] eq $op)){
+ print " - DEL conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $adc = 0; $adc < $addCount; $adc++){
- if ($arrays->{addconn}->[$adc] eq $conn && $arrays->{addop}->[$adc] eq $op){
- print " - ADD conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
+ if (($arrays->{addconn}->[$adc] && $arrays->{addop}->[$adc]) &&
+ ($arrays->{addconn}->[$adc] eq $conn && $arrays->{addop}->[$adc] eq $op)){
+ print " - ADD conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $mc = 0; $mc < $modCount; $mc++){
- if ($arrays->{modconn}->[$mc] eq $conn && $arrays->{modop}->[$mc] eq $op){
- print " - MOD conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
+ if (($arrays->{modconn}->[$mc] && $arrays->{modop}->[$mc]) &&
+ ($arrays->{modconn}->[$mc] eq $conn && $arrays->{modop}->[$mc] eq $op)){
+ print " - MOD conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $cc = 0; $cc < $cmpCount; $cc++){
- if ($arrays->{cmpconn}->[$cc] eq $conn && $arrays->{cmpop}->[$cc] eq $op){
- print " - CMP conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
+ if (($arrays->{cmpconn}->[$cc] && $arrays->{cmpop}->[$cc]) &&
+ ($arrays->{cmpconn}->[$cc] eq $conn && $arrays->{cmpop}->[$cc] eq $op)){
+ print " - CMP conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $mdc = 0; $mdc < $modrdnCount; $mdc++){
- if ($arrays->{modrdnconn}->[$mdc] eq $conn && $arrays->{modrdnop}->[$mdc] eq $op){
+ if (($arrays->{modrdnconn}->[$mdc] && $arrays->{modrdnop}->[$mdc]) &&
+ ($arrays->{modrdnconn}->[$mdc] eq $conn && $arrays->{modrdnop}->[$mdc] eq $op)){
print " - MODRDN conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $bcb = 0; $bcb < $bindCount; $bcb++){
- if ($arrays->{bindconn}->[$bcb] eq $conn && $arrays->{bindop}->[$bcb] eq $op){
+ if (($arrays->{bindconn}->[$bcb] && $arrays->{bindop}->[$bcb]) &&
+ ($arrays->{bindconn}->[$bcb] eq $conn && $arrays->{bindop}->[$bcb] eq $op)){
print " - BIND conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $ubc = 0; $ubc < $unbindCount; $ubc++){
- if ($arrays->{unbindconn}->[$ubc] eq $conn && $arrays->{unbindop}->[$ubc] eq $op){
+ if (($arrays->{unbindconn}->[$ubc] && $arrays->{unbindop}->[$ubc]) &&
+ ($arrays->{unbindconn}->[$ubc] eq $conn && $arrays->{unbindop}->[$ubc] eq $op)){
print " - UNBIND conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
for (my $ec = 0; $ec < $extopCount; $ec++){
- if ($arrays->{extconn}->[$ec] eq $conn && $arrays->{extop}->[$ec] eq $op){
- print " - EXT conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
+ if (($arrays->{extconn}->[$ec] && $arrays->{extop}->[$ec]) &&
+ ($arrays->{extconn}->[$ec] eq $conn && $arrays->{extop}->[$ec] eq $op)){
+ print " - EXT conn=$conn op=$op msgid=$msgid client=$conn_hash->{$conn}\n";
}
}
}
@@ -1485,7 +1502,7 @@ parseLineBind {
return ;
}
$ip = $1;
- if ($_ =~ /conn= *([0-9]+)/i ){
+ if ($_ =~ /conn= *([0-9A-Z]+)/i ){
$connList{$ip} = $connList{$ip} . " $1 ";
}
return;
@@ -1516,7 +1533,7 @@ parseLineBind {
$bindReport{$dn}{"modrdn"} = 0;
$bindReport{$dn}{"failedBind"} = 0;
}
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$bindReport{$dn}{"conn"} = $bindReport{$dn}{"conn"} . " $1 ";
}
return;
@@ -1547,7 +1564,7 @@ processOpForBindReport
my $op = shift;
my $data = shift;
- if ($data =~ /conn= *([0-9]+)/i) {
+ if ($data =~ /conn= *([0-9A-Z]+)/i) {
foreach my $dn (keys %bindReport){
if ($bindReport{$dn}{"conn"} =~ / $1 /){
$bindReport{$dn}{$op}++;
@@ -1649,48 +1666,48 @@ sub parseLineNormal
$anyAttrs++;
}
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{srchconn}}, $1;}
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{srchop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{srchconn}}, $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{srchop}}, $1;}
}
}
if (m/ DEL/){
$delCount++;
if($reportStats){ inc_stats('del',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{delconn}}, $1;}
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{delop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{delconn}}, $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{delop}}, $1;}
}
}
if (m/ MOD dn=/){
$modCount++;
if($reportStats){ inc_stats('mod',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{modconn}}, $1;}
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{modop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{modconn}}, $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{modop}}, $1; }
}
}
if (m/ ADD/){
$addCount++;
if($reportStats){ inc_stats('add',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{addconn}}, $1; }
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{addop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{addconn}}, $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{addop}}, $1; }
}
}
if (m/ MODRDN/){
$modrdnCount++;
if($reportStats){ inc_stats('modrdn',$s_stats,$m_stats); }
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{modrdnconn}}, $1; }
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{modrdnop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{modrdnconn}}, $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{modrdnop}}, $1; }
}
}
if (m/ CMP dn=/){
$cmpCount++;
if($reportStats){ inc_stats('cmp',$s_stats,$m_stats); }
if ($verb eq "yes" || $usage =~ /g/i){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{cmpconn}}, $1;}
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{cmpop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{cmpconn}}, $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{cmpop}}, $1;}
}
}
if (m/ ABANDON /){
@@ -1699,13 +1716,13 @@ sub parseLineNormal
$allResults++;
if ($_ =~ /targetop= *([0-9a-zA-Z]+)/i ){
push @{$arrays->{targetop}}, $1;
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{targetconn}}, $1; }
- if ($_ =~ /msgid= *([0-9]+)/i){ push @{$arrays->{msgid}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{targetconn}}, $1; }
+ if ($_ =~ /msgid= *([0-9\-]+)/i){ push @{$arrays->{msgid}}, $1; }
}
}
if (m/ VLV /){
- if ($_ =~ /conn= *([0-9]+)/i){ $vlvconn[$vlvCount] = $1;}
- if ($_ =~ /op= *([0-9]+)/i){ $vlvop[$vlvCount] = $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ $vlvconn[$vlvCount] = $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i){ $vlvop[$vlvCount] = $1;}
$vlvCount++;
}
if (m/ authzid=/){
@@ -1792,16 +1809,16 @@ sub parseLineNormal
$tmpp = $1;
$tmpp =~ tr/A-Z/a-z/;
$hashes->{bindlist}->{$tmpp}++;
- if ($_ =~ /conn= *([0-9]+)/i) { push @{$arrays->{bindconn}}, $1;}
- if ($_ =~ /op= *([0-9]+)/i) { push @{$arrays->{bindop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) { push @{$arrays->{bindconn}}, $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i) { push @{$arrays->{bindop}}, $1;}
if($usage =~ /f/ || $verb eq "yes"){
push @{$arrays->{binddn}}, $tmpp;
}
} else {
$anonymousBindCount++;
$hashes->{bindlist}->{"Anonymous Binds"}++;
- if ($_ =~ /conn= *([0-9]+)/i) { push @{$arrays->{bindconn}}, $1;}
- if ($_ =~ /op= *([0-9]+)/i) { push @{$arrays->{bindop}}, $1;}
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) { push @{$arrays->{bindconn}}, $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i) { push @{$arrays->{bindop}}, $1;}
push @{$arrays->{binddn}}, "";
inc_stats('anonbind',$s_stats,$m_stats);
}
@@ -1809,17 +1826,18 @@ sub parseLineNormal
if (m/ UNBIND/){
$unbindCount++;
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{unbindconn}}, $1; }
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{unbindop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{unbindconn}}, $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{unbindop}}, $1; }
}
}
if (m/ RESULT err=/ && m/ notes=P/){
$pagedSearchCount++;
}
if (m/ notes=A/){
- if ($_ =~ /conn= *([0-9]+)/i){
+ $con = "";
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){
$con = $1;
- if ($_ =~ /op= *([0-9]+)/i){ $op = $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i){ $op = $1;}
}
for (my $i=0; $i < $vlvCount;$i++){
if ($vlvconn[$i] eq $con && $vlvop[$i] eq $op){ $vlvNotesACount++; $isVlvNotes="1";}
@@ -1833,8 +1851,8 @@ sub parseLineNormal
if ($usage =~ /u/ || $verb eq "yes"){
if ($isVlvNotes == 0 ){
if ($_ =~ /etime= *([0-9.]+)/i ){ push @{$arrays->{notesAetime}}, $1; }
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{notesAconn}}, $1; }
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{notesAop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{notesAconn}}, $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{notesAop}}, $1; }
if ($_ =~ / *([0-9a-z:\/]+)/i){ push @{$arrays->{notesAtime}}, $1; }
if ($_ =~ /nentries= *([0-9]+)/i ){ push @{$arrays->{notesAnentries}}, $1; }
}
@@ -1842,9 +1860,10 @@ sub parseLineNormal
$isVlvNotes = 0;
}
if (m/ notes=U/){
- if ($_ =~ /conn= *([0-9]+)/i){
+ $con = "";
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){
$con = $1;
- if ($_ =~ /op= *([0-9]+)/i){ $op = $1;}
+ if ($_ =~ /op= *([0-9\-]+)/i){ $op = $1;}
}
for (my $i=0; $i < $vlvCount;$i++){
if ($vlvconn[$i] eq $con && $vlvop[$i] eq $op){ $vlvNotesUCount++; $isVlvNotes="1";}
@@ -1858,8 +1877,8 @@ sub parseLineNormal
if ($usage =~ /u/ || $verb eq "yes"){
if ($isVlvNotes == 0 ){
if ($_ =~ /etime= *([0-9.]+)/i ){ push @{$arrays->{notesUetime}}, $1; }
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{notesUconn}}, $1; }
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{notesUop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{notesUconn}}, $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{notesUop}}, $1; }
if ($_ =~ / *([0-9a-z:\/]+)/i){ push @{$arrays->{notesUtime}}, $1; }
if ($_ =~ /nentries= *([0-9]+)/i ){ push @{$arrays->{notesUnentries}}, $1; }
}
@@ -1922,14 +1941,14 @@ sub parseLineNormal
}
$ip = $1;
$hashes->{ip_hash}->{$ip}++;
- if ($_ =~ /conn= *([0-9]+)/i ){
+ if ($_ =~ /conn= *([0-9A-Z]+)/i ){
if ($exc ne "yes"){
$hashes->{conn_hash}->{$1} = $ip;
}
}
}
if (m/- A1/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -1944,7 +1963,7 @@ sub parseLineNormal
}
}
if (m/- B1/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -1959,7 +1978,7 @@ sub parseLineNormal
}
}
if (m/- B4/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -1974,7 +1993,7 @@ sub parseLineNormal
}
}
if (m/- T1/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -1989,7 +2008,7 @@ sub parseLineNormal
}
}
if (m/- T2/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -2004,7 +2023,7 @@ sub parseLineNormal
}
}
if (m/- B2/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
$maxBerSizeCount++;
@@ -2020,7 +2039,7 @@ sub parseLineNormal
}
}
if (m/- B3/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -2035,7 +2054,7 @@ sub parseLineNormal
}
}
if (m/- R1/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -2050,7 +2069,7 @@ sub parseLineNormal
}
}
if (m/- P1/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -2065,7 +2084,7 @@ sub parseLineNormal
}
}
if (m/- P2/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -2080,7 +2099,7 @@ sub parseLineNormal
}
}
if (m/- U1/){
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$exc = "no";
$ip = getIPfromConn($1);
if ($ip eq ""){$ip = "Unknown_Host";}
@@ -2112,8 +2131,8 @@ sub parseLineNormal
if ($_ =~ /oid=\" *([0-9\.]+)/i ){ $hashes->{oid}->{$1}++; }
if ($1 && $1 eq $startTLSoid){$startTLSCount++;}
if ($verb eq "yes"){
- if ($_ =~ /conn= *([0-9]+)/i){ push @{$arrays->{extconn}}, $1; }
- if ($_ =~ /op= *([0-9]+)/i){ push @{$arrays->{extop}}, $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i){ push @{$arrays->{extconn}}, $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i){ push @{$arrays->{extop}}, $1; }
}
}
if (($usage =~ /l/ || $verb eq "yes") and / SRCH /){
@@ -2123,15 +2142,15 @@ sub parseLineNormal
$tmpp =~ tr/A-Z/a-z/;
$tmpp =~ s/\\22/\"/g;
$hashes->{filter}->{$tmpp}++;
- if ($_ =~ /conn= *([0-9]+)/i) { $filterConn = $1; }
- if ($_ =~ /op= *([0-9]+)/i) { $filterOp = $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) { $filterConn = $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i) { $filterOp = $1; }
} elsif (/ SRCH / && $_ =~ /filter=\"(.*)\"/i){
$tmpp = $1;
$tmpp =~ tr/A-Z/a-z/;
$tmpp =~ s/\\22/\"/g;
$hashes->{filter}->{$tmpp}++;
- if ($_ =~ /conn= *([0-9]+)/i) { $filterConn = $1; }
- if ($_ =~ /op= *([0-9]+)/i) { $filterOp = $1; }
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) { $filterConn = $1; }
+ if ($_ =~ /op= *([0-9\-]+)/i) { $filterOp = $1; }
}
$filterCount++;
if($usage =~ /u/ || $verb eq "yes"){
@@ -2157,11 +2176,11 @@ sub parseLineNormal
if ($_ =~ /scope= *([0-9]+)/i) {
$scopeVal = $1;
}
- if ($_ =~ /conn= *([0-9]+)/i) {
+ if ($_ =~ /conn= *([0-9A-Z]+)/i) {
$baseConn = $1;
$scopeConn = $1;
}
- if ($_ =~ /op= *([0-9]+)/i) {
+ if ($_ =~ /op= *([0-9\-]+)/i) {
$baseOp = $1;
$scopeOp = $1;
}
@@ -2170,9 +2189,9 @@ sub parseLineNormal
push @{$arrays->{baseval}}, $tmpp;
push @{$arrays->{baseconn}}, $baseConn;
push @{$arrays->{baseop}}, $baseOp;
- push @{$arrays->{scopeval}}, $scopeVal;
- push @{$arrays->{scopeconn}}, $scopeConn;
- push @{$arrays->{scopeop}}, $scopeOp;
+ push @{$arrays->{scopeval}}, $scopeTxt[$scopeVal];
+ push @{$arrays->{scopeconn}}, $scopeConn;
+ push @{$arrays->{scopeop}}, $scopeOp;
}
$baseCount++;
$scopeCount++;
@@ -2191,12 +2210,12 @@ sub parseLineNormal
$ds6x = "true";
$badPwdCount++;
} elsif (/ err=49 tag=/ ){
- if ($_ =~ /conn= *([0-9]+)/i ){
+ if ($_ =~ /conn= *([0-9A-Z]+)/i ){
push @{$arrays->{badpwdconn}}, $1;
$ip = getIPfromConn($1);
$badPwdCount++;
}
- if ($_ =~ /op= *([0-9]+)/i ){
+ if ($_ =~ /op= *([0-9\-]+)/i ){
push @{$arrays->{badpwdop}}, $1;
}
push @{$arrays->{badpwdip}}, $ip;
10 years, 7 months
Branch '389-ds-base-1.3.1' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl_extop.c | 11 +++++++-
ldap/servers/slapd/libglobs.c | 33 +++++++++++++++++++++++++-
ldap/servers/slapd/proto-slap.h | 2 +
ldap/servers/slapd/slap.h | 2 +
4 files changed, 45 insertions(+), 3 deletions(-)
New commits:
commit 1f2c15119f12b2da83da2305a432bc310ee0d84b
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Sep 18 12:32:23 2013 -0600
Ticket #47516 replication stops with excessive clock skew
https://fedorahosted.org/389/ticket/47516
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: Add a new configuration parameter to cn=config
nsslapd-ignore-time-skew: on|off - default off
If nsslapd-ignore-time-skew: on, the replication consumer will log errors
about excessive time skew, but will allow replication to proceed, and will
not return a time skew error to the replication supplier.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: yes - document new config param
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index 47348b7..f41cc7d 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -835,12 +835,19 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb)
rc = replica_update_csngen_state_ext (replica, supplier_ruv, replicacsn); /* too much skew */
if (rc == CSN_LIMIT_EXCEEDED)
{
- response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ extern int config_get_ignore_time_skew();
+
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"conn=%" NSPRIu64 " op=%d repl=\"%s\": "
"Excessive clock skew from supplier RUV\n",
(long long unsigned int)connid, opid, repl_root);
- goto send_response;
+ if (!config_get_ignore_time_skew()) {
+ response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ goto send_response;
+ } else {
+ /* else just continue */
+ rc = 0;
+ }
}
else if (rc != 0)
{
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 1a889fd..f8c5b01 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -257,6 +257,7 @@ slapi_onoff_t init_sasl_mapping_fallback;
slapi_onoff_t init_return_orig_type;
slapi_onoff_t init_enable_turbo_mode;
slapi_int_t init_listen_backlog_size;
+slapi_onoff_t init_ignore_time_skew;
#ifdef MEMPOOL_EXPERIMENTAL
slapi_onoff_t init_mempool_switch;
#endif
@@ -1047,7 +1048,11 @@ static struct config_get_and_set {
{CONFIG_LISTEN_BACKLOG_SIZE, config_set_listen_backlog_size,
NULL, 0,
(void**)&global_slapdFrontendConfig.listen_backlog_size, CONFIG_INT,
- (ConfigGetFunc)config_get_listen_backlog_size, &init_listen_backlog_size}
+ (ConfigGetFunc)config_get_listen_backlog_size, &init_listen_backlog_size},
+ {CONFIG_IGNORE_TIME_SKEW, config_set_ignore_time_skew,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.ignore_time_skew,
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_ignore_time_skew, &init_ignore_time_skew}
#ifdef MEMPOOL_EXPERIMENTAL
,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
NULL, 0,
@@ -1488,6 +1493,7 @@ FrontendConfig_init () {
init_enable_turbo_mode = cfg->enable_turbo_mode = LDAP_ON;
init_listen_backlog_size = cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
+ init_ignore_time_skew = cfg->ignore_time_skew = LDAP_OFF;
#ifdef MEMPOOL_EXPERIMENTAL
init_mempool_switch = cfg->mempool_switch = LDAP_ON;
cfg->mempool_maxfreelist = 1024;
@@ -6910,6 +6916,18 @@ config_get_unhashed_pw_switch()
}
int
+config_get_ignore_time_skew(void)
+{
+ int retVal;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->ignore_time_skew;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
config_set_enable_turbo_mode( const char *attrname, char *value,
char *errorbuf, int apply )
{
@@ -6923,6 +6941,19 @@ config_set_enable_turbo_mode( const char *attrname, char *value,
}
int
+config_set_ignore_time_skew( const char *attrname, char *value,
+ char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff(attrname, value,
+ &(slapdFrontendConfig->ignore_time_skew),
+ errorbuf, apply);
+ return retVal;
+}
+
+int
config_set_listen_backlog_size( const char *attrname, char *value,
char *errorbuf, int apply )
{
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 60fa4e4..37f5f85 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -396,6 +396,7 @@ int config_set_unhashed_pw_switch(const char *attrname, char *value, char *error
int config_set_return_orig_type_switch(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_listen_backlog_size(const char *attrname, char *value, char *errorbuf, int apply);
+int config_set_ignore_time_skew(const char *attrname, char *value, char *errorbuf, int apply);
#if !defined(_WIN32) && !defined(AIX)
int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply );
@@ -569,6 +570,7 @@ int config_get_listen_backlog_size(void);
PLHashNumber hashNocaseString(const void *key);
PRIntn hashNocaseCompare(const void *v1, const void *v2);
+int config_get_ignore_time_skew();
int is_abspath(const char *);
char* rel2abspath( char * );
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index b1246c5..eaa824d 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2094,6 +2094,7 @@ typedef struct _slapdEntryPoints {
#ifndef DAEMON_LISTEN_SIZE
#define DAEMON_LISTEN_SIZE 128
#endif
+#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew"
#ifdef MEMPOOL_EXPERIMENTAL
#define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool"
@@ -2335,6 +2336,7 @@ typedef struct _slapdFrontendConfig {
slapi_onoff_t ignore_vattrs;
slapi_onoff_t unhashed_pw_switch; /* switch to on/off/nolog unhashed pw */
slapi_onoff_t enable_turbo_mode;
+ slapi_onoff_t ignore_time_skew;
} slapdFrontendConfig_t;
/* possible values for slapdFrontendConfig_t.schemareplace */
10 years, 7 months
ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl_extop.c | 11 +++++++-
ldap/servers/slapd/libglobs.c | 33 +++++++++++++++++++++++++-
ldap/servers/slapd/proto-slap.h | 2 +
ldap/servers/slapd/slap.h | 2 +
4 files changed, 45 insertions(+), 3 deletions(-)
New commits:
commit bde43727d17645c820f0c2f97636c8289882e434
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Sep 18 12:32:23 2013 -0600
Ticket #47516 replication stops with excessive clock skew
https://fedorahosted.org/389/ticket/47516
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: Add a new configuration parameter to cn=config
nsslapd-ignore-time-skew: on|off - default off
If nsslapd-ignore-time-skew: on, the replication consumer will log errors
about excessive time skew, but will allow replication to proceed, and will
not return a time skew error to the replication supplier.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: yes - document new config param
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index 47348b7..f41cc7d 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -835,12 +835,19 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb)
rc = replica_update_csngen_state_ext (replica, supplier_ruv, replicacsn); /* too much skew */
if (rc == CSN_LIMIT_EXCEEDED)
{
- response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ extern int config_get_ignore_time_skew();
+
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"conn=%" NSPRIu64 " op=%d repl=\"%s\": "
"Excessive clock skew from supplier RUV\n",
(long long unsigned int)connid, opid, repl_root);
- goto send_response;
+ if (!config_get_ignore_time_skew()) {
+ response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ goto send_response;
+ } else {
+ /* else just continue */
+ rc = 0;
+ }
}
else if (rc != 0)
{
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 047bd1c..9d1cf77 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -261,6 +261,7 @@ slapi_onoff_t init_connection_nocanon;
slapi_onoff_t init_plugin_logging;
slapi_int_t init_connection_buffer;
slapi_int_t init_listen_backlog_size;
+slapi_onoff_t init_ignore_time_skew;
#ifdef MEMPOOL_EXPERIMENTAL
slapi_onoff_t init_mempool_switch;
#endif
@@ -1067,7 +1068,11 @@ static struct config_get_and_set {
{CONFIG_LISTEN_BACKLOG_SIZE, config_set_listen_backlog_size,
NULL, 0,
(void**)&global_slapdFrontendConfig.listen_backlog_size, CONFIG_INT,
- (ConfigGetFunc)config_get_listen_backlog_size, &init_listen_backlog_size}
+ (ConfigGetFunc)config_get_listen_backlog_size, &init_listen_backlog_size},
+ {CONFIG_IGNORE_TIME_SKEW, config_set_ignore_time_skew,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.ignore_time_skew,
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_ignore_time_skew, &init_ignore_time_skew}
#ifdef MEMPOOL_EXPERIMENTAL
,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
NULL, 0,
@@ -1510,6 +1515,7 @@ FrontendConfig_init () {
init_connection_nocanon = cfg->connection_nocanon = LDAP_ON;
init_plugin_logging = cfg->plugin_logging = LDAP_OFF;
init_listen_backlog_size = cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
+ init_ignore_time_skew = cfg->ignore_time_skew = LDAP_OFF;
#ifdef MEMPOOL_EXPERIMENTAL
init_mempool_switch = cfg->mempool_switch = LDAP_ON;
cfg->mempool_maxfreelist = 1024;
@@ -6989,6 +6995,18 @@ config_get_unhashed_pw_switch()
}
int
+config_get_ignore_time_skew(void)
+{
+ int retVal;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->ignore_time_skew;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
config_set_enable_turbo_mode( const char *attrname, char *value,
char *errorbuf, int apply )
{
@@ -7015,6 +7033,19 @@ config_set_connection_nocanon( const char *attrname, char *value,
}
int
+config_set_ignore_time_skew( const char *attrname, char *value,
+ char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff(attrname, value,
+ &(slapdFrontendConfig->ignore_time_skew),
+ errorbuf, apply);
+ return retVal;
+}
+
+int
config_set_plugin_logging( const char *attrname, char *value,
char *errorbuf, int apply )
{
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index f2f5319..bbd1cf2 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -397,6 +397,7 @@ int config_set_unhashed_pw_switch(const char *attrname, char *value, char *error
int config_set_return_orig_type_switch(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_listen_backlog_size(const char *attrname, char *value, char *errorbuf, int apply);
+int config_set_ignore_time_skew(const char *attrname, char *value, char *errorbuf, int apply);
#if !defined(_WIN32) && !defined(AIX)
int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply );
@@ -576,6 +577,7 @@ int config_get_listen_backlog_size(void);
PLHashNumber hashNocaseString(const void *key);
PRIntn hashNocaseCompare(const void *v1, const void *v2);
+int config_get_ignore_time_skew();
int is_abspath(const char *);
char* rel2abspath( char * );
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 6c88a56..ffee433 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2121,6 +2121,7 @@ typedef struct _slapdEntryPoints {
#ifndef DAEMON_LISTEN_SIZE
#define DAEMON_LISTEN_SIZE 128
#endif
+#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew"
#ifdef MEMPOOL_EXPERIMENTAL
#define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool"
@@ -2366,6 +2367,7 @@ typedef struct _slapdFrontendConfig {
slapi_int_t connection_buffer; /* values are CONNECTION_BUFFER_* below */
slapi_onoff_t connection_nocanon; /* if "on" sets LDAP_OPT_X_SASL_NOCANON */
slapi_onoff_t plugin_logging; /* log all internal plugin operations */
+ slapi_onoff_t ignore_time_skew;
} slapdFrontendConfig_t;
/* possible values for slapdFrontendConfig_t.schemareplace */
10 years, 7 months
Branch '389-ds-base-1.2.11' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl_extop.c | 11 +++++++-
ldap/servers/slapd/libglobs.c | 32 +++++++++++++++++++++++++-
ldap/servers/slapd/proto-slap.h | 2 +
ldap/servers/slapd/slap.h | 2 +
4 files changed, 44 insertions(+), 3 deletions(-)
New commits:
commit 9dc7a4630cb13f1da074183208b1b34962fe8101
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Sep 18 12:32:23 2013 -0600
Ticket #47516 replication stops with excessive clock skew
https://fedorahosted.org/389/ticket/47516
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: Add a new configuration parameter to cn=config
nsslapd-ignore-time-skew: on|off - default off
If nsslapd-ignore-time-skew: on, the replication consumer will log errors
about excessive time skew, but will allow replication to proceed, and will
not return a time skew error to the replication supplier.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: yes - document new config param
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index 68aed62..f7f1d36 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -835,12 +835,19 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb)
rc = replica_update_csngen_state_ext (replica, supplier_ruv, replicacsn); /* too much skew */
if (rc == CSN_LIMIT_EXCEEDED)
{
- response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ extern int config_get_ignore_time_skew();
+
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"conn=%" NSPRIu64 " op=%d repl=\"%s\": "
"Excessive clock skew from supplier RUV\n",
connid, opid, repl_root);
- goto send_response;
+ if (!config_get_ignore_time_skew()) {
+ response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ goto send_response;
+ } else {
+ /* else just continue */
+ rc = 0;
+ }
}
else if (rc != 0)
{
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index c7ed279..0fc9022 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -696,7 +696,11 @@ static struct config_get_and_set {
{CONFIG_LISTEN_BACKLOG_SIZE, config_set_listen_backlog_size,
NULL, 0,
(void**)&global_slapdFrontendConfig.listen_backlog_size, CONFIG_INT,
- (ConfigGetFunc)config_get_listen_backlog_size}
+ (ConfigGetFunc)config_get_listen_backlog_size},
+ {CONFIG_IGNORE_TIME_SKEW, config_set_ignore_time_skew,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.ignore_time_skew,
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_ignore_time_skew}
#ifdef MEMPOOL_EXPERIMENTAL
,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
NULL, 0,
@@ -1100,6 +1104,7 @@ FrontendConfig_init () {
cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE;
cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
+ cfg->ignore_time_skew = LDAP_OFF;
#ifdef MEMPOOL_EXPERIMENTAL
cfg->mempool_switch = LDAP_ON;
cfg->mempool_maxfreelist = 1024;
@@ -6216,6 +6221,31 @@ config_get_listen_backlog_size()
return retVal;
}
+int
+config_get_ignore_time_skew(void)
+{
+ int retVal;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->ignore_time_skew;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
+config_set_ignore_time_skew( const char *attrname, char *value,
+ char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff(attrname, value,
+ &(slapdFrontendConfig->ignore_time_skew),
+ errorbuf, apply);
+ return retVal;
+}
+
/*
* This function is intended to be used from the dse code modify callback. It
* is "optimized" for that case because it takes a berval** of values, which is
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index a5d4d3f..cda038d 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -393,6 +393,7 @@ int config_set_disk_logging_critical( const char *attrname, char *value, char *e
int config_set_auditlog_unhashed_pw(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_listen_backlog_size(const char *attrname, char *value, char *errorbuf, int apply);
+int config_set_ignore_time_skew(const char *attrname, char *value, char *errorbuf, int apply);
#if !defined(_WIN32) && !defined(AIX)
int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply );
@@ -549,6 +550,7 @@ int config_get_disk_grace_period();
int config_get_disk_logging_critical();
int config_get_sasl_maxbufsize();
int config_get_listen_backlog_size(void);
+int config_get_ignore_time_skew();
int is_abspath(const char *);
char* rel2abspath( char * );
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index eaa1fee..4724f27 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2006,6 +2006,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_DISK_LOGGING_CRITICAL "nsslapd-disk-monitoring-logging-critical"
#define CONFIG_SASL_MAXBUFSIZE "nsslapd-sasl-max-buffer-size"
#define CONFIG_LISTEN_BACKLOG_SIZE "nsslapd-listen-backlog-size"
+#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew"
/*
* Define the backlog number for use in listen() call.
@@ -2250,6 +2251,7 @@ typedef struct _slapdFrontendConfig {
PRUint64 disk_threshold;
int disk_grace_period;
int disk_logging_critical;
+ int ignore_time_skew;
} slapdFrontendConfig_t;
/* possible values for slapdFrontendConfig_t.schemareplace */
10 years, 7 months
Branch '389-ds-base-1.3.0' - ldap/servers
by Richard Allen Megginson
ldap/servers/plugins/replication/repl_extop.c | 11 +++++++-
ldap/servers/slapd/libglobs.c | 33 +++++++++++++++++++++++++-
ldap/servers/slapd/proto-slap.h | 2 +
ldap/servers/slapd/slap.h | 2 +
4 files changed, 45 insertions(+), 3 deletions(-)
New commits:
commit e61009e49797b130e8d28e78bcb3ed6bf8858e7f
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Sep 18 12:32:23 2013 -0600
Ticket #47516 replication stops with excessive clock skew
https://fedorahosted.org/389/ticket/47516
Reviewed by: nhosoi (Thanks!)
Branch: master
Fix Description: Add a new configuration parameter to cn=config
nsslapd-ignore-time-skew: on|off - default off
If nsslapd-ignore-time-skew: on, the replication consumer will log errors
about excessive time skew, but will allow replication to proceed, and will
not return a time skew error to the replication supplier.
Platforms tested: RHEL6 x86_64
Flag Day: no
Doc impact: yes - document new config param
diff --git a/ldap/servers/plugins/replication/repl_extop.c b/ldap/servers/plugins/replication/repl_extop.c
index 9ee5237..e7f33f9 100644
--- a/ldap/servers/plugins/replication/repl_extop.c
+++ b/ldap/servers/plugins/replication/repl_extop.c
@@ -835,12 +835,19 @@ multimaster_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb)
rc = replica_update_csngen_state_ext (replica, supplier_ruv, replicacsn); /* too much skew */
if (rc == CSN_LIMIT_EXCEEDED)
{
- response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ extern int config_get_ignore_time_skew();
+
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"conn=%" NSPRIu64 " op=%d repl=\"%s\": "
"Excessive clock skew from supplier RUV\n",
connid, opid, repl_root);
- goto send_response;
+ if (!config_get_ignore_time_skew()) {
+ response = NSDS50_REPL_EXCESSIVE_CLOCK_SKEW;
+ goto send_response;
+ } else {
+ /* else just continue */
+ rc = 0;
+ }
}
else if (rc != 0)
{
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index dbd9de2..00db0e0 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -253,6 +253,7 @@ int init_disk_monitoring;
int init_disk_logging_critical;
int init_ndn_cache_enabled;
int init_listen_backlog_size;
+int init_ignore_time_skew;
#ifdef MEMPOOL_EXPERIMENTAL
int init_mempool_switch;
@@ -1016,7 +1017,11 @@ static struct config_get_and_set {
{CONFIG_LISTEN_BACKLOG_SIZE, config_set_listen_backlog_size,
NULL, 0,
(void**)&global_slapdFrontendConfig.listen_backlog_size, CONFIG_INT,
- (ConfigGetFunc)config_get_listen_backlog_size, &init_listen_backlog_size}
+ (ConfigGetFunc)config_get_listen_backlog_size, &init_listen_backlog_size},
+ {CONFIG_IGNORE_TIME_SKEW, config_set_ignore_time_skew,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.ignore_time_skew,
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_ignore_time_skew, &init_ignore_time_skew}
#ifdef MEMPOOL_EXPERIMENTAL
,{CONFIG_MEMPOOL_SWITCH_ATTRIBUTE, config_set_mempool_switch,
NULL, 0,
@@ -1445,6 +1450,7 @@ FrontendConfig_init () {
cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE;
init_listen_backlog_size = cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
+ init_ignore_time_skew = cfg->ignore_time_skew = LDAP_OFF;
#ifdef MEMPOOL_EXPERIMENTAL
init_mempool_switch = cfg->mempool_switch = LDAP_ON;
cfg->mempool_maxfreelist = 1024;
@@ -6690,6 +6696,31 @@ config_set_default_naming_context(const char *attrname,
}
int
+config_get_ignore_time_skew(void)
+{
+ int retVal;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ CFG_LOCK_READ(slapdFrontendConfig);
+ retVal = slapdFrontendConfig->ignore_time_skew;
+ CFG_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
+config_set_ignore_time_skew( const char *attrname, char *value,
+ char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff(attrname, value,
+ &(slapdFrontendConfig->ignore_time_skew),
+ errorbuf, apply);
+ return retVal;
+}
+
+int
config_set_listen_backlog_size( const char *attrname, char *value,
char *errorbuf, int apply )
{
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 2e000bd..01d114a 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -396,6 +396,7 @@ int config_set_ndn_cache_enabled(const char *attrname, char *value, char *errorb
int config_set_ndn_cache_max_size(const char *attrname, char *value, char *errorbuf, int apply);
int config_set_sasl_maxbufsize(const char *attrname, char *value, char *errorbuf, int apply );
int config_set_listen_backlog_size(const char *attrname, char *value, char *errorbuf, int apply);
+int config_set_ignore_time_skew(const char *attrname, char *value, char *errorbuf, int apply);
#if !defined(_WIN32) && !defined(AIX)
int config_set_maxdescriptors( const char *attrname, char *value, char *errorbuf, int apply );
@@ -561,6 +562,7 @@ int config_get_listen_backlog_size(void);
PLHashNumber hashNocaseString(const void *key);
PRIntn hashNocaseCompare(const void *v1, const void *v2);
+int config_get_ignore_time_skew();
int is_abspath(const char *);
char* rel2abspath( char * );
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 5d2ae10..e18967f 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2063,6 +2063,7 @@ typedef struct _slapdEntryPoints {
#ifndef DAEMON_LISTEN_SIZE
#define DAEMON_LISTEN_SIZE 128
#endif
+#define CONFIG_IGNORE_TIME_SKEW "nsslapd-ignore-time-skew"
#ifdef MEMPOOL_EXPERIMENTAL
#define CONFIG_MEMPOOL_SWITCH_ATTRIBUTE "nsslapd-mempool"
@@ -2286,6 +2287,7 @@ typedef struct _slapdFrontendConfig {
/* normalized dn cache */
int ndn_cache_enabled;
size_t ndn_cache_max_size;
+ int ignore_time_skew;
} slapdFrontendConfig_t;
/* possible values for slapdFrontendConfig_t.schemareplace */
10 years, 7 months
ldap/schema ldap/servers
by Noriko Hosoi
ldap/schema/02common.ldif | 5
ldap/servers/plugins/replication/repl5.h | 3
ldap/servers/plugins/replication/repl_globals.c | 3
ldap/servers/plugins/replication/windows_connection.c | 19
ldap/servers/plugins/replication/windows_private.c | 581 ++++++++++++---
ldap/servers/plugins/replication/windows_protocol_util.c | 552 ++++++++++----
ldap/servers/plugins/replication/windows_tot_protocol.c | 125 ++-
ldap/servers/plugins/replication/windowsrepl.h | 18
ldap/servers/slapd/dn.c | 93 ++
ldap/servers/slapd/slapi-plugin.h | 45 +
ldap/servers/slapd/util.c | 2
11 files changed, 1163 insertions(+), 283 deletions(-)
New commits:
commit c410b87b2b345711faed0a5767d97827bfc417c1
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Wed Sep 18 14:05:40 2013 -0700
Ticket #460 - support multiple subtrees and filters
Description:
1. Support multiple subtrees
new config parameter in windwows sync agreement:
winSyncSubtreePair: <DS Subtree>:<AD Subtree>
Example:
winSyncSubtreePair: ou=OU1,dc=DSexample,dc=com:ou=OU1,DC=ADexample,DC=com
winSyncSubtreePair: ou=OU2,dc=DSexample,dc=com:ou=OU2,DC=ADexample,DC=com
winSyncSubtreePair: ou=OU3,dc=DSexample,dc=com:ou=OU3,DC=ADexample,DC=com
. Attribute type "winSyncSubtreePair" is added to the objectclass
"nsDSWindowsReplicationAgreement".
. If "winSyncSubtreePair" is not set, there is not behavioral
difference: the AD subtree "nsds7WindowsReplicaSubtree" and the
DS subtree "nsds7DirectoryReplicaSubtree" are used for the sync
target checks.
. When "winSyncSubtreePair" is set, the above 2 config parameters
are ignored.
To determine if an entry is the target of the synchronization,
the DN is examined whether the DN is a descendent of any of the
subtrees or not. If it is, the subtree of the counter part is
retrieved.
Moving an entry from one subtree to another is synchronized.
Members of a group is synchronized as long as the member entry
is in any of the defined subtrees.
2. Support filters
new config parameters in windwows sync agreement:
winSyncWindowsFilter: <additional filter on AD>
winSyncDirectoryFilter: <additional filter on DS>
Example:
winSyncWindowsFilter: (|(cn=*user*)(cn=*group*))
winSyncDirectoryFilter: (|(uid=*user*)(cn=*group*))
. The filters are set to the windows_userfilter and directory_
userfilter in the private area in the windows agreement. And
when each server is searched the filters are added to the internal
filter. For instance, filters shown in the above Example allow
synchronizing the entries which CN contains "user" or "group".
3. Misc
. Added slapi_sdn_set_ndn_byref, slapi_sdn_set_ndn_passin, and
slapi_sdn_common_ancestor to dn.c (see also slapi-plugin.h).
. Fixed memory leaks.
. Fixed some of the mixed indentations.
https://fedorahosted.org/389/ticket/460
Reviewed by Rich (Thank you!!)
diff --git a/ldap/schema/02common.ldif b/ldap/schema/02common.ldif
index b67ec8d..724c532 100644
--- a/ldap/schema/02common.ldif
+++ b/ldap/schema/02common.ldif
@@ -148,6 +148,9 @@ attributeTypes: ( 2.16.840.1.113730.3.1.1099 NAME 'winSyncInterval' DESC 'Netsca
attributeTypes: ( 2.16.840.1.113730.3.1.1100 NAME 'oneWaySync' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.1101 NAME 'nsRoleScopeDN' DESC 'Scope of a role' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN '389 Directory Server' )
attributeTypes: ( 2.16.840.1.113730.3.1.2139 NAME 'winSyncMoveAction' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2162 NAME 'winSyncDirectoryFilter' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2163 NAME 'winSyncWindowsFilter' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2164 NAME 'winSyncSubtreePair' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
attributeTypes: ( 1.3.6.1.1.4 NAME 'vendorName' EQUALITY 1.3.6.1.4.1.1466.109.114.1 SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation X-ORIGIN 'RFC 3045' )
attributeTypes: ( 1.3.6.1.1.5 NAME 'vendorVersion' EQUALITY 1.3.6.1.4.1.1466.109.114.1 SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation X-ORIGIN 'RFC 3045' )
attributeTypes: ( 2.16.840.1.113730.3.1.3023 NAME 'nsViewFilter' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
@@ -182,7 +185,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.99 NAME 'cosSuperDefinition' DESC 'Netsca
objectClasses: ( 2.16.840.1.113730.3.2.100 NAME 'cosClassicDefinition' DESC 'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosTemplateDn $ cosspecifier ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.101 NAME 'cosPointerDefinition' DESC 'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosTemplateDn ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.102 NAME 'cosIndirectDefinition' DESC 'Netscape defined objectclass' SUP cosSuperDefinition MAY ( cosIndirectSpecifier ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.503 NAME 'nsDSWindowsReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime $ nsds7WindowsReplicaSubtree $ nsds7DirectoryReplicaSubtree $ nsds7NewWinUserSyncEnabled $ nsds7NewWinGroupSyncEnabled $ nsds7WindowsDomain $ nsds7DirsyncCookie $ winSyncInterval $ oneWaySync $ winSyncM
oveAction $ nsds5ReplicaEnabled ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.503 NAME 'nsDSWindowsReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5replicaSessionPauseTime $ nsds7WindowsReplicaSubtree $ nsds7DirectoryReplicaSubtree $ nsds7NewWinUserSyncEnabled $ nsds7NewWinGroupSyncEnabled $ nsds7WindowsDomain $ nsds7DirsyncCookie $ winSyncInterval $ oneWaySync $ winSyncM
oveAction $ nsds5ReplicaEnabled $ winSyncDirectoryFilter $ winSyncWindowsFilter $ winSyncSubtreePair ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.128 NAME 'costemplate' DESC 'Netscape defined objectclass' SUP top MAY ( cn $ cospriority ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.304 NAME 'nsView' DESC 'Netscape defined objectclass' SUP top AUXILIARY MAY ( nsViewFilter $ description ) X-ORIGIN 'Netscape Directory Server' )
objectClasses: ( 2.16.840.1.113730.3.2.316 NAME 'nsAttributeEncryption' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsEncryptionAlgorithm ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index b2c69a3..fc11232 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -182,6 +182,9 @@ extern const char *type_nsds7WindowsDomain;
extern const char *type_winSyncInterval;
extern const char *type_oneWaySync;
extern const char *type_winsyncMoveAction;
+extern const char *type_winSyncWindowsFilter;
+extern const char *type_winSyncDirectoryFilter;
+extern const char *type_winSyncSubtreePair;
/* To Allow Consumer Initialisation when adding an agreement - */
extern const char *type_nsds5BeginReplicaRefresh;
diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c
index b934354..c0b8712 100644
--- a/ldap/servers/plugins/replication/repl_globals.c
+++ b/ldap/servers/plugins/replication/repl_globals.c
@@ -145,6 +145,9 @@ const char *type_nsds7DirsyncCookie = "nsds7DirsyncCookie";
const char *type_winSyncInterval = "winSyncInterval";
const char *type_oneWaySync = "oneWaySync";
const char *type_winsyncMoveAction = "winSyncMoveAction";
+const char *type_winSyncWindowsFilter = "winSyncWindowsFilter";
+const char *type_winSyncDirectoryFilter = "winSyncDirectoryFilter";
+const char *type_winSyncSubtreePair = "winSyncSubtreePair";
/* To Allow Consumer Initialization when adding an agreement - */
const char *type_nsds5BeginReplicaRefresh = "nsds5BeginReplicaRefresh";
diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c
index e6bd062..c7c7a98 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -846,12 +846,13 @@ send_dirsync_search(Repl_Connection *conn)
const char *op_string = NULL;
int rc;
int scope = LDAP_SCOPE_SUBTREE;
- char *filter = slapi_ch_strdup("(objectclass=*)");
+ const char *userfilter = NULL;
+ char *filter = NULL;
char **attrs = NULL;
LDAPControl **server_controls = NULL;
int msgid;
- /* need to strip the dn down to dc= */
const char *old_dn = slapi_sdn_get_ndn( windows_private_get_windows_subtree(conn->agmt) );
+ /* LDAP_SERVER_DIRSYNC_OID requires the search base Naming Context */
char *dn = slapi_ch_strdup(strstr(old_dn, "dc="));
char **exattrs = NULL;
@@ -861,8 +862,8 @@ send_dirsync_search(Repl_Connection *conn)
} else
{
slapi_add_control_ext(&server_controls,
- windows_private_dirsync_control(conn->agmt),
- 0 /* no copy - passin */);
+ windows_private_dirsync_control(conn->agmt),
+ 0 /* no copy - passin */);
}
conn->last_operation = CONN_SEARCH;
@@ -870,9 +871,15 @@ send_dirsync_search(Repl_Connection *conn)
op_string = "search";
LDAPDebug( LDAP_DEBUG_REPL, "Calling dirsync search request plugin\n", 0, 0, 0 );
+ userfilter = windows_private_get_windows_userfilter(conn->agmt);
+ if (userfilter) {
+ filter = slapi_ch_strdup(userfilter);
+ } else {
+ filter = slapi_ch_strdup("(objectclass=*)");
+ }
winsync_plugin_call_dirsync_search_params_cb(conn->agmt, old_dn, &dn, &scope, &filter,
- &attrs, &server_controls);
+ &attrs, &server_controls);
exattrs = windows_private_get_range_attrs(conn->agmt);
charray_merge(&attrs, exattrs, 0 /* pass in */);
slapi_ch_free((void **)&exattrs); /* strings are passed in */
@@ -1038,7 +1045,7 @@ Slapi_Entry * windows_conn_get_search_result(Repl_Connection *conn)
{
char **exattrs = NULL;
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"received entry from dirsync: %s\n", dn);
- lm = ldap_first_entry( conn->ld, res );
+ lm = ldap_first_entry( conn->ld, res );
e = windows_private_get_curr_entry(conn->agmt); /* if range search, e != NULL */
e = windows_LDAPMessage2Entry(e, conn, lm, 0, &exattrs);
ldap_memfree(dn);
diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c
index 51e959a..cfa2704 100644
--- a/ldap/servers/plugins/replication/windows_private.c
+++ b/ldap/servers/plugins/replication/windows_private.c
@@ -52,12 +52,12 @@
struct windowsprivate {
- Slapi_DN *windows_subtree; /* DN of synchronized subtree (on the windows side) */
+ Slapi_DN *windows_subtree; /* DN of synchronized subtree (on the windows side) */
Slapi_DN *directory_subtree; /* DN of synchronized subtree on directory side */
- /* this simplifies the mapping as it's simply
- from the former to the latter container, or
- vice versa */
- ber_int_t dirsync_flags;
+ /* this simplifies the mapping as it's simply
+ from the former to the latter container, or
+ vice versa */
+ ber_int_t dirsync_flags;
ber_int_t dirsync_maxattributecount;
char *dirsync_cookie;
int dirsync_cookie_len;
@@ -70,6 +70,7 @@ struct windowsprivate {
/* This filter is used to determine if an entry belongs to this agreement. We put it here
* so we only have to allocate each filter once instead of doing it every time we receive a change. */
Slapi_Filter *directory_filter; /* Used for checking if local entries need to be sync'd to AD */
+ Slapi_Filter *windows_filter; /* Used for checking if remote entries need to be sync'd to DS */
Slapi_Filter *deleted_filter; /* Used for checking if an entry is an AD tombstone */
Slapi_Entry *raw_entry; /* "raw" un-schema processed last entry read from AD */
int keep_raw_entry; /* flag to control when the raw entry is set */
@@ -79,9 +80,20 @@ struct windowsprivate {
int move_action; /* Indicates what to do with DS entry if AD entry is moved out of scope */
Slapi_Entry *curr_entry; /* entry being retrieved; used for the range retrieval */
char **range_attrs; /* next attributes for the range retrieval */
+ char *windows_userfilter;
+ char *directory_userfilter;
+ struct subtreepair *subtree_pairs; /* Array of subtree pairs (winSyncSubtreePair) */
+ Slapi_DN *windows_treetop; /* Common subtree top to sync on AD */
+ /* If winSyncSubtreePair is not set, identical to windows_subtree.
+ * If set, ancestor node of all AD subtrees. */
+ Slapi_DN *directory_treetop; /* Common subtree top to sync on DS */
+ /* If winSyncSubtreePair is not set, identical to directory_subtree.
+ * If set, ancestor node of all DS subtrees. */
};
static void windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain);
+static subtreePair *create_subtree_pairs(char **pairs);
+static void free_subtree_pairs(subtreePair **pairs);
static int
true_value_from_string(char *val)
@@ -153,6 +165,10 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e)
return retval;
}
+ /*
+ * if winSyncSubtreePair is set, WindowsReplicaArea and DirectoryReplicaArea
+ * are ignored.
+ */
if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsReplicaArea))
{
tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsReplicaArea);
@@ -295,6 +311,29 @@ windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e)
}
retval = 1;
}
+ if (type == NULL || slapi_attr_types_equivalent(type,type_winSyncWindowsFilter))
+ {
+ tmpstr = slapi_entry_attr_get_charptr(e, type_winSyncWindowsFilter);
+ windows_private_set_windows_userfilter(ra, tmpstr); /* if NULL, set it */
+ retval = 1;
+ }
+ if (type == NULL || slapi_attr_types_equivalent(type,type_winSyncDirectoryFilter))
+ {
+ tmpstr = slapi_entry_attr_get_charptr(e, type_winSyncDirectoryFilter);
+ windows_private_set_directory_userfilter(ra, tmpstr); /* if NULL, set it */
+ retval = 1;
+ }
+ if (type == NULL || slapi_attr_types_equivalent(type, type_winSyncSubtreePair))
+ {
+ char **parray = slapi_entry_attr_get_charray(e, type_winSyncSubtreePair);
+
+ /* If winSyncSubtreePair is not set, subtree_pairs is NULL */
+ windows_private_set_subtreepairs(ra, parray);
+ slapi_ch_array_free(parray);
+ retval = 1;
+ }
+ windows_private_set_windows_treetop(ra, NULL);
+ windows_private_set_directory_treetop(ra, NULL);
return retval;
}
@@ -370,8 +409,14 @@ Dirsync_Private* windows_private_new()
dp->dirsync_maxattributecount = -1;
dp->directory_filter = NULL;
+ dp->windows_filter = NULL;
dp->deleted_filter = NULL;
dp->sync_interval = PERIODIC_DIRSYNC_INTERVAL;
+ dp->windows_userfilter = NULL;
+ dp->directory_userfilter = NULL;
+ dp->subtree_pairs = NULL;
+ dp->windows_treetop = NULL;
+ dp->directory_treetop = NULL;
LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_new\n" );
return dp;
@@ -380,6 +425,7 @@ Dirsync_Private* windows_private_new()
void windows_agreement_delete(Repl_Agmt *ra)
{
+ const subtreePair *sp;
Dirsync_Private *dp = (Dirsync_Private *) agmt_get_priv(ra);
LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_delete\n" );
@@ -394,12 +440,25 @@ void windows_agreement_delete(Repl_Agmt *ra)
slapi_sdn_free(&dp->directory_subtree);
slapi_sdn_free(&dp->windows_subtree);
slapi_filter_free(dp->directory_filter, 1);
+ slapi_filter_free(dp->windows_filter, 1);
slapi_filter_free(dp->deleted_filter, 1);
slapi_entry_free(dp->raw_entry);
slapi_ch_free_string(&dp->windows_domain);
dp->raw_entry = NULL;
dp->api_cookie = NULL;
- slapi_ch_free((void **)dp);
+ slapi_ch_free_string(&dp->dirsync_cookie);
+ dp->dirsync_cookie_len = 0;
+
+ slapi_ch_free_string(&dp->windows_userfilter);
+ slapi_ch_free_string(&dp->directory_userfilter);
+ slapi_sdn_free((Slapi_DN **)&dp->windows_treetop);
+ slapi_sdn_free((Slapi_DN **)&dp->directory_treetop);
+ for (sp = dp->subtree_pairs; sp && sp->ADsubtree && sp->DSsubtree; sp++) {
+ slapi_sdn_free((Slapi_DN **)&sp->ADsubtree);
+ slapi_sdn_free((Slapi_DN **)&sp->DSsubtree);
+ }
+ slapi_ch_free((void **)&dp->subtree_pairs);
+ slapi_ch_free((void **)&dp);
LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_delete\n" );
@@ -407,183 +466,228 @@ void windows_agreement_delete(Repl_Agmt *ra)
int windows_private_get_isnt4(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_isnt4\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_isnt4\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_isnt4\n" );
-
- return dp->isnt4;
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_isnt4\n" );
+
+ return dp->isnt4;
}
void windows_private_set_isnt4(const Repl_Agmt *ra, int isit)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_isnt4\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_isnt4\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- dp->isnt4 = isit;
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_isnt4\n" );
+ dp->isnt4 = isit;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_isnt4\n" );
}
int windows_private_get_iswin2k3(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_iswin2k3\n" );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_iswin2k3\n" );
- return dp->iswin2k3;
+ return dp->iswin2k3;
}
void windows_private_set_iswin2k3(const Repl_Agmt *ra, int isit)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_iswin2k3\n" );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- dp->iswin2k3 = isit;
+ dp->iswin2k3 = isit;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_iswin2k3\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_iswin2k3\n" );
}
/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */
Slapi_Filter* windows_private_get_directory_filter(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_filter\n" );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- if (dp->directory_filter == NULL) {
- char *string_filter = slapi_ch_strdup("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*))");
- /* The filter gets freed in windows_agreement_delete() */
- dp->directory_filter = slapi_str2filter( string_filter );
- slapi_ch_free_string(&string_filter);
+ if (dp->directory_filter == NULL) {
+ char *string_filter = NULL;
+ const char *userfilter = windows_private_get_directory_userfilter(ra);
+ if (userfilter) {
+ if ('(' == *userfilter) {
+ string_filter = slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*)%s)",
+ userfilter);
+ } else {
+ string_filter = slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*)(%s))",
+ userfilter);
+ }
+ } else {
+ string_filter = slapi_ch_strdup("(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*))");
}
+ /* The filter gets freed in windows_agreement_delete() */
+ dp->directory_filter = slapi_str2filter( string_filter );
+ slapi_ch_free_string(&string_filter);
+ }
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_filter\n" );
- return dp->directory_filter;
+ return dp->directory_filter;
}
/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */
-Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra)
+Slapi_Filter*
+windows_private_get_windows_filter(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_deleted_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_filter\n" );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- if (dp->deleted_filter == NULL) {
- char *string_filter = slapi_ch_strdup("(isdeleted=*)");
+ if (dp->windows_filter == NULL) {
+ const char *userfilter = windows_private_get_windows_userfilter(ra);
+ if (userfilter) {
+ char *string_filter = NULL;
+ if ('(' == *userfilter) {
+ string_filter = slapi_ch_strdup(userfilter);
+ } else {
+ string_filter = slapi_ch_smprintf("(%s)", userfilter);
+ }
/* The filter gets freed in windows_agreement_delete() */
- dp->deleted_filter = slapi_str2filter( string_filter );
+ dp->windows_filter = slapi_str2filter( string_filter );
slapi_ch_free_string(&string_filter);
}
+ }
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_filter\n" );
+
+ return dp->windows_filter;
+}
+
+/* Returns a copy of the Slapi_Filter pointer. The caller should not free it */
+Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_deleted_filter\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ if (dp->deleted_filter == NULL) {
+ char *string_filter = slapi_ch_strdup("(isdeleted=*)");
+ /* The filter gets freed in windows_agreement_delete() */
+ dp->deleted_filter = slapi_str2filter( string_filter );
+ slapi_ch_free_string(&string_filter);
+ }
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_deleted_filter\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_deleted_filter\n" );
- return dp->deleted_filter;
+ return dp->deleted_filter;
}
/* Returns a copy of the Slapi_DN pointer, no need to free it */
const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_subtree\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_subtree\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_subtree\n" );
-
- return dp->windows_subtree;
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_subtree\n" );
+
+ return dp->windows_subtree;
}
const char *
windows_private_get_windows_domain(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_domain\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_domain\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_domain\n" );
-
- return dp->windows_domain;
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_domain\n" );
+
+ return dp->windows_domain;
}
static void
windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_domain\n" );
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_domain\n" );
- PR_ASSERT(ra);
+ PR_ASSERT(ra);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- slapi_ch_free_string(&dp->windows_domain);
- dp->windows_domain = domain;
-
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_domain\n" );
- }
+ slapi_ch_free_string(&dp->windows_domain);
+ dp->windows_domain = domain;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_domain\n" );
+}
/* Returns a copy of the Slapi_DN pointer, no need to free it */
const Slapi_DN* windows_private_get_directory_subtree (const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_replarea\n" );
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_replarea\n" );
+ PR_ASSERT(ra);
- PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
- dp = (Dirsync_Private *) agmt_get_priv(ra);
- PR_ASSERT (dp);
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_replarea\n" );
- LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_replarea\n" );
-
- return dp->directory_subtree;
+ return dp->directory_subtree;
}
/* Takes a copy of the sdn passed in */
@@ -724,6 +828,299 @@ void windows_private_set_one_way(const Repl_Agmt *ra, int value)
LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_one_way\n" );
}
+const char*
+windows_private_get_windows_userfilter(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_userfilter\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_userfilter\n" );
+
+ return dp->windows_userfilter;
+}
+
+/* filter is passed in */
+void
+windows_private_set_windows_userfilter(const Repl_Agmt *ra, char *filter)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_userfilter\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_ch_free_string(&dp->windows_userfilter);
+ dp->windows_userfilter = filter;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_userfilter\n" );
+}
+
+const char*
+windows_private_get_directory_userfilter(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_userfilter\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_userfilter\n" );
+
+ return dp->directory_userfilter;
+}
+
+/* filter is passed in */
+void
+windows_private_set_directory_userfilter(const Repl_Agmt *ra, char *filter)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_directory_userfilter\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_ch_free_string(&dp->directory_userfilter);
+ dp->directory_userfilter = filter;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_directory_userfilter\n" );
+}
+
+const subtreePair*
+windows_private_get_subtreepairs(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_subtreepairs\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_subtreepairs\n" );
+
+ return dp->subtree_pairs;
+}
+
+/* parray is NOT passed in */
+void
+windows_private_set_subtreepairs(const Repl_Agmt *ra, char **parray)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_subtreepairs\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ free_subtree_pairs(&(dp->subtree_pairs));
+ dp->subtree_pairs = create_subtree_pairs(parray);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_subtreepairs\n" );
+}
+
+/*
+ * winSyncSubtreePair: <DS_SUBTREE>:<WINDOWS_SUBTREE>
+ * E.g.,
+ * winSyncSubtreePair: ou=people,dc=example,dc=com:CN=users,DC=example,DC=com
+ * winSyncSubtreePair: ou=adminpeople,dc=example,dc=com:CN=adminusers,DC=example,DC=com
+ */
+static subtreePair *
+create_subtree_pairs(char **pairs)
+{
+ subtreePair *subtree_pairs = NULL;
+ subtreePair *spp;
+ char **ptr;
+ char *p0, *p1;
+ char *saveptr;
+ int cnt;
+
+ for (cnt = 0, ptr = pairs; ptr && *ptr; cnt++, ptr++) ;
+ if (0 == cnt) {
+ return NULL;
+ }
+ subtree_pairs = (subtreePair *)slapi_ch_calloc(cnt + 1, sizeof(subtreePair));
+ spp = subtree_pairs;
+
+ for (ptr = pairs; ptr && *ptr; ptr++) {
+ p0 = ldap_utf8strtok_r(*ptr, ":", &saveptr);
+ p1 = ldap_utf8strtok_r(NULL, ":", &saveptr);
+ spp->DSsubtree = slapi_sdn_new_dn_byval(p0);
+ if (NULL == spp->DSsubtree) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "create_subtree_pairs: "
+ "Ignoring invalid DS subtree \"%s\".\n",
+ p0);
+ continue;
+ }
+ spp->ADsubtree = slapi_sdn_new_dn_byval(p1);
+ if (NULL == spp->ADsubtree) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "create_subtree_pairs: "
+ "Ignoring invalid AD subtree \"%s\".\n",
+ p1);
+ slapi_sdn_free(&(spp->DSsubtree));
+ continue;
+ }
+ spp++;
+ }
+ return subtree_pairs;
+}
+
+static void
+free_subtree_pairs(subtreePair **pairs)
+{
+ subtreePair *p;
+
+ if (NULL == pairs) {
+ return;
+ }
+ for (p = *pairs; p; p++) {
+ slapi_sdn_free(&(p->ADsubtree));
+ slapi_sdn_free(&(p->DSsubtree));
+ }
+ slapi_ch_free((void **)pairs);
+}
+
+const Slapi_DN*
+windows_private_get_windows_treetop(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_treetop\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_treetop\n" );
+
+ return dp->windows_treetop;
+}
+
+/* treetop is NOT passed in */
+void
+windows_private_set_windows_treetop(const Repl_Agmt *ra, char *treetop)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_treetop\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_sdn_free(&(dp->windows_treetop));
+ if (treetop) {
+ dp->windows_treetop = slapi_sdn_new_dn_byval(treetop);
+ } else {
+ const subtreePair *subtree_pairs = windows_private_get_subtreepairs(ra);
+ const subtreePair *sp;
+ if (subtree_pairs) {
+ Slapi_DN *treetop_sdn = NULL;
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ if (NULL == treetop_sdn) {
+ treetop_sdn = slapi_sdn_dup(sp->ADsubtree);
+ } else {
+ Slapi_DN *prev = treetop_sdn;
+ treetop_sdn = slapi_sdn_common_ancestor(prev, sp->ADsubtree);
+ slapi_sdn_free(&prev);
+ }
+ }
+ if (treetop_sdn) {
+ dp->windows_treetop = treetop_sdn;
+ } else {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "windows_private_set_windows_treetop: "
+ "winSyncSubtreePair contains inconsistent Windows subtrees.\n");
+ dp->windows_treetop = NULL;
+ }
+ } else {
+ const Slapi_DN *windows_subtree = windows_private_get_windows_subtree(ra);
+ dp->windows_treetop = slapi_sdn_dup(windows_subtree);
+ }
+ }
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_treetop\n" );
+}
+
+const Slapi_DN*
+windows_private_get_directory_treetop(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_treetop\n" );
+
+ PR_ASSERT(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_treetop\n" );
+
+ return dp->directory_treetop;
+}
+
+/* treetop is NOT passed in */
+void
+windows_private_set_directory_treetop(const Repl_Agmt *ra, char *treetop)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_private_set_directory_treetop\n" );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ slapi_sdn_free(&(dp->directory_treetop));
+ if (treetop) {
+ dp->directory_treetop = slapi_sdn_new_dn_byval(treetop);
+ } else {
+ const subtreePair *subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair *sp;
+ Slapi_DN *treetop_sdn = NULL;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (NULL == treetop_sdn) {
+ treetop_sdn = slapi_sdn_dup(sp->DSsubtree);
+ } else {
+ Slapi_DN *prev = treetop_sdn;
+ treetop_sdn = slapi_sdn_common_ancestor(prev, sp->DSsubtree);
+ slapi_sdn_free(&prev);
+ }
+ }
+ if (treetop_sdn) {
+ dp->directory_treetop = treetop_sdn;
+ } else {
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
+ "windows_private_set_directory_treetop: "
+ "winSyncSubtreePair contains inconsistent Windows subtrees.\n");
+ dp->directory_treetop = NULL;
+ }
+ } else {
+ const Slapi_DN *directory_subtree = windows_private_get_directory_subtree(ra);
+ dp->directory_treetop = slapi_sdn_dup(directory_subtree);
+ }
+ }
+
+ LDAPDebug0Args( LDAP_DEBUG_TRACE, "<= windows_private_set_directory_treetop\n" );
+}
/*
This function returns the current Dirsync_Private that's inside
@@ -744,7 +1141,7 @@ LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
- ber = ber_alloc();
+ ber = ber_alloc();
ber_printf( ber, "{iio}", dp->dirsync_flags, dp->dirsync_maxattributecount, dp->dirsync_cookie ? dp->dirsync_cookie : "", dp->dirsync_cookie_len );
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index e618be0..40b5c3f 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -1136,10 +1136,33 @@ process_replay_add(Private_Repl_Protocol *prp, Slapi_Entry *add_entry, Slapi_Ent
if (cn_string) {
char *container_str = NULL;
- const char *suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ const char *suffix = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
+ /* Figure out the Windows subtree from the local subtree... */
+ local_sdn = slapi_entry_get_sdn_const(local_entry);
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (slapi_sdn_scope_test(local_sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE)) {
+ suffix = slapi_sdn_get_dn(sp->ADsubtree);
+ break;
+ }
+ }
+ }
+ if (NULL == suffix) {
+ suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ }
- container_str = extract_container(slapi_entry_get_sdn_const(local_entry),
- windows_private_get_directory_subtree(prp->agmt));
+ if (sp && sp->DSsubtree) {
+ container_str = extract_container(slapi_entry_get_sdn_const(local_entry),
+ sp->DSsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(local_entry),
+ windows_private_get_directory_subtree(prp->agmt));
+ }
new_dn_string = slapi_create_dn_string("cn=\"%s\",%s%s", cn_string, container_str, suffix);
if (new_dn_string) {
@@ -1311,7 +1334,9 @@ process_replay_rename(Private_Repl_Protocol *prp,
char *remote_rdn = NULL;
char *remote_dn = NULL;
char *local_pndn = NULL;
-
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
if (NULL == local_origsdn || NULL == local_newentry) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"process_replay_rename: %s is empty\n",
@@ -1324,29 +1349,40 @@ process_replay_rename(Private_Repl_Protocol *prp,
/* Generate newsuperior for AD */
winrepl_agmt = prp->agmt;
- remote_subtree =
- slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
- local_subtree =
- slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
- if (NULL == remote_subtree || NULL == local_subtree ||
- '\0' == *remote_subtree || '\0' == *local_subtree) {
+ remote_subtree = slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
+ local_subtree = slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
+ subtree_pairs = windows_private_get_subtreepairs(winrepl_agmt);
+ if ((NULL == remote_subtree || NULL == local_subtree ||
+ '\0' == *remote_subtree || '\0' == *local_subtree) &&
+ (NULL == subtree_pairs)) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"process_replay_rename: local subtree \"%s\" or "
- "remote subtree \"%s\" is empty\n",
+ "remote subtree \"%s\" and "
+ "subtree_pairs are empty\n",
local_subtree?local_subtree:"empty",
remote_subtree?remote_subtree:"empty");
goto bail;
}
- /* if given, newparent is already normzlized; just ignore the case */
+ /* if given, newparent is already normalized; just ignore the case */
if (newparent) {
norm_newparent = slapi_ch_strdup(newparent);
+ slapi_dn_ignore_case(norm_newparent);
} else {
/* newparent is NULL; set the original parent */
/* slapi_dn_parent returns the dup'ed dn */
norm_newparent = slapi_dn_parent(slapi_sdn_get_ndn(local_origsdn));
}
- slapi_dn_ignore_case(norm_newparent);
- p = strstr(norm_newparent, local_subtree);
+ p = NULL;
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ p = strstr(norm_newparent, slapi_sdn_get_ndn(sp->DSsubtree));
+ if (p) {
+ break;
+ }
+ }
+ } else {
+ p = strstr(norm_newparent, local_subtree);
+ }
if (NULL == p) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"process_replay_rename: new superior \"%s\" is not "
@@ -1354,11 +1390,20 @@ process_replay_rename(Private_Repl_Protocol *prp,
norm_newparent, local_subtree);
goto bail; /* not in the subtree */
}
- *p = '\0';
- if (p == norm_newparent) {
- newsuperior = PR_smprintf("%s", remote_subtree);
+ if (sp && sp->DSsubtree) {
+ if (p == norm_newparent) {
+ newsuperior = PR_smprintf("%s", slapi_sdn_get_ndn(sp->ADsubtree));
+ } else {
+ *p = '\0';
+ newsuperior = PR_smprintf("%s%s", norm_newparent, slapi_sdn_get_ndn(sp->ADsubtree));
+ }
} else {
- newsuperior = PR_smprintf("%s%s", norm_newparent, remote_subtree);
+ if (p == norm_newparent) {
+ newsuperior = PR_smprintf("%s", remote_subtree);
+ } else {
+ *p = '\0';
+ newsuperior = PR_smprintf("%s%s", norm_newparent, remote_subtree);
+ }
}
if (is_user) {
@@ -1385,7 +1430,16 @@ process_replay_rename(Private_Repl_Protocol *prp,
/* local parent normalized dn */
local_pndn = /* strdup'ed */
slapi_dn_parent((const char *)slapi_sdn_get_ndn(local_origsdn));
- p = strstr(local_pndn, local_subtree);
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ p = strstr(local_pndn, slapi_sdn_get_ndn(sp->DSsubtree));
+ if (p) {
+ break;
+ }
+ }
+ } else {
+ p = strstr(local_pndn, local_subtree);
+ }
if (NULL == p) {
/* Original entry is not in the subtree.
* To add the entry after returning from this function,
@@ -1393,10 +1447,23 @@ process_replay_rename(Private_Repl_Protocol *prp,
windows_conn_set_error(prp->conn, LDAP_NO_SUCH_OBJECT);
goto bail;
}
- *p = '\0';
/* generate a remote dn */
- remote_dn = PR_smprintf("%s,%s%s", remote_rdn, local_pndn, remote_subtree);
+ if (sp && sp->DSsubtree) {
+ if (p == local_pndn) {
+ remote_dn = PR_smprintf("%s,%s", remote_rdn, slapi_sdn_get_ndn(sp->ADsubtree));
+ } else {
+ *p = '\0';
+ remote_dn = PR_smprintf("%s,%s%s", remote_rdn, local_pndn, slapi_sdn_get_ndn(sp->ADsubtree));
+ }
+ } else {
+ if (p == local_pndn) {
+ remote_dn = PR_smprintf("%s,%s", remote_rdn, remote_subtree);
+ } else {
+ *p = '\0';
+ remote_dn = PR_smprintf("%s,%s%s", remote_rdn, local_pndn, remote_subtree);
+ }
+ }
if (!deleteoldrdn) {
/* AD does not accept deleteoldrdn == 0 */
/*
@@ -1677,7 +1744,7 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op
case SLAPI_OPERATION_MODRDN:
/* only move case (newsuperior: ...) comse here since local leaf RDN is
* not identical to the remote leaf RDN. */
- {
+ {
return_value = process_replay_rename(prp, local_entry, local_dn,
op->p.p_modrdn.modrdn_newrdn,
REPL_GET_DN(&op->p.p_modrdn.modrdn_newsuperior_address),
@@ -1696,7 +1763,7 @@ windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op
}
}
break;
- }
+ }
default:
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: replay_update: Unknown "
"operation type %lu found in changelog - skipping change.\n",
@@ -2372,8 +2439,12 @@ windows_get_superior_change(Private_Repl_Protocol *prp,
char *local_pndn = NULL; /* Normalized parent dn of the local entry */
const char *remote_subtree = NULL; /* Normalized subtree of the remote entry */
const char *local_subtree = NULL; /* Normalized subtree of the local entry */
- char *ptr = NULL;
+ char *mptr = NULL;
+ char *lptr = NULL;
int rc = -1;
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* msp = NULL;
+ const subtreePair* lsp = NULL;
if (NULL == newsuperior) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
@@ -2389,15 +2460,16 @@ windows_get_superior_change(Private_Repl_Protocol *prp,
/* Check if modrdn with superior has happened on AD */
winrepl_agmt = prp->agmt;
- remote_subtree =
- slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
- local_subtree =
- slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
- if (NULL == remote_subtree || NULL == local_subtree ||
- '\0' == *remote_subtree || '\0' == *local_subtree) {
+ remote_subtree = slapi_sdn_get_ndn(windows_private_get_windows_subtree(winrepl_agmt));
+ local_subtree = slapi_sdn_get_ndn(windows_private_get_directory_subtree(winrepl_agmt));
+ subtree_pairs = windows_private_get_subtreepairs(winrepl_agmt);
+ if ((NULL == remote_subtree || NULL == local_subtree ||
+ '\0' == *remote_subtree || '\0' == *local_subtree) &&
+ (NULL == subtree_pairs)) {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
"windows_get_superior_change: local subtree \"%s\" or "
- "remote subtree \"%s\" is empty\n",
+ "remote subtree \"%s\" and "
+ "subtree_pairs are empty\n",
local_subtree?local_subtree:"empty",
remote_subtree?remote_subtree:"empty");
goto bail;
@@ -2423,18 +2495,69 @@ windows_get_superior_change(Private_Repl_Protocol *prp,
mapped_pndn?mapped_pndn:"empty");
goto bail;
}
- ptr = strstr(mapped_pndn, local_subtree);
- if (ptr) {
- *ptr = '\0'; /* if ptr != mapped_pndn, mapped_pndn ends with ',' */
- ptr = strstr(local_pndn, local_subtree);
- if (ptr) {
- *ptr = '\0'; /* if ptr != local_pndn, local_pndn ends with ',' */
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (msp = subtree_pairs; msp && msp->DSsubtree; msp++) {
+ mptr = strstr(mapped_pndn, slapi_sdn_get_ndn(msp->DSsubtree));
+ if (mptr) {
+ break;
+ }
+ }
+ } else {
+ mptr = strstr(mapped_pndn, local_subtree);
+ }
+ if (mptr) {
+ /* mapped DN (originally from AD) is in the DS subtree(s) defined in the agreement */
+ if (subtree_pairs && subtree_pairs->DSsubtree) {
+ for (lsp = subtree_pairs; lsp && lsp->DSsubtree; lsp++) {
+ lptr = strstr(local_pndn, slapi_sdn_get_ndn(lsp->DSsubtree));
+ if (lptr) {
+ break;
+ }
+ }
+ } else {
+ lptr = strstr(local_pndn, local_subtree);
+ }
+ if (lptr) {
+ /* local DN is in the DS subtree(s) defined in the agreement*/
if (0 != strcmp(mapped_pndn, local_pndn)) {
- /* the remote parent is different from the local parent */
- if (to_windows) {
- *newsuperior = slapi_create_dn_string("%s%s", local_pndn, remote_subtree);
- } else {
- *newsuperior = slapi_create_dn_string("%s%s", mapped_pndn, local_subtree);
+ /*
+ * The mapped remote parent is different from the local parent.
+ * we need to move the entry to the new superior.
+ */
+ if (to_windows) { /* from DS to AD */
+ if (lsp && lsp->ADsubtree) {
+ if (lptr == local_pndn) {
+ *newsuperior = slapi_ch_strdup(slapi_sdn_get_ndn(lsp->ADsubtree));
+ } else {
+ *lptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", local_pndn,
+ slapi_sdn_get_ndn(lsp->ADsubtree));
+ }
+ } else {
+ if (lptr == local_pndn) {
+ *newsuperior = slapi_ch_smprintf("%s", remote_subtree);
+ } else {
+ *lptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", local_pndn, remote_subtree);
+ }
+ }
+ } else { /* from AD to DS */
+ if (msp && msp->DSsubtree) {
+ if (mptr == mapped_pndn) {
+ *newsuperior = slapi_ch_strdup(slapi_sdn_get_ndn(msp->DSsubtree));
+ } else {
+ *mptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", mapped_pndn,
+ slapi_sdn_get_ndn(msp->DSsubtree));
+ }
+ } else {
+ if (mptr == mapped_pndn) {
+ *newsuperior = slapi_ch_strdup(local_subtree);
+ } else {
+ *mptr = '\0';
+ *newsuperior = slapi_ch_smprintf("%s%s", mapped_pndn, local_subtree);
+ }
+ }
}
rc = 0;
}
@@ -2642,6 +2765,7 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,
const Slapi_Entry *ad_entry = NULL;
Slapi_Entry *ad_entry_copy = NULL;
const Slapi_DN *windows_subtree = NULL;
+ const subtreePair* subtree_pairs = NULL;
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_map_mods_for_replay\n", 0, 0, 0 );
if (NULL == prp) {
@@ -2650,7 +2774,8 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,
return;
}
windows_subtree = windows_private_get_windows_subtree(prp->agmt);
- if (NULL == windows_subtree) {
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if ((NULL == windows_subtree) && (NULL == subtree_pairs)) {
LDAPDebug(LDAP_DEBUG_TRACE,
"<= windows_map_mods_for_replay; NULL agreement subtree; NOOP\n", 0, 0, 0);
return;
@@ -2770,8 +2895,17 @@ windows_map_mods_for_replay(Private_Repl_Protocol *prp,
const char *strval = slapi_value_get_string(valp); /* no dup */
if (strval) {
slapi_sdn_set_dn_byref(sdn, strval);
- is_in_subtree = slapi_sdn_scope_test(sdn, windows_subtree,
- LDAP_SCOPE_SUBTREE);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ is_in_subtree = slapi_sdn_scope_test(sdn, sp->ADsubtree, LDAP_SCOPE_SUBTREE);
+ if (is_in_subtree) {
+ break;
+ }
+ }
+ } else {
+ is_in_subtree = slapi_sdn_scope_test(sdn, windows_subtree, LDAP_SCOPE_SUBTREE);
+ }
if (is_in_subtree) {
/*
* If delete all on DS,
@@ -3015,18 +3149,18 @@ find_entry_by_attr_value_remote(const char *attribute, const char *value, Slapi_
int retval = 0;
ConnResult cres = 0;
char *filter = NULL;
- const char *searchbase = NULL;
+ const Slapi_DN *searchbase = NULL;
Slapi_Entry *found_entry = NULL;
/* should not have to escape attribute names */
filter = slapi_filter_sprintf("(%s=%s%s)",attribute, ESC_NEXT_VAL, value);
- searchbase = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
- cres = windows_search_entry(prp->conn, (char*)searchbase, filter, &found_entry);
+ searchbase = windows_private_get_windows_treetop(prp->agmt);
+ cres = windows_search_entry(prp->conn, (char*)slapi_sdn_get_dn(searchbase), filter, &found_entry);
if (cres)
{
retval = -1;
} else
- {
+ {
if (found_entry)
{
*e = found_entry;
@@ -3136,7 +3270,7 @@ find_entry_by_attr_value(const char *attribute, const char *value, Slapi_Entry *
Slapi_Entry **entries = NULL, **ep = NULL;
Slapi_Entry *entry_found = NULL;
LDAPControl **server_controls = NULL;
- const char *subtree_dn = NULL;
+ const Slapi_DN *subtree_sdn = NULL;
char *subtree_dn_copy = NULL;
char **attrs = NULL;
char *query = NULL;
@@ -3152,10 +3286,10 @@ find_entry_by_attr_value(const char *attribute, const char *value, Slapi_Entry *
query = slapi_filter_sprintf("(%s=%s%s)", attribute, ESC_NEXT_VAL, value);
if (query == NULL)
- goto done;
+ goto done;
- subtree_dn = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
- subtree_dn_copy = slapi_ch_strdup(subtree_dn);
+ subtree_sdn = windows_private_get_directory_treetop(ra);
+ subtree_dn_copy = slapi_ch_strdup(slapi_sdn_get_ndn(subtree_sdn));
winsync_plugin_call_pre_ds_search_entry_cb(ra, NULL, &subtree_dn_copy, &scope, &query,
&attrs, &server_controls);
@@ -3391,9 +3525,10 @@ map_windows_tombstone_dn(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *p
/* The tombstone suffix discards any containers, so we need
* to trim the DN to only dc components. */
- if ((suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt)))) {
+ suffix = slapi_sdn_get_ndn(windows_private_get_windows_treetop(prp->agmt));
+ if (suffix) {
/* If this isn't found, it is treated as an error below. */
- suffix = (const char *) PL_strcasestr(suffix,"dc=");
+ suffix = (const char *)PL_strstr(suffix, "dc=");
}
if (cn && guid && suffix) {
@@ -3566,7 +3701,18 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp,
char *guid = NULL;
Slapi_DN *new_dn = NULL;
int is_nt4 = windows_private_get_isnt4(prp->agmt);
- const char *suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ const char *suffix = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
+ if (NULL == e) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_outbound: NULL entry.\n",
+ agmt_get_long_name(prp->agmt));
+ return -1;
+ }
+
/* To find the DN of the peer entry we first look for an ntUniqueId attribute
* on the local entry. If that's present, we generate a GUID-form DN.
* If there's no GUID, then we look for an ntUserDomainId attribute
@@ -3585,6 +3731,25 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp,
*dn = NULL;
*missing_entry = 0;
+ local_sdn = slapi_entry_get_sdn_const(e);
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (slapi_sdn_scope_test(local_sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE)) {
+ suffix = slapi_sdn_get_dn(sp->ADsubtree);
+ break;
+ }
+ }
+ } else {
+ suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ }
+ if (NULL == suffix) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_outbound: Failed to get the AD suffix of %s.\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(local_sdn));
+ return -1;
+ }
+
guid = slapi_entry_attr_get_charptr(e,"ntUniqueId");
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
"%s: map_entry_dn_outbound: looking for AD entry for DS "
@@ -3646,8 +3811,12 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp,
if (cn_string) {
char *container_str = NULL;
- container_str = extract_container(slapi_entry_get_sdn_const(e),
- windows_private_get_directory_subtree(prp->agmt));
+ if (sp) {
+ container_str = extract_container(slapi_entry_get_sdn_const(e), sp->DSsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(e),
+ windows_private_get_directory_subtree(prp->agmt));
+ }
new_dn_string = slapi_create_dn_string("cn=\"%s\",%s%s", cn_string, container_str, suffix);
if (new_dn_string) {
@@ -3714,7 +3883,12 @@ map_entry_dn_outbound(Slapi_Entry *e, Slapi_DN **dn, Private_Repl_Protocol *prp,
char *rdnstr = NULL;
char *container_str = NULL;
- container_str = extract_container(slapi_entry_get_sdn_const(e), windows_private_get_directory_subtree(prp->agmt));
+ if (sp) {
+ container_str = extract_container(slapi_entry_get_sdn_const(e), sp->DSsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(e),
+ windows_private_get_directory_subtree(prp->agmt));
+ }
rdnstr = is_nt4 ? "samaccountname=\"%s\",%s%s" : "cn=\"%s\",%s%s";
@@ -3843,6 +4017,14 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
int is_user = 0;
int is_group = 0;
int is_nt4 = windows_private_get_isnt4(ra);
+ char *container_str = NULL;
+
+ if (NULL == e) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_inbound: entry is NULL.\n",
+ agmt_get_long_name(ra));
+ return -1;
+ }
/* To map a non-tombstone's DN we need to first try to look it up by GUID.
* If we do not find it, then we need to generate the DN that it would have if added as a new entry.
@@ -3967,10 +4149,34 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
char *new_dn_string = NULL;
if (username)
{
- const char *suffix = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
- char *container_str = NULL;
+ const char *suffix = NULL;
+ const subtreePair* subtree_pairs = windows_private_get_subtreepairs(ra);
+ const subtreePair* sp = NULL;
+ const Slapi_DN *remote_sdn = slapi_entry_get_sdn_const(e);
+
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ if (slapi_sdn_scope_test(remote_sdn, sp->ADsubtree, LDAP_SCOPE_SUBTREE)) {
+ suffix = slapi_sdn_get_dn(sp->DSsubtree);
+ break;
+ }
+ }
+ } else {
+ suffix = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
+ }
- container_str = extract_container(slapi_entry_get_sdn_const(e), windows_private_get_windows_subtree(ra));
+ if (sp) {
+ container_str = extract_container(slapi_entry_get_sdn_const(e), sp->ADsubtree);
+ } else {
+ container_str = extract_container(slapi_entry_get_sdn_const(e),
+ windows_private_get_windows_subtree(ra));
+ }
+ if (NULL == suffix) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: map_entry_dn_inbound: Failed to retrieve local suiffx from %s\n",
+ agmt_get_long_name(ra), slapi_sdn_get_dn(remote_sdn));
+ goto error;
+ }
/* Local DNs for users and groups are different */
if (is_user)
{
@@ -3979,8 +4185,10 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
windows_private_get_raw_entry(ra),
e,
&new_dn_string,
- windows_private_get_directory_subtree(ra),
- windows_private_get_windows_subtree(ra));
+ sp?sp->DSsubtree:
+ windows_private_get_directory_subtree(ra),
+ sp?sp->ADsubtree:
+ windows_private_get_windows_subtree(ra));
} else
{
new_dn_string = slapi_create_dn_string("cn=\"%s\",%s%s",username,container_str,suffix);
@@ -3989,8 +4197,10 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
windows_private_get_raw_entry(ra),
e,
&new_dn_string,
- windows_private_get_directory_subtree(ra),
- windows_private_get_windows_subtree(ra));
+ sp?sp->DSsubtree:
+ windows_private_get_directory_subtree(ra),
+ sp?sp->ADsubtree:
+ windows_private_get_windows_subtree(ra));
}
}
/*
@@ -3998,7 +4208,6 @@ map_entry_dn_inbound_ext(Slapi_Entry *e, Slapi_DN **dn, const Repl_Agmt *ra, int
* which is normalized. Thus, we can use _normdn_.
*/
new_dn = slapi_sdn_new_normdn_passin(new_dn_string);
- slapi_ch_free_string(&container_str);
} else
{
/* Error, no username */
@@ -4015,14 +4224,9 @@ error:
{
PR_smprintf_free(guid);
}
- if (matching_entry)
- {
- slapi_entry_free(matching_entry);
- }
- if (username)
- {
- slapi_ch_free_string(&username);
- }
+ slapi_entry_free(matching_entry);
+ slapi_ch_free_string(&username);
+ slapi_ch_free_string(&container_str);
return retval;
}
@@ -4034,30 +4238,41 @@ is_subject_of_agreement_local(const Slapi_Entry *local_entry, const Repl_Agmt *r
{
int retval = 0;
int is_in_subtree = 0;
- const Slapi_DN *agreement_subtree = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
- /* First test for the sync'ed subtree */
- agreement_subtree = windows_private_get_directory_subtree(ra);
- if (NULL == agreement_subtree)
- {
+ if (!local_entry) {
+ /* Error: couldn't find the entry */
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "failed to find entry in is_subject_of_agreement_local\n");
goto error;
}
- is_in_subtree = slapi_sdn_scope_test(slapi_entry_get_sdn_const(local_entry), agreement_subtree, LDAP_SCOPE_SUBTREE);
- if (is_in_subtree)
- {
- /* Next test for the correct kind of entry */
- if (local_entry) {
- if (slapi_filter_test_simple( (Slapi_Entry*)local_entry,
- (Slapi_Filter*)windows_private_get_directory_filter(ra)) == 0)
- {
- retval = 1;
+
+ /* First test for the sync'ed subtree */
+ local_sdn = slapi_entry_get_sdn_const(local_entry);
+ subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ is_in_subtree = slapi_sdn_scope_test(local_sdn,
+ sp->DSsubtree, LDAP_SCOPE_SUBTREE);
+ if (is_in_subtree) {
+ break;
}
- } else
- {
- /* Error: couldn't find the entry */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "failed to find entry in is_subject_of_agreement_local: %d\n", retval);
- retval = 0;
+ }
+ } else {
+ const Slapi_DN *agreement_subtree = NULL;
+ agreement_subtree = windows_private_get_directory_subtree(ra);
+ if (agreement_subtree) {
+ is_in_subtree = slapi_sdn_scope_test(local_sdn,
+ agreement_subtree, LDAP_SCOPE_SUBTREE);
+ }
+ }
+ if (is_in_subtree) {
+ /* Next test for the correct kind of entry */
+ if (slapi_filter_test_simple((Slapi_Entry*)local_entry,
+ windows_private_get_directory_filter(ra)) == 0) {
+ retval = 1;
}
}
error:
@@ -4069,19 +4284,26 @@ static int
is_dn_subject_of_agreement_local(const Slapi_DN *sdn, const Repl_Agmt *ra)
{
int retval = 0;
- const Slapi_DN *agreement_subtree = NULL;
+ const subtreePair* subtree_pairs = NULL;
/* Get the subtree from the agreement */
- agreement_subtree = windows_private_get_directory_subtree(ra);
- if (NULL == agreement_subtree)
- {
- goto error;
+ subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ retval = slapi_sdn_scope_test(sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE);
+ if (retval) {
+ break;
+ }
+ }
+ } else {
+ const Slapi_DN *agreement_subtree = NULL;
+ agreement_subtree = windows_private_get_directory_subtree(ra);
+ if (agreement_subtree) {
+ /* Check if the DN is within the subtree */
+ retval = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
+ }
}
-
- /* Check if the DN is within the subtree */
- retval = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
-
-error:
return retval;
}
@@ -4097,20 +4319,41 @@ is_subject_of_agreement_remote(Slapi_Entry *e, const Repl_Agmt *ra)
int retval = 0;
int is_in_subtree = 0;
const Slapi_DN *agreement_subtree = NULL;
- const Slapi_DN *sdn;
-
- /* First test for the sync'ed subtree */
- agreement_subtree = windows_private_get_windows_subtree(ra);
- if (NULL == agreement_subtree)
- {
+ const Slapi_DN *sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+
+ if (!e) {
goto error;
}
sdn = slapi_entry_get_sdn_const(e);
- is_in_subtree = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
+ /* First test for the sync'ed subtree */
+ /* check the subtree pairs; if not set, check windows_subtree */
+ subtree_pairs = windows_private_get_subtreepairs(ra);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->ADsubtree; sp++) {
+ is_in_subtree = slapi_sdn_scope_test(sdn, sp->ADsubtree, LDAP_SCOPE_SUBTREE);
+ if (is_in_subtree) {
+ agreement_subtree = sp->ADsubtree;
+ break;
+ }
+ }
+ } else {
+ agreement_subtree = windows_private_get_windows_subtree(ra);
+ if (agreement_subtree) {
+ is_in_subtree = slapi_sdn_scope_test(sdn, agreement_subtree, LDAP_SCOPE_SUBTREE);
+ }
+ }
if (is_in_subtree)
{
Slapi_DN psdn = {0};
Slapi_Entry *pentry = NULL;
+
+ if (windows_private_get_windows_filter(ra) &&
+ slapi_filter_test_simple(e, windows_private_get_windows_filter(ra))) {
+ /* type_winSyncWindowsFilter is set and the remote entry does not match the filter */
+ goto error;
+ }
/*
* Check whether the parent of the entry exists or not.
* If it does not, treat the entry e is out of scope.
@@ -4357,9 +4600,16 @@ windows_generate_dn_value_mods(char *local_type, const Slapi_Attr *attr, Slapi_M
return ret;
}
-/* Generate the mods for an update in either direction. Be careful... the "remote" entry is the DS entry in the to_windows case, but the AD entry in the other case. */
+/*
+ * Generate the mods for an update in either direction.
+ */
static int
-windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry, int to_windows, Slapi_Mods *smods, int *do_modify)
+windows_generate_update_mods(Private_Repl_Protocol *prp,
+ Slapi_Entry *remote_entry,
+ Slapi_Entry *local_entry,
+ int to_windows,
+ Slapi_Mods *smods,
+ int *do_modify)
{
int retval = 0;
Slapi_Attr *attr = NULL;
@@ -4369,6 +4619,10 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
int rc = 0;
int is_nt4 = windows_private_get_isnt4(prp->agmt);
const Slapi_DN *local_subtree = NULL;
+ const Slapi_DN *local_sdn = NULL;
+ const subtreePair* subtree_pairs = NULL;
+ Slapi_Entry *target_entry = NULL;
+
/* Iterate over the attributes on the remote entry, updating the local entry where appropriate */
LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_generate_update_mods\n", 0, 0, 0 );
@@ -4385,14 +4639,16 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
if (to_windows)
{
- windows_is_local_entry_user_or_group(remote_entry,&is_user,&is_group);
+ windows_is_local_entry_user_or_group(local_entry,&is_user,&is_group);
+ target_entry = local_entry;
} else
{
windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group);
+ target_entry = remote_entry;
}
- for (rc = slapi_entry_first_attr(remote_entry, &attr); rc == 0;
- rc = slapi_entry_next_attr(remote_entry, attr, &attr))
+ for (rc = slapi_entry_first_attr(target_entry, &attr); rc == 0;
+ rc = slapi_entry_next_attr(target_entry, attr, &attr))
{
int is_present_local = 0;
char *type = NULL;
@@ -4432,7 +4688,7 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
}
if (to_windows && (0 == slapi_attr_type_cmp(local_type, "streetAddress", SLAPI_TYPE_CMP_SUBTYPE))) {
- slapi_entry_attr_find(local_entry,FAKE_STREET_ATTR_NAME,&local_attr);
+ slapi_entry_attr_find(remote_entry,FAKE_STREET_ATTR_NAME,&local_attr);
} else {
slapi_entry_attr_find(local_entry,local_type,&local_attr);
}
@@ -4474,8 +4730,8 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
if (!values_equal)
{
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "windows_generate_update_mods: %s, %s : values are different\n",
- slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type);
+ "windows_generate_update_mods: %s, %s : values are different\n",
+ slapi_entry_get_dn_const(local_entry), local_type);
if (to_windows && ((0 == slapi_attr_type_cmp(local_type, "streetAddress", SLAPI_TYPE_CMP_SUBTYPE)) ||
(0 == slapi_attr_type_cmp(local_type, "telephoneNumber", SLAPI_TYPE_CMP_SUBTYPE)) ||
@@ -4531,7 +4787,8 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
} else
{
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "windows_generate_update_mods: %s, %s : values are equal\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type);
+ "windows_generate_update_mods: %s, %s : values are equal\n",
+ slapi_entry_get_dn_const(local_entry), local_type);
}
} else {
/* A dn-valued attribute : need to take special steps */
@@ -4702,7 +4959,22 @@ windows_generate_update_mods(Private_Repl_Protocol *prp,Slapi_Entry *remote_entr
/* Check if any attributes were deleted from the remote entry */
entry_first_deleted_attribute(remote_entry, &del_attr);
- local_subtree = windows_private_get_directory_subtree(prp->agmt);
+ local_sdn = slapi_entry_get_sdn_const(local_entry);
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ const subtreePair* sp;
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ if (slapi_sdn_scope_test(local_sdn, sp->DSsubtree, LDAP_SCOPE_SUBTREE)) {
+ local_subtree = sp->DSsubtree;
+ break;
+ }
+ }
+ } else {
+ local_subtree = windows_private_get_directory_subtree(prp->agmt);
+ }
+ if (NULL == local_subtree) {
+ goto bail;
+ }
while (del_attr != NULL) {
Slapi_Attr *local_attr = NULL;
char *type = NULL;
@@ -4832,14 +5104,14 @@ bail:
static int
windows_update_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry, int is_user)
{
- Slapi_Mods smods = {0};
+ Slapi_Mods smods = {0};
int retval = 0;
int do_modify = 0;
int ldap_op = 0;
int ldap_result_code = 0;
- slapi_mods_init (&smods, 0);
- retval = windows_generate_update_mods(prp,local_entry,remote_entry,1,&smods,&do_modify);
+ slapi_mods_init (&smods, 0);
+ retval = windows_generate_update_mods(prp, remote_entry, local_entry, 1, &smods, &do_modify);
/* Now perform the modify if we need to */
if (0 == retval && do_modify)
{
@@ -4943,7 +5215,7 @@ windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "renaming entry \"%s\" - "
"(newrdn: \"%s\", newsuperior: \"%s\"\n", newdn,
newrdn ? newrdn:"NULL", newsuperior ? newsuperior:"NULL");
- slapi_sdn_init_dn_byref(&newsuperior_sdn, newsuperior);
+ slapi_sdn_init_ndn_byref(&newsuperior_sdn, newsuperior);
slapi_rename_internal_set_pb_ext (pb,
slapi_entry_get_sdn(local_entry),
newrdn, &newsuperior_sdn, 1 /* delete old RDNS */,
@@ -5076,7 +5348,7 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r
(void)slapi_entry2mods (mapped_entry , NULL /* &entrydn : We don't need it */, &entryattrs);
if (NULL == entryattrs)
{
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_replay_update: Cannot convert entry to LDAPMods.\n",agmt_get_long_name(prp->agmt));
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_process_total_add: Cannot convert entry to LDAPMods.\n",agmt_get_long_name(prp->agmt));
retval = CONN_LOCAL_ERROR;
}
else
@@ -5112,7 +5384,7 @@ windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* r
/* It's possible that the entry already exists in AD, in which case we fall back to modify it */
if (retval)
{
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_replay_update: Cannot replay add operation.\n",agmt_get_long_name(prp->agmt));
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_process_total_add: Cannot replay add operation.\n",agmt_get_long_name(prp->agmt));
}
ldap_mods_free(entryattrs, 1);
entryattrs = NULL;
@@ -5183,7 +5455,7 @@ int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e)
if (retval || NULL == remote_dn)
{
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "%s: windows_replay_update: failed map dn for total update dn=\"%s\"\n",
+ "%s: windows_process_total_entry: failed map dn for total update dn=\"%s\"\n",
agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(local_dn));
goto error;
}
@@ -5198,19 +5470,27 @@ error:
}
static int
-windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *uniqueid, char ** attrs, Slapi_Entry **ret_entry, int tombstone, void * component_identity, int is_global)
+windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp,
+ const char *uniqueid,
+ char ** attrs,
+ Slapi_Entry **ret_entry,
+ int tombstone,
+ void * component_identity,
+ int is_global)
{
- Slapi_Entry **entries = NULL;
- Slapi_PBlock *int_search_pb = NULL;
- int rc = 0;
+ Slapi_Entry **entries = NULL;
+ Slapi_PBlock *int_search_pb = NULL;
+ int rc = 0;
char *filter_string = NULL;
const Slapi_DN *local_subtree = NULL;
+ const Slapi_DN *local_subtree_sdn = NULL;
- *ret_entry = NULL;
+ *ret_entry = NULL;
if (is_global) { /* Search from the suffix (rename case) */
local_subtree = agmt_get_replarea(prp->agmt);
+ local_subtree_sdn = local_subtree;
} else {
- local_subtree = windows_private_get_directory_subtree(prp->agmt);
+ local_subtree_sdn = windows_private_get_directory_treetop(prp->agmt);
}
/* Searching for tombstones can be expensive, so the caller needs to specify if
@@ -5222,7 +5502,7 @@ windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *u
}
int_search_pb = slapi_pblock_new ();
- slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(local_subtree), LDAP_SCOPE_SUBTREE, filter_string,
+ slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(local_subtree_sdn), LDAP_SCOPE_SUBTREE, filter_string,
attrs ,
0 /* attrsonly */, NULL /* controls */,
NULL /* uniqueid */,
diff --git a/ldap/servers/plugins/replication/windows_tot_protocol.c b/ldap/servers/plugins/replication/windows_tot_protocol.c
index 0791941..c81974b 100644
--- a/ldap/servers/plugins/replication/windows_tot_protocol.c
+++ b/ldap/servers/plugins/replication/windows_tot_protocol.c
@@ -85,6 +85,57 @@ static void get_result (int rc, void *cb_data);
static int send_entry (Slapi_Entry *e, void *callback_data);
static void windows_tot_delete(Private_Repl_Protocol **prp);
+static void
+_windows_tot_send_entry(const Repl_Agmt *ra, callback_data *cbp, const Slapi_DN *local_sdn)
+{
+ Slapi_PBlock *pb = NULL;
+ char* dn = NULL;
+ int scope = LDAP_SCOPE_SUBTREE;
+ char *filter = NULL;
+ const char *userfilter = NULL;
+ char **attrs = NULL;
+ LDAPControl **server_controls = NULL;
+
+ if ((NULL == ra) || (NULL == cbp) || (NULL == local_sdn)) {
+ return;
+ }
+ dn = slapi_ch_strdup(slapi_sdn_get_dn(local_sdn));
+ userfilter = windows_private_get_directory_userfilter(ra);
+ if (userfilter) {
+ if ('(' == *userfilter) {
+ filter = slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))%s)",
+ userfilter);
+ } else {
+ filter = slapi_ch_smprintf("(&(|(objectclass=ntuser)(objectclass=ntgroup))(%s))",
+ userfilter);
+ }
+ } else {
+ filter = slapi_ch_strdup("(|(objectclass=ntuser)(objectclass=ntgroup))");
+ }
+
+ winsync_plugin_call_pre_ds_search_all_cb(ra, NULL, &dn, &scope, &filter,
+ &attrs, &server_controls);
+
+ pb = slapi_pblock_new ();
+ /* Perform a subtree search for any ntuser or ntgroup entries underneath the
+ * suffix defined in the sync agreement. */
+ slapi_search_internal_set_pb(pb, dn, scope, filter, attrs, 0, server_controls, NULL,
+ repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
+
+ slapi_search_internal_callback_pb(pb, cbp /* callback data */,
+ get_result /* result callback */,
+ send_entry /* entry callback */,
+ NULL /* referral callback */);
+
+ slapi_ch_free_string(&dn);
+ slapi_ch_free_string(&filter);
+ slapi_ch_array_free(attrs);
+ attrs = NULL;
+ ldap_controls_free(server_controls);
+ server_controls = NULL;
+ slapi_pblock_destroy (pb);
+}
+
/*
* Completely refresh a replica. The basic protocol interaction goes
* like this:
@@ -98,16 +149,10 @@ windows_tot_run(Private_Repl_Protocol *prp)
{
int rc;
callback_data cb_data;
- Slapi_PBlock *pb = NULL;
- char* dn = NULL;
RUV *ruv = NULL;
RUV *starting_ruv = NULL;
Replica *replica = NULL;
Object *local_ruv_obj = NULL;
- int scope = LDAP_SCOPE_SUBTREE;
- char *filter = slapi_ch_strdup("(|(objectclass=ntuser)(objectclass=ntgroup))");
- char **attrs = NULL;
- LDAPControl **server_controls = NULL;
int one_way;
LDAPDebug0Args( LDAP_DEBUG_TRACE, "=> windows_tot_run\n" );
@@ -160,9 +205,9 @@ windows_tot_run(Private_Repl_Protocol *prp)
/* call begin total update callback */
winsync_plugin_call_begin_update_cb(prp->agmt,
- windows_private_get_directory_subtree(prp->agmt),
- windows_private_get_windows_subtree(prp->agmt),
- 1 /* is_total == TRUE */);
+ windows_private_get_directory_treetop(prp->agmt),
+ windows_private_get_windows_treetop(prp->agmt),
+ 1 /* is_total == TRUE */);
if ((one_way == ONE_WAY_SYNC_DISABLED) || (one_way == ONE_WAY_SYNC_FROM_AD)) {
/* get everything */
@@ -178,10 +223,10 @@ windows_tot_run(Private_Repl_Protocol *prp)
* the incremental sync protocol ( send_updates() ). We will
* use this value for setting the consumer RUV if the total
* update succeeds. */
- replica = object_get_data(prp->replica_object);
- local_ruv_obj = replica_get_ruv (replica);
- starting_ruv = ruv_dup((RUV*) object_get_data ( local_ruv_obj ));
- object_release (local_ruv_obj);
+ replica = object_get_data(prp->replica_object);
+ local_ruv_obj = replica_get_ruv (replica);
+ starting_ruv = ruv_dup((RUV*)object_get_data ( local_ruv_obj ));
+ object_release (local_ruv_obj);
/* Set up the callback data. */
cb_data.prp = prp;
@@ -190,44 +235,30 @@ windows_tot_run(Private_Repl_Protocol *prp)
cb_data.sleep_on_busy = 0UL;
cb_data.last_busy = current_time ();
- /* Don't send anything if one-way is set. */
+ /* Don't send anything if one-way (ONE_WAY_SYNC_FROM_AD) is set. */
if ((one_way == ONE_WAY_SYNC_DISABLED) || (one_way == ONE_WAY_SYNC_TO_AD)) {
/* send everything */
- dn = slapi_ch_strdup(slapi_sdn_get_dn( windows_private_get_directory_subtree(prp->agmt)));
-
- winsync_plugin_call_pre_ds_search_all_cb(prp->agmt, NULL, &dn, &scope, &filter,
- &attrs, &server_controls);
-
- pb = slapi_pblock_new ();
- /* Perform a subtree search for any ntuser or ntgroup entries underneath the
- * suffix defined in the sync agreement. */
- slapi_search_internal_set_pb (pb, dn, scope, filter, attrs, 0, server_controls, NULL,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
-
- slapi_search_internal_callback_pb (pb, &cb_data /* callback data */,
- get_result /* result callback */,
- send_entry /* entry callback */,
- NULL /* referral callback*/);
+ const subtreePair* subtree_pairs = NULL;
+ const subtreePair* sp = NULL;
+
+ subtree_pairs = windows_private_get_subtreepairs(prp->agmt);
+ if (subtree_pairs) {
+ for (sp = subtree_pairs; sp && sp->DSsubtree; sp++) {
+ _windows_tot_send_entry(prp->agmt, &cb_data, sp->DSsubtree);
+ }
+ } else {
+ _windows_tot_send_entry(prp->agmt, &cb_data, windows_private_get_directory_subtree(prp->agmt));
+ }
}
-
- slapi_ch_free_string(&dn);
- slapi_ch_free_string(&filter);
- slapi_ch_array_free(attrs);
- attrs = NULL;
- ldap_controls_free(server_controls);
- server_controls = NULL;
-
- slapi_pblock_destroy (pb);
rc = cb_data.rc;
windows_release_replica(prp);
- if (rc != LDAP_SUCCESS)
- {
- slapi_log_error (SLAPI_LOG_REPL, windows_repl_plugin_name, "%s: windows_tot_run: "
- "failed to obtain data to send to the consumer; LDAP error - %d\n",
- agmt_get_long_name(prp->agmt), rc);
+ if (rc != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "%s: windows_tot_run: "
+ "failed to obtain data to send to the consumer; LDAP error - %d\n",
+ agmt_get_long_name(prp->agmt), rc);
agmt_set_last_init_status(prp->agmt, rc, 0, "Total update aborted");
- } else {
+ } else {
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "Finished total update of replica "
"\"%s\". Sent %lu entries.\n", agmt_get_long_name(prp->agmt), cb_data.num_entries);
agmt_set_last_init_status(prp->agmt, 0, 0, "Total update succeeded");
@@ -256,9 +287,9 @@ windows_tot_run(Private_Repl_Protocol *prp)
/* call end total update callback */
winsync_plugin_call_end_update_cb(prp->agmt,
- windows_private_get_directory_subtree(prp->agmt),
- windows_private_get_windows_subtree(prp->agmt),
- 1 /* is_total == TRUE */);
+ windows_private_get_directory_treetop(prp->agmt),
+ windows_private_get_windows_treetop(prp->agmt),
+ 1 /* is_total == TRUE */);
done:
if (starting_ruv)
diff --git a/ldap/servers/plugins/replication/windowsrepl.h b/ldap/servers/plugins/replication/windowsrepl.h
index 9279179..f9c747c 100644
--- a/ldap/servers/plugins/replication/windowsrepl.h
+++ b/ldap/servers/plugins/replication/windowsrepl.h
@@ -43,6 +43,11 @@
/* windows_private.c */
typedef struct windowsprivate Dirsync_Private;
+typedef struct subtreepair {
+ Slapi_DN *ADsubtree;
+ Slapi_DN *DSsubtree;
+} subtreePair;
+
Dirsync_Private* windows_private_new();
void windows_private_set_windows_subtree (const Repl_Agmt *ra,Slapi_DN* sdn );
const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra);
@@ -68,6 +73,7 @@ void windows_private_set_isnt4(const Repl_Agmt *ra, int isit);
int windows_private_get_iswin2k3(const Repl_Agmt *ra);
void windows_private_set_iswin2k3(const Repl_Agmt *ra, int isit);
Slapi_Filter* windows_private_get_directory_filter(const Repl_Agmt *ra);
+Slapi_Filter* windows_private_get_windows_filter(const Repl_Agmt *ra);
Slapi_Filter* windows_private_get_deleted_filter(const Repl_Agmt *ra);
const char* windows_private_get_purl(const Repl_Agmt *ra);
/*
@@ -94,6 +100,18 @@ void windows_private_set_curr_entry(const Repl_Agmt *ra, Slapi_Entry *e);
char **windows_private_get_range_attrs(const Repl_Agmt *ra);
void windows_private_set_range_attrs(const Repl_Agmt *ra, char **attrs);
+void windows_private_set_directory_userfilter(const Repl_Agmt *ra, char *filter);
+void windows_private_set_windows_userfilter(const Repl_Agmt *ra, char *filter);
+const char* windows_private_get_directory_userfilter(const Repl_Agmt *ra);
+const char* windows_private_get_windows_userfilter(const Repl_Agmt *ra);
+
+const subtreePair* windows_private_get_subtreepairs(const Repl_Agmt *ra);
+void windows_private_set_subtreepairs(const Repl_Agmt *ra, char **parray);
+const Slapi_DN* windows_private_get_windows_treetop(const Repl_Agmt *ra);
+void windows_private_set_windows_treetop(const Repl_Agmt *ra, char *treetop);
+const Slapi_DN* windows_private_get_directory_treetop(const Repl_Agmt *ra);
+void windows_private_set_directory_treetop(const Repl_Agmt *ra, char *treetop);
+
/* in windows_connection.c */
ConnResult windows_conn_connect(Repl_Connection *conn);
void windows_conn_disconnect(Repl_Connection *conn);
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 9ed8091..8328ed5 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -2011,6 +2011,17 @@ slapi_sdn_new_ndn_byref(const char *ndn)
return sdn;
}
+/* use when dn is already fully normalized */
+Slapi_DN *
+slapi_sdn_new_ndn_passin(const char *ndn)
+{
+ Slapi_DN *sdn = slapi_sdn_new();
+ slapi_sdn_set_ndn_passin(sdn, ndn);
+ SDN_DUMP( sdn, "slapi_sdn_new_ndn_passin");
+ return sdn;
+}
+
+
/* use when dn is already normalized */
Slapi_DN *
slapi_sdn_new_normdn_byref(const char *normdn)
@@ -2154,6 +2165,20 @@ slapi_sdn_set_ndn_byref(Slapi_DN *sdn, const char *ndn)
return sdn;
}
+Slapi_DN *
+slapi_sdn_set_ndn_passin(Slapi_DN *sdn, const char *ndn)
+{
+ slapi_sdn_done(sdn);
+ sdn->flag = slapi_setbit_uchar(sdn->flag, FLAG_NDN);
+ sdn->ndn = ndn;
+ if (ndn == NULL) {
+ sdn->ndn_len = 0;
+ } else {
+ sdn->ndn_len = strlen(ndn);
+ }
+ return sdn;
+}
+
/*
* Set the RDN of the DN.
*/
@@ -3017,3 +3042,71 @@ ndn_cache_get_stats(PRUint64 *hits, PRUint64 *tries, size_t *size, size_t *max_s
slapi_rwlock_unlock(ndn_cache_lock);
}
+/* Common ancestor sdn is allocated.
+ * caller is responsible to free it */
+Slapi_DN *
+slapi_sdn_common_ancestor(Slapi_DN *dn1, Slapi_DN *dn2)
+{
+ const char *dn1str = NULL;
+ const char *dn2str = NULL;
+ char **dns1 = NULL;
+ char **dns2 = NULL;
+ char **dn1p, **dn2p;
+ char **dn1end;
+ int dn1len = 0;
+ int dn2len = 0;
+ char *common = NULL;
+ char *cp = 0;
+ if ((NULL == dn1) || (NULL == dn2)) {
+ return NULL;
+ }
+ dn1str = slapi_sdn_get_ndn(dn1);
+ dn2str = slapi_sdn_get_ndn(dn2);
+ if (0 == strcmp(dn1str, dn2str)) {
+ /* identical */
+ return slapi_sdn_dup(dn1);
+ }
+ dn1len = strlen(dn1str);
+ dn2len = strlen(dn2str);
+ if (dn1len > dn2len) {
+ if (slapi_sdn_isparent(dn2, dn1)) {
+ /* dn2 is dn1's parent */
+ return slapi_sdn_dup(dn2);
+ }
+ } else if (dn1len < dn2len) {
+ if (slapi_sdn_isparent(dn1, dn2)) {
+ /* dn1 is dn2's parent */
+ return slapi_sdn_dup(dn1);
+ }
+ }
+ dns1 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(dn1), 0);
+ dns2 = slapi_ldap_explode_dn(slapi_sdn_get_ndn(dn2), 0);
+ for (dn1p = dns1; dn1p && *dn1p; dn1p++) ;
+ for (dn2p = dns2; dn2p && *dn2p; dn2p++) ;
+ dn1end = dn1p;
+ while (--dn1p && --dn2p && (dn1p >= dns1) && (dn2p >= dns2)) {
+ if (strcmp(*dn1p, *dn2p)) {
+ break;
+ }
+ }
+ if (dn1end == ++dn1p) {
+ /* No common ancestor */
+ charray_free(dns1);
+ charray_free(dns2);
+ return NULL;
+ }
+ dn1len += 1;
+ cp = common = slapi_ch_malloc(dn1len);
+ *common = '\0';
+ do {
+ PR_snprintf(cp, dn1len, "%s,", *dn1p);
+ cp += strlen(*dn1p) + 1/*,*/;
+ } while (++dn1p < dn1end);
+ dn1len = strlen(common);
+ if (',' == *(common + dn1len - 1)) {
+ *(common + dn1len - 1) = '\0';
+ }
+ charray_free(dns1);
+ charray_free(dns2);
+ return slapi_sdn_new_ndn_passin(common);
+}
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 233dbe9..97fb81f 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -2262,6 +2262,7 @@ Slapi_DN *slapi_sdn_new_dn_byval(const char *dn);
* \warning The \c ndn value is copied by the function itself. The caller
* is still responsible for the memory used by \c ndn.
* \see slapi_sdn_new_ndn_byref()
+ * \see slapi_sdn_new_ndn_passin()
* \see slapi_sdn_free()
* \see slapi_sdn_copy()
* \see slapi_sdn_done()
@@ -2301,6 +2302,7 @@ Slapi_DN *slapi_sdn_new_dn_byref(const char *dn);
* memory should not be freed until the returned \c Slapi_DN has been
* disposed of or reinitialized.
* \see slapi_sdn_new_ndn_byval()
+ * \see slapi_sdn_new_ndn_passin()
* \see slapi_sdn_free()
* \see slapi_sdn_copy()
* \see slapi_sdn_done()
@@ -2308,6 +2310,23 @@ Slapi_DN *slapi_sdn_new_dn_byref(const char *dn);
Slapi_DN *slapi_sdn_new_ndn_byref(const char *ndn);
/**
+ * Creates a new \c Slapi_DN structure and intializes it's normalized and case ignored DN to a requested value.
+ *
+ * The normalized and case ignored DN of the new structure will point to the same string pointed to by \c ndn.
+ * Ownership of the memory pointed to by \c ndn is tranferred to the Slapi_DN.
+ *
+ * \param ndn The normalized and case ignored DN value to be set in the new \c Slapi_DN structure.
+ * \return A pointer to the newly allocated \c Slapi_DN structure with
+ * the normalized and case ignored DN value set to the content of \c ndn.
+ * \see slapi_sdn_new_ndn_byval()
+ * \see slapi_sdn_new_ndn_byref()
+ * \see slapi_sdn_free()
+ * \see slapi_sdn_copy()
+ * \see slapi_sdn_done()
+ */
+Slapi_DN *slapi_sdn_new_ndn_passin(const char *ndn);
+
+/**
* Creates a new \c Slapi_DN structure and intializes it's DN to a requested value.
*
* The DN of the new structure will point to the same string pointed to by \c dn.
@@ -2494,6 +2513,7 @@ Slapi_DN *slapi_sdn_set_normdn_byval(Slapi_DN *sdn, const char *dn);
* \warning The \c ndn value is copied by the function itself. The caller
* is still responsible for the memory used by \c ndn.
* \see slapi_sdn_set_ndn_byref()
+ * \see slapi_sdn_set_ndn_passin()
*/
Slapi_DN *slapi_sdn_set_ndn_byval(Slapi_DN *sdn, const char *ndn);
@@ -2510,10 +2530,26 @@ Slapi_DN *slapi_sdn_set_ndn_byval(Slapi_DN *sdn, const char *ndn);
* memory should not be freed until the returned \c Slapi_DN has been
* disposed of or reinitialized.
* \see slapi_sdn_set_ndn_byval()
+ * \see slapi_sdn_set_ndn_passin()
*/
Slapi_DN *slapi_sdn_set_ndn_byref(Slapi_DN *sdn, const char *ndn);
/**
+ * Sets a normalized DN value in a \c Slapi_DN structure.
+ *
+ * The normalized DN of the structure will point to the same string pointed to
+ * by \c ndn.
+ * Ownership of the memory pointed to by \c ndn is tranferred to the Slapi_DN.
+ *
+ * \param sdn The target \c Slapi_DN structure.
+ * \param ndn The normalized DN value to be set in \c sdn.
+ * \return A pointer to the \c Slapi_DN structure containing the new normalized DN value.
+ * \see slapi_sdn_set_ndn_byval()
+ * \see slapi_sdn_set_ndn_byref()
+ */
+Slapi_DN *slapi_sdn_set_ndn_passin(Slapi_DN *sdn, const char *ndn);
+
+/**
* Clears the contents of a Slapi_DN structure.
*
* Both the DN and the normalized DN are freed if the \c Slapi_DN structure
@@ -3631,6 +3667,15 @@ int slapi_rdn2typeval( char *rdn, char **type, struct berval *bv );
*/
char *slapi_dn_plus_rdn(const char *dn, const char *rdn);
+/**
+ * Create an Slapi_DN that is a common ancestor of given 2 Slapi_DN's
+ *
+ * \param dn1 The first DN
+ * \param dn2 the second DN
+ * \return A pointer to the new Slapi_DN that is a common ancestor of dn1 and dn2
+ * \warning The caller must free the returnd Slapi_DN
+ */
+Slapi_DN *slapi_sdn_common_ancestor(Slapi_DN *dn1, Slapi_DN *dn2);
/*
* thread safe random functions
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index fb92867..1991040 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -604,7 +604,7 @@ int slapi_mods2entry (Slapi_Entry **e, const char *idn, LDAPMod **iattrs)
if (rc != LDAP_SUCCESS)
{
LDAPDebug2Args(LDAP_DEBUG_ANY,
- "slapi_add_internal: add_values for type %s failed (rc: %d)\n",
+ "slapi_mods2entry: add_values for type %s failed (rc: %d)\n",
normtype, rc );
slapi_entry_free (*e);
*e = NULL;
10 years, 7 months
ldap/servers
by Mark Reynolds
ldap/servers/slapd/libglobs.c | 32 +++++
ldap/servers/slapd/proto-slap.h | 2
ldap/servers/slapd/result.c | 226 ++++++++++++++++++++++------------------
ldap/servers/slapd/slap.h | 2
4 files changed, 163 insertions(+), 99 deletions(-)
New commits:
commit 55ff5cf4cbbbd9bce392f5253031a8e5b4b14dc6
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Tue Sep 17 18:32:13 2013 -0400
Ticket 47401 - report unindexed internal searches
Bug Description: Internal search operations that are unindexed are not logged. By
default plugins do not log their operations, even if access log level
is set to record internal operations - unless the undocumented config
attribute "nsslapd-logAccess: on" is set in each plugin config entry.
Fix Description: Record the unindexed search in the error log, if access logging is not
recording internal operations. Also, a new config attribute was added
to cn=config:
nsslapd-plugin-logging: on|off
When set to on, it turns on logging for all plugin internal operations.
https://fedorahosted.org/389/ticket/47401
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 16799f5..047bd1c 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -258,6 +258,7 @@ slapi_onoff_t init_sasl_mapping_fallback;
slapi_onoff_t init_return_orig_type;
slapi_onoff_t init_enable_turbo_mode;
slapi_onoff_t init_connection_nocanon;
+slapi_onoff_t init_plugin_logging;
slapi_int_t init_connection_buffer;
slapi_int_t init_listen_backlog_size;
#ifdef MEMPOOL_EXPERIMENTAL
@@ -1059,6 +1060,10 @@ static struct config_get_and_set {
NULL, 0,
(void**)&global_slapdFrontendConfig.connection_nocanon,
CONFIG_ON_OFF, (ConfigGetFunc)config_get_connection_nocanon, &init_connection_nocanon},
+ {CONFIG_PLUGIN_LOGGING, config_set_plugin_logging,
+ NULL, 0,
+ (void**)&global_slapdFrontendConfig.plugin_logging,
+ CONFIG_ON_OFF, (ConfigGetFunc)config_get_plugin_logging, &init_plugin_logging},
{CONFIG_LISTEN_BACKLOG_SIZE, config_set_listen_backlog_size,
NULL, 0,
(void**)&global_slapdFrontendConfig.listen_backlog_size, CONFIG_INT,
@@ -1503,7 +1508,7 @@ FrontendConfig_init () {
init_enable_turbo_mode = cfg->enable_turbo_mode = LDAP_ON;
init_connection_buffer = cfg->connection_buffer = CONNECTION_BUFFER_ON;
init_connection_nocanon = cfg->connection_nocanon = LDAP_ON;
-
+ init_plugin_logging = cfg->plugin_logging = LDAP_OFF;
init_listen_backlog_size = cfg->listen_backlog_size = DAEMON_LISTEN_SIZE;
#ifdef MEMPOOL_EXPERIMENTAL
init_mempool_switch = cfg->mempool_switch = LDAP_ON;
@@ -6954,6 +6959,18 @@ config_get_connection_nocanon(void)
}
int
+config_get_plugin_logging(void)
+{
+ int retVal;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+ CFG_ONOFF_LOCK_READ(slapdFrontendConfig);
+ retVal = (int)slapdFrontendConfig->plugin_logging;
+ CFG_ONOFF_UNLOCK_READ(slapdFrontendConfig);
+
+ return retVal;
+}
+
+int
slapi_config_get_unhashed_pw_switch()
{
return config_get_unhashed_pw_switch();
@@ -6998,6 +7015,19 @@ config_set_connection_nocanon( const char *attrname, char *value,
}
int
+config_set_plugin_logging( const char *attrname, char *value,
+ char *errorbuf, int apply )
+{
+ int retVal = LDAP_SUCCESS;
+ slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
+
+ retVal = config_set_onoff(attrname, value,
+ &(slapdFrontendConfig->plugin_logging),
+ errorbuf, apply);
+ return retVal;
+}
+
+int
config_get_connection_buffer(void)
{
int retVal;
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 03cf8e5..f2f5319 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -569,7 +569,9 @@ int config_set_enable_turbo_mode(const char *attrname, char *value, char *errorb
int config_get_connection_buffer();
int config_set_connection_buffer(const char *attrname, char *value, char *errorbuf, int apply);
int config_get_connection_nocanon();
+int config_get_plugin_logging();
int config_set_connection_nocanon(const char *attrname, char *value, char *errorbuf, int apply);
+int config_set_plugin_logging(const char *attrname, char *value, char *errorbuf, int apply);
int config_get_listen_backlog_size(void);
PLHashNumber hashNocaseString(const void *key);
diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c
index 9b6fb8b..f520e6b 100644
--- a/ldap/servers/slapd/result.c
+++ b/ldap/servers/slapd/result.c
@@ -568,8 +568,9 @@ send_ldap_result_ext(
log_and_return:
operation->o_status = SLAPI_OP_STATUS_RESULT_SENT; /* in case this has not yet been set */
- if ( logit && operation_is_flag_set( operation,
- OP_FLAG_ACTION_LOG_ACCESS )) {
+ if ( logit && (operation_is_flag_set( operation, OP_FLAG_ACTION_LOG_ACCESS ) ||
+ (internal_op && config_get_plugin_logging() )))
+ {
log_result( pb, operation, err, tag, nentries );
}
@@ -1857,33 +1858,30 @@ notes2str( unsigned int notes, char *buf, size_t buflen )
#define ETIME_BUFSIZ 16 /* room for 99999999.999999 */
static void
-log_result( Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag,
- int nentries )
+log_result( Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries )
{
char *notes_str, notes_buf[ 256 ];
int internal_op;
CSN *operationcsn = NULL;
char csn_str[CSN_STRSIZE + 5];
- char etime[ETIME_BUFSIZ];
+ char etime[ETIME_BUFSIZ];
internal_op = operation_is_flag_set( op, OP_FLAG_INTERNAL );
- if ( (config_get_accesslog_level() & LDAP_DEBUG_TIMING) &&
- (op->o_interval != (PRIntervalTime) 0) ) {
- PRIntervalTime delta = PR_IntervalNow() - op->o_interval;
- PR_snprintf(etime, ETIME_BUFSIZ, "%f",
- (PRFloat64)delta/PR_TicksPerSecond());
- } else {
- PR_snprintf(etime, ETIME_BUFSIZ, "%ld", current_time() - op->o_time);
- }
+ if ( (config_get_accesslog_level() & LDAP_DEBUG_TIMING) &&
+ (op->o_interval != (PRIntervalTime) 0) ) {
+ PRIntervalTime delta = PR_IntervalNow() - op->o_interval;
+ PR_snprintf(etime, ETIME_BUFSIZ, "%f", (PRFloat64)delta/PR_TicksPerSecond());
+ } else {
+ PR_snprintf(etime, ETIME_BUFSIZ, "%ld", current_time() - op->o_time);
+ }
if ( 0 == pb->pb_operation_notes ) {
notes_str = "";
} else {
notes_str = notes_buf;
*notes_buf = ' ';
- notes2str( pb->pb_operation_notes, notes_buf + 1,
- sizeof( notes_buf ) - 1 );
+ notes2str( pb->pb_operation_notes, notes_buf + 1, sizeof( notes_buf ) - 1 );
}
csn_str[0] = '\0';
@@ -1897,92 +1895,124 @@ log_result( Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag,
}
}
- if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SASL_BIND_IN_PROGRESS) {
- /*
- * Not actually an error.
- * Make that clear in the log.
- */
- if ( !internal_op )
- {
- slapi_log_access( LDAP_DEBUG_STATS,
- "conn=%" NSPRIu64 " op=%d RESULT err=%d"
- " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
- ", SASL bind in progress\n",
- (long long unsigned int)op->o_connid,
- op->o_opid,
- err, tag, nentries,
- etime,
- notes_str, csn_str );
- }
- else
- {
- slapi_log_access( LDAP_DEBUG_ARGS,
- "conn=%s op=%d RESULT err=%d"
- " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
- ", SASL bind in progress\n",
- LOG_INTERNAL_OP_CON_ID,
- LOG_INTERNAL_OP_OP_ID,
- err, tag, nentries,
- etime,
- notes_str, csn_str );
- }
- } else if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SUCCESS) {
- char *dn = NULL;
-
- /*
- * For methods other than simple, the dn in the bind request
- * may be irrelevant. Log the actual authenticated dn.
- */
- slapi_pblock_get(pb, SLAPI_CONN_DN, &dn);
- if ( !internal_op )
- {
- slapi_log_access( LDAP_DEBUG_STATS,
- "conn=%" NSPRIu64 " op=%d RESULT err=%d"
- " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
- " dn=\"%s\"\n",
- (long long unsigned int)op->o_connid,
- op->o_opid,
- err, tag, nentries,
- etime,
- notes_str, csn_str, dn ? dn : "");
- }
- else
- {
- slapi_log_access( LDAP_DEBUG_ARGS,
- "conn=%s op=%d RESULT err=%d"
- " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
- " dn=\"%s\"\n",
- LOG_INTERNAL_OP_CON_ID,
- LOG_INTERNAL_OP_OP_ID,
- err, tag, nentries,
- etime,
- notes_str, csn_str, dn ? dn : "");
- }
- slapi_ch_free((void**)&dn);
- } else {
- if ( !internal_op )
- {
- slapi_log_access( LDAP_DEBUG_STATS,
- "conn=%" NSPRIu64 " op=%d RESULT err=%d"
- " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n",
- (long long unsigned int)op->o_connid,
- op->o_opid,
- err, tag, nentries,
- etime,
- notes_str, csn_str );
- }
- else
+ if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SASL_BIND_IN_PROGRESS) {
+ /*
+ * Not actually an error.
+ * Make that clear in the log.
+ */
+ if ( !internal_op )
+ {
+ slapi_log_access( LDAP_DEBUG_STATS,
+ "conn=%" NSPRIu64 " op=%d RESULT err=%d"
+ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
+ ", SASL bind in progress\n",
+ (long long unsigned int)op->o_connid,
+ op->o_opid,
+ err, tag, nentries,
+ etime,
+ notes_str, csn_str );
+ }
+ else
+ {
+ slapi_log_access( LDAP_DEBUG_ARGS,
+ "conn=%s op=%d RESULT err=%d"
+ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
+ ", SASL bind in progress\n",
+ LOG_INTERNAL_OP_CON_ID,
+ LOG_INTERNAL_OP_OP_ID,
+ err, tag, nentries,
+ etime,
+ notes_str, csn_str );
+ }
+ } else if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SUCCESS) {
+ char *dn = NULL;
+
+ /*
+ * For methods other than simple, the dn in the bind request
+ * may be irrelevant. Log the actual authenticated dn.
+ */
+ slapi_pblock_get(pb, SLAPI_CONN_DN, &dn);
+ if ( !internal_op )
+ {
+ slapi_log_access( LDAP_DEBUG_STATS,
+ "conn=%" NSPRIu64 " op=%d RESULT err=%d"
+ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
+ " dn=\"%s\"\n",
+ (long long unsigned int)op->o_connid,
+ op->o_opid,
+ err, tag, nentries,
+ etime,
+ notes_str, csn_str, dn ? dn : "");
+ }
+ else
+ {
+ slapi_log_access( LDAP_DEBUG_ARGS,
+ "conn=%s op=%d RESULT err=%d"
+ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
+ " dn=\"%s\"\n",
+ LOG_INTERNAL_OP_CON_ID,
+ LOG_INTERNAL_OP_OP_ID,
+ err, tag, nentries,
+ etime,
+ notes_str, csn_str, dn ? dn : "");
+ }
+ slapi_ch_free((void**)&dn);
+ } else {
+ if ( !internal_op )
+ {
+ slapi_log_access( LDAP_DEBUG_STATS,
+ "conn=%" NSPRIu64 " op=%d RESULT err=%d"
+ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n",
+ (long long unsigned int)op->o_connid,
+ op->o_opid,
+ err, tag, nentries,
+ etime,
+ notes_str, csn_str );
+ }
+ else
+ {
+ int optype;
+ slapi_log_access( LDAP_DEBUG_ARGS,
+ "conn=%s op=%d RESULT err=%d"
+ " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n",
+ LOG_INTERNAL_OP_CON_ID,
+ LOG_INTERNAL_OP_OP_ID,
+ err, tag, nentries,
+ etime,
+ notes_str, csn_str );
+ /*
+ * If this is an unindexed search we should log it in the error log if
+ * we didn't log it in the access log.
+ */
+ slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype );
+ if(optype == SLAPI_OPERATION_SEARCH && /* search, */
+ strcmp(notes_str,"") && /* that's unindexed, */
+ !(config_get_accesslog_level() & LDAP_DEBUG_ARGS)) /* and not logged in access log */
{
- slapi_log_access( LDAP_DEBUG_ARGS,
- "conn=%s op=%d RESULT err=%d"
- " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n",
- LOG_INTERNAL_OP_CON_ID,
- LOG_INTERNAL_OP_OP_ID,
- err, tag, nentries,
- etime,
- notes_str, csn_str );
+ struct slapdplugin *plugin = NULL;
+ struct slapi_componentid *cid = NULL;
+ char *filter_str;
+ char *plugin_dn;
+ char *base_dn;
+
+ slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &filter_str);
+ slapi_pblock_get(pb, SLAPI_TARGET_DN, &base_dn);
+ slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
+ if (cid){
+ plugin=(struct slapdplugin *) cid->sci_plugin;
+ } else {
+ slapi_pblock_get (pb, SLAPI_PLUGIN, &plugin);
+ }
+ plugin_dn = plugin_get_dn(plugin);
+
+ slapi_log_error (SLAPI_LOG_FATAL, "Internal search" , "Unindexed search: source (%s) "
+ "search base=\"%s\" filter=\"%s\" etime=%s nentries=%d %s\n",
+ plugin_dn, base_dn, filter_str, etime, nentries, notes_str);
+
+ slapi_ch_free_string(&plugin_dn);
}
}
+ }
}
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index a98de47..6c88a56 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2111,6 +2111,7 @@ typedef struct _slapdEntryPoints {
#define CONFIG_ENABLE_TURBO_MODE "nsslapd-enable-turbo-mode"
#define CONFIG_CONNECTION_BUFFER "nsslapd-connection-buffer"
#define CONFIG_CONNECTION_NOCANON "nsslapd-connection-nocanon"
+#define CONFIG_PLUGIN_LOGGING "nsslapd-plugin-logging"
#define CONFIG_LISTEN_BACKLOG_SIZE "nsslapd-listen-backlog-size"
/*
@@ -2364,6 +2365,7 @@ typedef struct _slapdFrontendConfig {
slapi_onoff_t enable_turbo_mode;
slapi_int_t connection_buffer; /* values are CONNECTION_BUFFER_* below */
slapi_onoff_t connection_nocanon; /* if "on" sets LDAP_OPT_X_SASL_NOCANON */
+ slapi_onoff_t plugin_logging; /* log all internal plugin operations */
} slapdFrontendConfig_t;
/* possible values for slapdFrontendConfig_t.schemareplace */
10 years, 7 months
2 commits - ldap/servers
by Ludwig Krispenz
ldap/servers/plugins/replication/replutil.c | 12 ++-
ldap/servers/slapd/mapping_tree.c | 96 ++++++++++++++++++++++++----
ldap/servers/slapd/slapi-plugin.h | 5 +
ldap/servers/slapd/slapi-private.h | 3
4 files changed, 100 insertions(+), 16 deletions(-)
New commits:
commit 8c216a99cc752e6be2d73fd91a446f9d1d44a701
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Fri Sep 13 10:03:31 2013 +0200
Use defines for backend error handling
diff --git a/ldap/servers/plugins/replication/replutil.c b/ldap/servers/plugins/replication/replutil.c
index 4dee4c1..a567832 100644
--- a/ldap/servers/plugins/replication/replutil.c
+++ b/ldap/servers/plugins/replication/replutil.c
@@ -947,9 +947,9 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
if (root_mode == CHAIN_ROOT_UPDATE_LOCAL)
return local_backend;
else if (root_mode == CHAIN_ROOT_UPDATE_REJECT)
- return (-2);
+ return (SLAPI_BE_NO_BACKEND);
else if (root_mode == CHAIN_ROOT_UPDATE_REFERRAL)
- return (-3);
+ return (SLAPI_BE_REMOTE_BACKEND);
}
/* if the operation is a replicated operation
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index 53df04a..d0801e7 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -2572,7 +2572,7 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node * target_node,
}
/* check if distribution plugi returned a special mode for
* updates as root */
- else if (index == -2 || index == -3)
+ else if (index == SLAPI_BE_NO_BACKEND || index == SLAPI_BE_REMOTE_BACKEND)
{
/* nothing special to do */
}
@@ -2686,17 +2686,17 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
} else {
*index = mtn_get_be_distributed(pb, target_node,
target_sdn, &flag_stop);
- if (*index == -2)
+ if (*index == SLAPI_BE_NO_BACKEND)
result = LDAP_UNWILLING_TO_PERFORM;
}
}
- if (*index == -3) {
+ if (*index == SLAPI_BE_REMOTE_BACKEND) {
*be = NULL;
*referral = (target_node->mtn_referral_entry ?
slapi_entry_dup(target_node->mtn_referral_entry) :
NULL);
(*index)++;
- }else if ((*index == -2) || (*index >= target_node->mtn_be_count)) {
+ }else if ((*index == SLAPI_BE_NO_BACKEND) || (*index >= target_node->mtn_be_count)) {
/* we have already returned all backends -> return NULL */
*be = NULL;
*referral = NULL;
@@ -2739,7 +2739,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
*be = defbackend_get_backend();
}
if (flag_stop)
- *index = -2;
+ *index = SLAPI_BE_NO_BACKEND;
else
(*index)++;
}
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 6cb6d74..233dbe9 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -6163,8 +6163,13 @@ int slapi_unregister_backend_state_change(void * handle);
/* SLAPI_BE_ALL_BACKENDS is a special value that is returned by
* a distribution plugin function to indicate that all backends
* should be searched (it is only used for search operations).
+ *
+ * SLAPI_BE_NO_BACKEND indicates no more backend is available or allowed
+ * SLAPI_BE_REMOTE_BACKEND indicates that the are not locally available
*/
#define SLAPI_BE_ALL_BACKENDS -1
+#define SLAPI_BE_NO_BACKEND -2
+#define SLAPI_BE_REMOTE_BACKEND -3
commit b2ece76189f87f75ef16ae9c75fc4348904a6714
Author: Ludwig Krispenz <lkrispen(a)redhat.com>
Date: Wed Sep 11 14:42:36 2013 +0200
Ticket 314 - ChaiOnUpdate for root handling
Bug Description: If chaining and distribution are configured
updates as root are always applied locally
This leads to inconsistent data
Fix Description: Add a configuration option to control the
processing of root updates. Valid options are:
- local: apply changes to the local database
- reject: do not handle root updates
- referral: return the referral to the
chaining backend
https://fedorahosted.org/389/ticket/314
Reviewed by: ?
diff --git a/ldap/servers/plugins/replication/replutil.c b/ldap/servers/plugins/replication/replutil.c
index d007f6c..4dee4c1 100644
--- a/ldap/servers/plugins/replication/replutil.c
+++ b/ldap/servers/plugins/replication/replutil.c
@@ -814,7 +814,8 @@ repl_set_mtn_state_and_referrals(
int
repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
char **mtn_be_names, int be_count,
- Slapi_DN * node_dn, int *mtn_be_states)
+ Slapi_DN * node_dn, int *mtn_be_states,
+ int root_mode)
{
char * requestor_dn;
unsigned long op_type;
@@ -943,7 +944,12 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
"is root: using local backend\n", connid, opid);
}
#endif
- return local_backend;
+ if (root_mode == CHAIN_ROOT_UPDATE_LOCAL)
+ return local_backend;
+ else if (root_mode == CHAIN_ROOT_UPDATE_REJECT)
+ return (-2);
+ else if (root_mode == CHAIN_ROOT_UPDATE_REFERRAL)
+ return (-3);
}
/* if the operation is a replicated operation
@@ -981,7 +987,7 @@ repl_chain_on_update(Slapi_PBlock *pb, Slapi_DN * target_dn,
}
}
- /* all other case (update while not directory manager) :
+ /* all other cases :
* or any normal non replicated client operation while local is disabled (import) :
* use the chaining backend
*/
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
index 9336d7c..53df04a 100644
--- a/ldap/servers/slapd/mapping_tree.c
+++ b/ldap/servers/slapd/mapping_tree.c
@@ -47,7 +47,7 @@
/* distribution plugin prototype */
typedef int (* mtn_distrib_fct) (Slapi_PBlock *pb, Slapi_DN * target_dn,
- char **mtn_be_names, int be_count, Slapi_DN * mtn_node_dn, int *mtn_be_states);
+ char **mtn_be_names, int be_count, Slapi_DN * mtn_node_dn, int *mtn_be_states, int rootmode);
struct mt_node
{
@@ -70,6 +70,7 @@ struct mt_node
* cn=config, cn=schema and root node */
char * mtn_dstr_plg_lib; /* distribution plugin library name */
char * mtn_dstr_plg_name; /* distribution plugin function name */
+ int mtn_dstr_plg_rootmode; /* determines how to process root updates in distribution */
mtn_distrib_fct mtn_dstr_plg; /* pointer to the actual ditribution function */
void *mtn_extension; /* plugins can extend a mapping tree node */
};
@@ -302,7 +303,7 @@ mapping_tree_node_new(Slapi_DN *dn, Slapi_Backend **be, char **backend_names, in
int count, int size,
char **referral, mapping_tree_node *parent,
int state, int private, char *plg_lib, char *plg_fct,
- mtn_distrib_fct plg)
+ mtn_distrib_fct plg, int plg_rootmode)
{
Slapi_RDN rdn;
mapping_tree_node *node;
@@ -326,6 +327,7 @@ mapping_tree_node_new(Slapi_DN *dn, Slapi_Backend **be, char **backend_names, in
slapi_rdn_done(&rdn);
node->mtn_dstr_plg_lib = plg_lib;
node->mtn_dstr_plg_name = plg_fct;
+ node->mtn_dstr_plg_rootmode = plg_rootmode;
node->mtn_dstr_plg = plg;
slapi_log_error(SLAPI_LOG_TRACE, "mapping_tree",
@@ -621,6 +623,7 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node **newnodep )
int * be_states = NULL;
char * plugin_funct = NULL;
char * plugin_lib = NULL;
+ int plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
mtn_distrib_fct plugin = NULL;
char **referral = NULL;
@@ -729,6 +732,24 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node **newnodep )
continue;
}
plugin_funct = slapi_ch_strdup(slapi_value_get_string(val));
+ } else if (!strcasecmp(type, "nsslapd-distribution-root-update")) {
+ const char *sval;
+ slapi_attr_first_value(attr, &val);
+ if (NULL == val) {
+ LDAPDebug(LDAP_DEBUG_ANY, "Warning: The nsslapd-distribution-plugin attribute has no value for the mapping tree node %s\n",
+ slapi_entry_get_dn(entry), 0, 0);
+ continue;
+ }
+ sval = slapi_value_get_string(val);
+ if (strcmp(sval,"reject") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
+ else if (strcmp(sval,"local") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_LOCAL;
+ else if (strcmp(sval,"referral") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REFERRAL;
+ else
+ LDAPDebug(LDAP_DEBUG_ANY, "Warning: The nsslapd-distribution-root-update attribute has undefined value (%s) for the mapping tree node %s\n",
+ sval, slapi_entry_get_dn(entry), 0);
} else if (!strcasecmp(type, MAPPING_TREE_PARENT_ATTRIBUTE)) {
Slapi_DN *parent_node_dn = get_parent_from_entry(entry);
parent_node = mtn_get_mapping_tree_node_by_entry(
@@ -845,7 +866,7 @@ mapping_tree_entry_add(Slapi_Entry *entry, mapping_tree_node **newnodep )
node= mapping_tree_node_new(subtree, be_list, be_names, be_states, be_list_count,
be_list_size, referral, parent_node, state,
0 /* Normal node. People can see and change it. */,
- plugin_lib, plugin_funct, plugin);
+ plugin_lib, plugin_funct, plugin, plugin_rootmode);
tmp_ndn = slapi_sdn_get_ndn( subtree );
if ( NULL != node && NULL == parent_node && tmp_ndn
@@ -1061,6 +1082,7 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor
int * be_states = NULL;
char * plugin_fct = NULL;
char * plugin_lib = NULL;
+ int plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
int plugin_flag = 0;
mtn_distrib_fct plugin = NULL;
@@ -1325,6 +1347,38 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor
plugin_flag = 1;
}
+ else if (strcasecmp(mods[i]->mod_type,
+ "nsslapd-distribution-root-update" ) == 0)
+ {
+ if (SLAPI_IS_MOD_REPLACE(mods[i]->mod_op)
+ || SLAPI_IS_MOD_ADD(mods[i]->mod_op))
+ {
+ const char *sval;
+ slapi_entry_attr_find(entryAfter,
+ "nsslapd-distribution-root-update", &attr);
+ slapi_attr_first_value(attr, &val);
+ if (NULL == val) {
+ LDAPDebug(LDAP_DEBUG_ANY,
+ "Warning: The nsslapd-distribution-root-update attribute"
+ " has no value for the mapping tree node %s\n",
+ slapi_entry_get_dn(entryAfter), 0, 0);
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
+ } else {
+ sval = slapi_value_get_string(val);
+ if (strcmp(sval,"reject") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT;
+ else if (strcmp(sval,"local") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_LOCAL;
+ else if (strcmp(sval,"referral") == 0)
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REFERRAL;
+ }
+ }
+ else if (SLAPI_IS_MOD_DELETE(mods[i]->mod_op))
+ {
+ plugin_rootmode = CHAIN_ROOT_UPDATE_REJECT; /* default */
+ }
+ plugin_flag = 1;
+ }
}
/* if distribution plugin has been configured or modified
@@ -1371,6 +1425,7 @@ int mapping_tree_entry_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor
if (node->mtn_dstr_plg_name)
slapi_ch_free((void **) &node->mtn_dstr_plg_name);
node->mtn_dstr_plg_name = plugin_fct;
+ node->mtn_dstr_plg_rootmode = plugin_rootmode;
node->mtn_dstr_plg = plugin;
mtn_unlock();
}
@@ -1626,7 +1681,7 @@ add_internal_mapping_tree_node(const char *subtree, Slapi_Backend *be, mapping_t
MTN_BACKEND,
1, /* The config node is a private node.
* People can't see or change it. */
- NULL, NULL, NULL);
+ NULL, NULL, NULL, 0); /* no distribution */
return node;
}
@@ -1994,6 +2049,8 @@ Slapi_Backend *slapi_mapping_tree_find_backend_for_sdn(Slapi_DN *sdn)
}
operation_set_target_spec(op, sdn);
slapi_pblock_set(pb, SLAPI_OPERATION, op);
+ /* requestor dn is not set in pblock, so the distribution plugin
+ * will return index >= 0 */
index = mtn_get_be_distributed(pb, target_node, sdn, &flag_stop);
slapi_pblock_destroy(pb); /* also frees the operation */
@@ -2504,7 +2561,7 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node * target_node,
{
index = (*target_node->mtn_dstr_plg)(pb, target_sdn,
target_node->mtn_backend_names, target_node->mtn_be_count,
- target_node->mtn_subtree, target_node->mtn_be_states);
+ target_node->mtn_subtree, target_node->mtn_be_states, target_node->mtn_dstr_plg_rootmode);
if (index == SLAPI_BE_ALL_BACKENDS)
{
@@ -2513,6 +2570,12 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node * target_node,
*/
index = 0;
}
+ /* check if distribution plugi returned a special mode for
+ * updates as root */
+ else if (index == -2 || index == -3)
+ {
+ /* nothing special to do */
+ }
/* paranoid check, never trust another programmer */
else if ((index >= target_node->mtn_be_count) || (index < 0))
{
@@ -2521,7 +2584,7 @@ mtn_get_be_distributed(Slapi_PBlock *pb, mapping_tree_node * target_node,
" : %d for entry %s at node %s\n",
index, slapi_sdn_get_ndn(target_sdn),
slapi_sdn_get_ndn(target_node->mtn_subtree));
- index = 0;
+ index = 0;
}
else
{
@@ -2600,6 +2663,7 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
((SLAPI_OPERATION_SEARCH == op_type)||(SLAPI_OPERATION_BIND == op_type) ||
(SLAPI_OPERATION_UNBIND == op_type) || (SLAPI_OPERATION_COMPARE == op_type))) ||
override_referral) {
+ *referral = NULL;
if ((target_node == mapping_tree_root) ){
/* If we got here, then we couldn't find a matching node
* for the target. We'll use the default backend. Once
@@ -2622,11 +2686,18 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
} else {
*index = mtn_get_be_distributed(pb, target_node,
target_sdn, &flag_stop);
- }
- }
-
- if ((*index == -2) || (*index >= target_node->mtn_be_count)) {
- /* we have already returned all backends -> return NULL */
+ if (*index == -2)
+ result = LDAP_UNWILLING_TO_PERFORM;
+ }
+ }
+ if (*index == -3) {
+ *be = NULL;
+ *referral = (target_node->mtn_referral_entry ?
+ slapi_entry_dup(target_node->mtn_referral_entry) :
+ NULL);
+ (*index)++;
+ }else if ((*index == -2) || (*index >= target_node->mtn_be_count)) {
+ /* we have already returned all backends -> return NULL */
*be = NULL;
*referral = NULL;
} else {
@@ -2673,7 +2744,6 @@ static int mtn_get_be(mapping_tree_node *target_node, Slapi_PBlock *pb,
(*index)++;
}
}
- *referral = NULL;
} else {
/* otherwise we must return the referral
* if ((target_node->mtn_state == MTN_REFERRAL) ||
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index 10d531e..900d3e5 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -762,6 +762,9 @@ char * slapi_schema_get_superior_name(const char *ocname_or_oid);
CSN *dup_global_schema_csn();
/* misc function for the chaining backend */
+#define CHAIN_ROOT_UPDATE_REJECT 0
+#define CHAIN_ROOT_UPDATE_LOCAL 1
+#define CHAIN_ROOT_UPDATE_REFERRAL 2
char * slapi_get_rootdn(); /* return the directory manager dn in use */
/* plugin interface to bulk import */
10 years, 7 months