summaryrefslogtreecommitdiffstats
path: root/ldap/servers
diff options
context:
space:
mode:
authorDavid Boreham <dboreham@redhat.com>2005-03-31 22:00:46 +0000
committerDavid Boreham <dboreham@redhat.com>2005-03-31 22:00:46 +0000
commitff2e6525088908ba32f727d92f0ea861b1cfa0b4 (patch)
treeeb2f3fa50a44bf4b9e24fa9ed6221827c7efdf41 /ldap/servers
parent3e4f39cde6b1e1fa0395c2f7bce0e13eaa0ead88 (diff)
downloadds-ff2e6525088908ba32f727d92f0ea861b1cfa0b4.tar.gz
ds-ff2e6525088908ba32f727d92f0ea861b1cfa0b4.tar.xz
ds-ff2e6525088908ba32f727d92f0ea861b1cfa0b4.zip
New windows sync code
Diffstat (limited to 'ldap/servers')
-rw-r--r--ldap/servers/plugins/replication/Makefile4
-rw-r--r--ldap/servers/plugins/replication/repl5.h28
-rw-r--r--ldap/servers/plugins/replication/repl5_agmt.c34
-rw-r--r--ldap/servers/plugins/replication/repl5_agmtlist.c8
-rw-r--r--ldap/servers/plugins/replication/repl5_prot_private.h2
-rw-r--r--ldap/servers/plugins/replication/repl5_protocol.c1
-rw-r--r--ldap/servers/plugins/replication/repl_globals.c4
-rw-r--r--ldap/servers/plugins/replication/repl_shared.h1
-rw-r--r--ldap/servers/plugins/replication/windows_connection.c291
-rw-r--r--ldap/servers/plugins/replication/windows_inc_protocol.c1982
-rw-r--r--ldap/servers/plugins/replication/windows_private.c376
-rw-r--r--ldap/servers/plugins/replication/windows_prot_private.h2
-rw-r--r--ldap/servers/plugins/replication/windows_protocol_util.c2290
-rw-r--r--ldap/servers/plugins/replication/windows_replica.c1213
-rw-r--r--ldap/servers/plugins/replication/windows_tot_protocol.c70
-rw-r--r--ldap/servers/plugins/replication/windows_total.c63
-rw-r--r--ldap/servers/plugins/replication/windowsrepl.h373
17 files changed, 3534 insertions, 3208 deletions
diff --git a/ldap/servers/plugins/replication/Makefile b/ldap/servers/plugins/replication/Makefile
index 8d874b1e..85866a82 100644
--- a/ldap/servers/plugins/replication/Makefile
+++ b/ldap/servers/plugins/replication/Makefile
@@ -130,6 +130,10 @@ EXTRA_LIBS += $(DLL_EXTRA_LIBS)
LD=ld
endif
+# ICU used by Windows Sync code
+INCLUDES+= $(ICU_INCLUDE)
+EXTRA_LIBS+=$(ICULINK)
+
clientSDK:
all: $(OBJDEST) $(LIBDIR) $(LIBREPLICATION)
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 3527f56f..19cafa41 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -109,7 +109,9 @@ extern const char *type_nsds5ReplicaSessionPauseTime;
extern const char *type_nsds7WindowsReplicaArea;
extern const char *type_nsds7DirectoryReplicaArea;
extern const char *type_nsds7CreateNewUsers;
-
+extern const char *type_nsds7CreateNewGroups;
+extern const char *type_nsds7DirsyncCookie;
+extern const char *type_nsds7WindowsDomain;
/* To Allow Consumer Initialisation when adding an agreement - */
extern const char *type_nsds5BeginReplicaRefresh;
@@ -274,6 +276,8 @@ int agmt_set_replicated_attributes_from_entry(Repl_Agmt *ra, const Slapi_Entry *
int agmt_set_replicated_attributes_from_attr(Repl_Agmt *ra, Slapi_Attr *sattr);
char **agmt_get_fractional_attrs(const Repl_Agmt *ra);
char **agmt_validate_replicated_attributes(Repl_Agmt *ra);
+void* agmt_get_priv (const Repl_Agmt *agmt);
+void agmt_set_priv (Repl_Agmt *agmt, void* priv);
int get_agmt_agreement_type ( Repl_Agmt *agmt);
@@ -527,20 +531,10 @@ void repl5_set_debug_timeout(const char *val);
/* temp hack XXX */
ReplicaId agmt_get_consumerRID(Repl_Agmt *ra);
-/* windows_private.c */
-typedef struct windowsprivate Dirsync_Private;
-void windows_private_delete(Dirsync_Private **dp);
-void* get_priv_from_agmt (const Repl_Agmt *agmt);
-Dirsync_Private* windows_private_new();
-void windows_private_set_windows_replarea (const Repl_Agmt *ra,const Slapi_DN* sdn );
-const Slapi_DN* windows_private_get_windows_replarea (const Repl_Agmt *ra);
-void windows_private_set_directory_replarea (const Repl_Agmt *ra,const Slapi_DN* sdn );
-const Slapi_DN* windows_private_get_directory_replarea (const Repl_Agmt *ra);
-LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra);
-ConnResult perform_search(Repl_Connection *conn);
-Slapi_Entry *windows_conn_get_search_result(Repl_Connection *conn );
-void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **controls );
-void windows_private_null_dirsync_control(const Repl_Agmt *ra);
-void windows_private_set_create_users(const Repl_Agmt *ra, PRBool value);
-PRBool windows_private_create_users(const Repl_Agmt *ra);
+
+void windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e);
+void windows_agreement_delete(Repl_Agmt *ra);
+Repl_Connection *windows_conn_new(Repl_Agmt *agmt);
+
+
#endif /* _REPL5_H_ */
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index a52df287..afc0b15e 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -45,7 +45,6 @@
*/
#include "repl5.h"
-#include "windowsrepl.h"
#include "repl5_prot_private.h"
#include "cl5_api.h"
#include "slapi-plugin.h"
@@ -98,7 +97,7 @@ typedef struct repl5agmt {
to allow another supplier to send its updates -
should be greater than busywaittime -
if set to 0, this means do not pause */
- void *priv; /* private data, used for cookie, and windows domain name */
+ void *priv; /* private data, used for windows-specific agreement data */
int agreement_type;
} repl5agmt;
@@ -326,27 +325,7 @@ agmt_new_from_entry(Slapi_Entry *e)
if (slapi_entry_attr_hasvalue(e, "objectclass", "nsDSWindowsReplicationAgreement"))
{
ra->agreement_type = REPLICA_TYPE_WINDOWS;
- ra->priv = windows_private_new();
-
- /* DN of entry at root of replicated area */
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsReplicaArea);
- if (NULL != tmpstr)
- {
- windows_private_set_windows_replarea(ra, slapi_sdn_new_dn_passin(tmpstr) );
- }
-
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7DirectoryReplicaArea);
- if (NULL != tmpstr)
- {
- windows_private_set_directory_replarea(ra, slapi_sdn_new_dn_passin(tmpstr) );
- }
-
- tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7CreateNewUsers);
- if (NULL != tmpstr)
- windows_private_set_create_users(ra, PR_TRUE);
- else
- windows_private_set_create_users(ra, PR_FALSE);
-
+ windows_init_agreement_from_entry(ra,e);
}
else
{
@@ -481,7 +460,7 @@ agmt_delete(void **rap)
if (ra->agreement_type == REPLICA_TYPE_WINDOWS)
{
- windows_private_delete(ra->priv);
+ windows_agreement_delete(ra);
}
schedule_destroy(ra->schedule);
@@ -2120,11 +2099,16 @@ get_agmt_agreement_type( Repl_Agmt *agmt)
return agmt->agreement_type;
}
-void* get_priv_from_agmt (const Repl_Agmt *agmt)
+void* agmt_get_priv (const Repl_Agmt *agmt)
{
PR_ASSERT (agmt);
return agmt->priv;
+}
+void agmt_set_priv (Repl_Agmt *agmt, void* priv)
+{
+ PR_ASSERT (agmt);
+ agmt->priv = priv;
}
ReplicaId agmt_get_consumerRID(Repl_Agmt *ra)
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
index 178a22b0..cb775dae 100644
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
@@ -530,13 +530,13 @@ agmtlist_config_init()
/* Register callbacks so we're informed about updates */
slapi_config_register_callback(SLAPI_OPERATION_ADD, DSE_FLAG_PREOP, AGMT_CONFIG_BASE,
- LDAP_SCOPE_SUBTREE, CONFIG_FILTER, agmtlist_add_callback, NULL);
+ LDAP_SCOPE_SUBTREE, GLOBAL_CONFIG_FILTER, agmtlist_add_callback, NULL);
slapi_config_register_callback(SLAPI_OPERATION_MODIFY, DSE_FLAG_PREOP, AGMT_CONFIG_BASE,
- LDAP_SCOPE_SUBTREE, CONFIG_FILTER, agmtlist_modify_callback, NULL);
+ LDAP_SCOPE_SUBTREE, GLOBAL_CONFIG_FILTER, agmtlist_modify_callback, NULL);
slapi_config_register_callback(SLAPI_OPERATION_DELETE, DSE_FLAG_PREOP, AGMT_CONFIG_BASE,
- LDAP_SCOPE_SUBTREE, CONFIG_FILTER, agmtlist_delete_callback, NULL);
+ LDAP_SCOPE_SUBTREE, GLOBAL_CONFIG_FILTER, agmtlist_delete_callback, NULL);
slapi_config_register_callback(SLAPI_OPERATION_MODRDN, DSE_FLAG_PREOP, AGMT_CONFIG_BASE,
- LDAP_SCOPE_SUBTREE, CONFIG_FILTER, agmtlist_rename_callback, NULL);
+ LDAP_SCOPE_SUBTREE, GLOBAL_CONFIG_FILTER, agmtlist_rename_callback, NULL);
/* Search the DIT and find all the replication agreements */
pb = slapi_pblock_new();
diff --git a/ldap/servers/plugins/replication/repl5_prot_private.h b/ldap/servers/plugins/replication/repl5_prot_private.h
index f4ede144..e7efb705 100644
--- a/ldap/servers/plugins/replication/repl5_prot_private.h
+++ b/ldap/servers/plugins/replication/repl5_prot_private.h
@@ -67,6 +67,6 @@ CSN *get_current_csn(Slapi_DN *replarea_sdn);
char* protocol_response2string (int response);
int repl5_strip_fractional_mods(Repl_Agmt *agmt, LDAPMod **);
void windows_release_replica(Private_Repl_Protocol *prp);
-int windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv);
+int windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv, int check_ruv);
#endif /* _REPL5_PROT_PRIVATE_H_ */
diff --git a/ldap/servers/plugins/replication/repl5_protocol.c b/ldap/servers/plugins/replication/repl5_protocol.c
index 4d8dc3a9..fcb9b2a8 100644
--- a/ldap/servers/plugins/replication/repl5_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_protocol.c
@@ -15,7 +15,6 @@
*/
#include "repl5.h"
-#include "windowsrepl.h"
#include "repl5_prot_private.h"
#define PROTOCOL_5_INCREMENTAL 1
diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c
index bfabf777..d69e35ae 100644
--- a/ldap/servers/plugins/replication/repl_globals.c
+++ b/ldap/servers/plugins/replication/repl_globals.c
@@ -93,7 +93,9 @@ const char *type_nsds5ReplicaSessionPauseTime = "nsds5ReplicaSessionPauseTime";
const char *type_nsds7WindowsReplicaArea = "nsds7WindowsReplicaSubtree";
const char *type_nsds7DirectoryReplicaArea = "nsds7DirectoryReplicaSubtree";
const char *type_nsds7CreateNewUsers = "nsds7NewWinUserSyncEnabled";
-
+const char *type_nsds7CreateNewGroups = "nsds7NewWinGroupSyncEnabled";
+const char *type_nsds7WindowsDomain = "nsds7WindowsDomain";
+const char *type_nsds7DirsyncCookie = "nsds7DirsyncCookie";
/* To Allow Consumer Initialisation when adding an agreement - */
const char *type_nsds5BeginReplicaRefresh = "nsds5BeginReplicaRefresh";
diff --git a/ldap/servers/plugins/replication/repl_shared.h b/ldap/servers/plugins/replication/repl_shared.h
index 3e65ddff..df14a70f 100644
--- a/ldap/servers/plugins/replication/repl_shared.h
+++ b/ldap/servers/plugins/replication/repl_shared.h
@@ -98,6 +98,7 @@
#define CHANGELOG_DB_VERSION_PREV "3.0"
#define CHANGELOG_DB_VERSION "4.0"
extern char *repl_plugin_name;
+extern char *windows_repl_plugin_name;
extern char *repl_plugin_name_cl;
/* repl_monitor.c */
diff --git a/ldap/servers/plugins/replication/windows_connection.c b/ldap/servers/plugins/replication/windows_connection.c
index d0651f51..96593e84 100644
--- a/ldap/servers/plugins/replication/windows_connection.c
+++ b/ldap/servers/plugins/replication/windows_connection.c
@@ -15,8 +15,9 @@ replica locked. Seems like right thing to do.
*/
#include "repl5.h"
-#include "ldappr.h"
#include "windowsrepl.h"
+#include "ldappr.h"
+#include "slap.h"
typedef struct repl_connection
{
@@ -108,6 +109,8 @@ windows_conn_new(Repl_Agmt *agmt)
{
Repl_Connection *rpc;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_new\n", 0, 0, 0 );
+
rpc = (Repl_Connection *)slapi_ch_malloc(sizeof(repl_connection));
if ((rpc->lock = PR_NewLock()) == NULL)
{
@@ -138,9 +141,11 @@ windows_conn_new(Repl_Agmt *agmt)
rpc->timeout.tv_usec = 0;
rpc->flag_agmt_changed = 0;
rpc->plain = NULL;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_new\n", 0, 0, 0 );
return rpc;
loser:
windows_conn_delete(rpc);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_new - loser\n", 0, 0, 0 );
return NULL;
}
@@ -152,9 +157,11 @@ static PRBool
windows_conn_connected(Repl_Connection *conn)
{
PRBool return_value;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_connected\n", 0, 0, 0 );
PR_Lock(conn->lock);
return_value = STATE_CONNECTED == conn->state;
PR_Unlock(conn->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_connected\n", 0, 0, 0 );
return return_value;
}
@@ -165,12 +172,14 @@ windows_conn_connected(Repl_Connection *conn)
static void
windows_conn_delete_internal(Repl_Connection *conn)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_delete_internal\n", 0, 0, 0 );
PR_ASSERT(NULL != conn);
close_connection_internal(conn);
/* slapi_ch_free accepts NULL pointer */
slapi_ch_free((void **)&conn->hostname);
slapi_ch_free((void **)&conn->binddn);
slapi_ch_free((void **)&conn->plain);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_delete_internal\n", 0, 0, 0 );
}
/*
@@ -182,6 +191,8 @@ windows_conn_delete(Repl_Connection *conn)
{
PRBool destroy_it = PR_FALSE;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_delete\n", 0, 0, 0 );
+
PR_ASSERT(NULL != conn);
PR_Lock(conn->lock);
if (conn->linger_active)
@@ -207,6 +218,7 @@ windows_conn_delete(Repl_Connection *conn)
{
windows_conn_delete_internal(conn);
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_delete\n", 0, 0, 0 );
}
@@ -217,10 +229,12 @@ windows_conn_delete(Repl_Connection *conn)
void
windows_conn_get_error(Repl_Connection *conn, int *operation, int *error)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_get_error\n", 0, 0, 0 );
PR_Lock(conn->lock);
*operation = conn->last_operation;
*error = conn->last_ldap_error;
PR_Unlock(conn->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_get_error\n", 0, 0, 0 );
}
@@ -251,6 +265,8 @@ windows_perform_operation(Repl_Connection *conn, int optype, const char *dn,
const char *op_string = NULL;
const char *extra_op_string = NULL;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_perform_operation\n", 0, 0, 0 );
+
server_controls[0] = NULL;
if (windows_conn_connected(conn))
@@ -432,11 +448,111 @@ windows_perform_operation(Repl_Connection *conn, int optype, const char *dn,
*/
return_value = CONN_NOT_CONNECTED;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_perform_operation\n", 0, 0, 0 );
return return_value;
}
+/* Copied from the chaining backend*/
+static Slapi_Entry *
+windows_LDAPMessage2Entry(LDAP * ld, LDAPMessage * msg, int attrsonly) {
+
+ Slapi_Entry * e = slapi_entry_alloc();
+ char * a=NULL;
+ BerElement * ber=NULL;
+
+ if ( e == NULL ) return NULL;
+ if (msg == NULL) {
+ slapi_entry_free(e);
+ return NULL;
+ }
+
+ /*
+ * dn not allocated by slapi
+ * attribute type and values ARE allocated
+ */
+
+ slapi_entry_set_dn( e, ldap_get_dn( ld, msg ) );
+
+ for ( a = ldap_first_attribute( ld, msg, &ber ); a!=NULL;
+ a=ldap_next_attribute( ld, msg, ber ) ) {
+ if(attrsonly) {
+ slapi_entry_add_value(e, a, (Slapi_Value *)NULL);
+ ldap_memfree(a);
+ } else {
+ struct berval ** aVal = ldap_get_values_len( ld, msg, a);
+ slapi_entry_add_values( e, a, aVal);
+
+ ldap_memfree(a);
+ ldap_value_free_len(aVal);
+ }
+ }
+ if ( NULL != ber )
+ ldap_ber_free( ber, 0 );
+
+ return e;
+}
+
ConnResult
-perform_search(Repl_Connection *conn)
+windows_search_entry(Repl_Connection *conn, char* searchbase, char *filter, Slapi_Entry **entry)
+{
+ ConnResult return_value = 0;
+ int ldap_rc = 0;
+ LDAPMessage *res = NULL;
+ int not_unique = 0;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_search_entry\n", 0, 0, 0 );
+
+ *entry = NULL;
+
+ if (windows_conn_connected(conn))
+ {
+ ldap_rc = ldap_search_ext_s(conn->ld, searchbase, LDAP_SCOPE_SUBTREE,
+ filter, NULL, 0 /* attrsonly */,
+ NULL , NULL /* client controls */,
+ &conn->timeout, 0 /* sizelimit */, &res);
+ if (LDAP_SUCCESS == ldap_rc)
+ {
+ LDAPMessage *message = ldap_first_entry(conn->ld, res);
+ LDAPMessage *next_entry = NULL;
+ if (NULL != entry)
+ {
+ *entry = windows_LDAPMessage2Entry(conn->ld,message,0);
+ }
+ /* See if there are any more entries : if so then that's an error
+ * but we still need to get them to avoid gumming up the connection
+ */
+ while (NULL != ( next_entry = ldap_next_entry(conn->ld,res)))
+ {
+ not_unique = 1;
+ }
+ return_value = CONN_OPERATION_SUCCESS;
+ }
+ else if (IS_DISCONNECT_ERROR(ldap_rc))
+ {
+ windows_conn_disconnect(conn);
+ return_value = CONN_NOT_CONNECTED;
+ }
+ else
+ {
+ return_value = CONN_OPERATION_FAILED;
+ }
+ conn->last_ldap_error = ldap_rc;
+ if (NULL != res)
+ {
+ ldap_msgfree(res);
+ res = NULL;
+ }
+ }
+ else
+ {
+ return_value = CONN_NOT_CONNECTED;
+ }
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_search_entry\n", 0, 0, 0 );
+ return return_value;
+}
+
+ConnResult
+send_dirsync_search(Repl_Connection *conn)
{
int rc;
ConnResult return_value;
@@ -449,33 +565,38 @@ perform_search(Repl_Connection *conn)
char* dn = NULL;
int i=0;
int num_comp=0;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> send_dirsync_search\n", 0, 0, 0 );
/* need to strip the dn down to dc= */
- /* XXX: this is not the most elegant way of doing this */
- old_dn = slapi_sdn_get_ndn( windows_private_get_windows_replarea(conn->agmt) );
+ old_dn = slapi_sdn_get_ndn( windows_private_get_windows_subtree(conn->agmt) );
dn = strstr(old_dn, "dc=");
if (windows_conn_connected(conn))
{
if (conn->supports_dirsync == 0)
+ {
server_controls[0] = NULL; /* unsupported */
- else
+ } else
+ {
+ /* DBDB: I'm pretty sure that the control is leaked from here */
+ /* Purify agrees */
server_controls[0] = windows_private_dirsync_control(conn->agmt); /* yes, or don't know */
+ }
server_controls[1] = NULL;
conn->last_operation = CONN_SEARCH;
conn->status = STATUS_SEARCHING;
op_string = "search";
+ LDAPDebug( LDAP_DEBUG_REPL, "Sending dirsync search request\n", 0, 0, 0 );
+
rc = ldap_search_ext( conn->ld, dn, LDAP_SCOPE_SUBTREE, "(objectclass=*)", /* filter */
NULL /*attrs */, PR_FALSE, server_controls, NULL, /* ClientControls */
0,0, &msgid);
if (LDAP_SUCCESS == rc)
{
-
- int setlevel = 0;
- int finished = 0;
return_value = 0;
}
else
@@ -496,6 +617,11 @@ perform_search(Repl_Connection *conn)
return_value = CONN_OPERATION_FAILED;
}
}
+ if (server_controls[0])
+ {
+ ldap_control_free(server_controls[0]);
+ }
+
}
else
{
@@ -505,6 +631,7 @@ perform_search(Repl_Connection *conn)
*/
return_value = CONN_NOT_CONNECTED;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= send_dirsync_search\n", 0, 0, 0 );
return return_value;
}
@@ -516,10 +643,14 @@ ConnResult
windows_conn_send_add(Repl_Connection *conn, const char *dn, LDAPMod **attrs,
LDAPControl *update_control, LDAPControl ***returned_controls)
{
- return windows_perform_operation(conn, CONN_ADD, dn, attrs, NULL /* newrdn */,
+ ConnResult res = 0;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_send_add\n", 0, 0, 0 );
+ res = windows_perform_operation(conn, CONN_ADD, dn, attrs, NULL /* newrdn */,
NULL /* newparent */, 0 /* deleteoldrdn */, update_control,
NULL /* extop OID */, NULL /* extop payload */, NULL /* retoidp */,
NULL /* retdatap */, returned_controls);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_send_add\n", 0, 0, 0 );
+ return res;
}
@@ -530,6 +661,8 @@ ConnResult
windows_conn_send_delete(Repl_Connection *conn, const char *dn,
LDAPControl *update_control, LDAPControl ***returned_controls)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_send_delete\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_send_delete\n", 0, 0, 0 );
return windows_perform_operation(conn, CONN_DELETE, dn, NULL /* attrs */,
NULL /* newrdn */, NULL /* newparent */, 0 /* deleteoldrdn */,
update_control, NULL /* extop OID */, NULL /* extop payload */,
@@ -544,6 +677,8 @@ ConnResult
windows_conn_send_modify(Repl_Connection *conn, const char *dn, LDAPMod **mods,
LDAPControl *update_control, LDAPControl ***returned_controls)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_send_modify\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_send_modify\n", 0, 0, 0 );
return windows_perform_operation(conn, CONN_MODIFY, dn, mods, NULL /* newrdn */,
NULL /* newparent */, 0 /* deleteoldrdn */, update_control,
NULL /* extop OID */, NULL /* extop payload */, NULL /* retoidp */,
@@ -558,6 +693,8 @@ windows_conn_send_rename(Repl_Connection *conn, const char *dn,
const char *newrdn, const char *newparent, int deleteoldrdn,
LDAPControl *update_control, LDAPControl ***returned_controls)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_send_rename\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_send_rename\n", 0, 0, 0 );
return windows_perform_operation(conn, CONN_RENAME, dn, NULL /* attrs */,
newrdn, newparent, deleteoldrdn, update_control,
NULL /* extop OID */, NULL /* extop payload */, NULL /* retoidp */,
@@ -578,6 +715,9 @@ Slapi_Entry * windows_conn_get_search_result(Repl_Connection *conn)
char *a = "";
char *dn = "";
BerElement *ber = NULL;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_get_search_result\n", 0, 0, 0 );
+
if (windows_conn_connected(conn))
{
rc = ldap_result( conn->ld, LDAP_RES_ANY, 0, &conn->timeout, &res );
@@ -585,49 +725,48 @@ Slapi_Entry * windows_conn_get_search_result(Repl_Connection *conn)
case 0:
case -1:
case LDAP_RES_SEARCH_REFERENCE:
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "error, rc=%d\n", rc);
- ldap_msgfree( res );
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "error in windows_conn_get_search_result, rc=%d\n", rc);
break;
case LDAP_RES_SEARCH_RESULT:
{
- LDAPControl **returned_controls;
- int code=0;
- int parse_rc;
- parse_rc = ldap_parse_result( conn->ld, res, &code, NULL, NULL, NULL, &returned_controls, 1 );
- windows_private_update_dirsync_control(conn->agmt, returned_controls);
+ LDAPControl **returned_controls = NULL;
+ int code = 0;
+ int parse_rc = 0;
+ /* Purify says this is a leak : */
+ parse_rc = ldap_parse_result( conn->ld, res, &code, NULL, NULL, NULL, &returned_controls, 0 );
+ if (returned_controls)
+ {
+ windows_private_update_dirsync_control(conn->agmt, returned_controls);
+ ldap_controls_free(returned_controls);
+ }
+ if (windows_private_dirsync_has_more(conn->agmt)) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"received hasmore from dirsync\n", 0);
+ }
}
break;
case LDAP_RES_SEARCH_ENTRY:
{
if (( dn = ldap_get_dn( conn->ld, res )) != NULL )
{
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"found an entry %s\n", dn);
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"received entry from dirsync: %s\n", dn);
lm = ldap_first_entry( conn->ld, res );
- e = slapi_entry_alloc();
- slapi_entry_init(e, dn, NULL);
- for ( a = ldap_first_attribute( conn->ld, lm, &ber ); a != NULL; a = ldap_next_attribute( conn->ld, lm, ber ) )
- {
- int i =0;
- char **vals;
-
- if ((vals = ldap_get_values( conn->ld, lm, a)) != NULL )
- {
- for ( i = 0; vals[i] != NULL; i++ )
- {
- slapi_entry_add_string (e, a, vals[i]);
- }
- ldap_value_free( vals );
- }
- }
+ e = windows_LDAPMessage2Entry(conn->ld,lm,0);
+ ldap_memfree(dn);
}
}
break;
- } // switch
- } //if
+ } /* switch */
+ } /* if */
- return e;
+ if (res)
+ {
+ ldap_msgfree( res );
+ res = NULL;
+ }
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_get_search_result\n", 0, 0, 0 );
+ return e;
}
@@ -639,6 +778,8 @@ windows_conn_send_extended_operation(Repl_Connection *conn, const char *extop_oi
struct berval *payload, char **retoidp, struct berval **retdatap,
LDAPControl *update_control, LDAPControl ***returned_controls)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_send_extended_operation\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_send_extended_operation\n", 0, 0, 0 );
return windows_perform_operation(conn, CONN_EXTENDED_OPERATION, NULL /* dn */, NULL /* attrs */,
NULL /* newrdn */, NULL /* newparent */, 0 /* deleteoldrdn */,
update_control, extop_oid, payload, retoidp, retdatap,
@@ -665,6 +806,8 @@ windows_conn_read_entry_attribute(Repl_Connection *conn, const char *dn,
LDAPMessage *res = NULL;
char *attrs[2];
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_read_entry_attribute\n", 0, 0, 0 );
+
PR_ASSERT(NULL != type);
if (windows_conn_connected(conn))
{
@@ -705,6 +848,7 @@ windows_conn_read_entry_attribute(Repl_Connection *conn, const char *dn,
{
return_value = CONN_NOT_CONNECTED;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_read_entry_attribute\n", 0, 0, 0 );
return return_value;
}
@@ -716,6 +860,8 @@ windows_conn_read_entry_attribute(Repl_Connection *conn, const char *dn,
const char *
windows_conn_get_status(Repl_Connection *conn)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_get_status\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_get_status\n", 0, 0, 0 );
return conn->status;
}
@@ -728,6 +874,7 @@ windows_conn_get_status(Repl_Connection *conn)
void
windows_conn_cancel_linger(Repl_Connection *conn)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_cancel_linger\n", 0, 0, 0 );
PR_ASSERT(NULL != conn);
PR_Lock(conn->lock);
if (conn->linger_active)
@@ -750,6 +897,7 @@ windows_conn_cancel_linger(Repl_Connection *conn)
agmt_get_long_name(conn->agmt));
}
PR_Unlock(conn->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_cancel_linger\n", 0, 0, 0 );
}
@@ -765,6 +913,8 @@ linger_timeout(time_t event_time, void *arg)
PRBool delete_now;
Repl_Connection *conn = (Repl_Connection *)arg;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> linger_timeout\n", 0, 0, 0 );
+
PR_ASSERT(NULL != conn);
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
"%s: Linger timeout has expired on the connection\n",
@@ -782,6 +932,7 @@ linger_timeout(time_t event_time, void *arg)
{
windows_conn_delete_internal(conn);
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= linger_timeout\n", 0, 0, 0 );
}
@@ -794,6 +945,8 @@ windows_conn_start_linger(Repl_Connection *conn)
{
time_t now;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_start_linger\n", 0, 0, 0 );
+
PR_ASSERT(NULL != conn);
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
"%s: Beginning linger on the connection\n",
@@ -820,6 +973,7 @@ windows_conn_start_linger(Repl_Connection *conn)
conn->status = STATUS_LINGERING;
}
PR_Unlock(conn->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_start_linger\n", 0, 0, 0 );
}
@@ -843,8 +997,13 @@ windows_conn_connect(Repl_Connection *conn)
ConnResult return_value = CONN_OPERATION_SUCCESS;
int pw_ret = 1;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_connect\n", 0, 0, 0 );
+
/** Connection already open just return SUCCESS **/
- if(conn->state == STATE_CONNECTED) return return_value;
+ if(conn->state == STATE_CONNECTED) {
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_connect\n", 0, 0, 0 );
+ return return_value;
+ }
PR_Lock(conn->lock);
if (conn->flag_agmt_changed) {
@@ -882,6 +1041,7 @@ windows_conn_connect(Repl_Connection *conn)
return_value = CONN_OPERATION_FAILED;
conn->last_ldap_error = LDAP_INVALID_CREDENTIALS;
conn->state = STATE_DISCONNECTED;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_connect\n", 0, 0, 0 );
return (return_value);
} /* Else, does not mean that the plain is correct, only means the we had no internal
decoding pb */
@@ -915,6 +1075,7 @@ windows_conn_connect(Repl_Connection *conn)
conn->last_operation = CONN_INIT;
ber_bvfree(creds);
creds = NULL;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_connect\n", 0, 0, 0 );
return CONN_SSL_NOT_ENABLED;
} else
{
@@ -944,6 +1105,7 @@ windows_conn_connect(Repl_Connection *conn)
secure ? "secure " : "");
ber_bvfree(creds);
creds = NULL;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_connect\n", 0, 0, 0 );
return return_value;
}
@@ -1004,6 +1166,7 @@ windows_conn_connect(Repl_Connection *conn)
conn->state = STATE_CONNECTED;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_connect\n", 0, 0, 0 );
return return_value;
}
@@ -1011,6 +1174,8 @@ windows_conn_connect(Repl_Connection *conn)
static void
close_connection_internal(Repl_Connection *conn)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> close_connection_internal\n", 0, 0, 0 );
+
if (NULL != conn->ld)
{
/* Since we call slapi_ldap_init,
@@ -1023,15 +1188,18 @@ close_connection_internal(Repl_Connection *conn)
conn->supports_ds50_repl = -1;
slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
"%s: Disconnected from the consumer\n", agmt_get_long_name(conn->agmt));
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= close_connection_internal\n", 0, 0, 0 );
}
void
windows_conn_disconnect(Repl_Connection *conn)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_disconnect\n", 0, 0, 0 );
PR_ASSERT(NULL != conn);
PR_Lock(conn->lock);
close_connection_internal(conn);
PR_Unlock(conn->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_disconnect\n", 0, 0, 0 );
}
@@ -1051,6 +1219,8 @@ windows_conn_replica_supports_ds5_repl(Repl_Connection *conn)
ConnResult return_value;
int ldap_rc;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_replica_supports_ds5_repl\n", 0, 0, 0 );
+
if (windows_conn_connected(conn))
{
if (conn->supports_ds50_repl == -1) {
@@ -1118,6 +1288,7 @@ windows_conn_replica_supports_ds5_repl(Repl_Connection *conn)
/* Not connected */
return_value = CONN_NOT_CONNECTED;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_replica_supports_ds5_repl\n", 0, 0, 0 );
return return_value;
}
@@ -1128,6 +1299,8 @@ windows_conn_replica_supports_dirsync(Repl_Connection *conn)
ConnResult return_value;
int ldap_rc;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_replica_supports_dirsync\n", 0, 0, 0 );
+
if (windows_conn_connected(conn))
{
if (conn->supports_dirsync == -1) {
@@ -1180,6 +1353,7 @@ windows_conn_replica_supports_dirsync(Repl_Connection *conn)
/* Not connected */
return_value = CONN_NOT_CONNECTED;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_replica_supports_dirsync\n", 0, 0, 0 );
return return_value;
}
@@ -1195,6 +1369,8 @@ attribute_string_value_present(LDAP *ld, LDAPMessage *entry, const char *type,
{
int return_value = 0;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> attribute_string_value_present\n", 0, 0, 0 );
+
if (NULL != entry)
{
char *atype = NULL;
@@ -1228,6 +1404,7 @@ attribute_string_value_present(LDAP *ld, LDAPMessage *entry, const char *type,
if (NULL != atype)
ldap_memfree(atype);
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= attribute_string_value_present\n", 0, 0, 0 );
return return_value;
}
@@ -1251,20 +1428,24 @@ attribute_string_value_present(LDAP *ld, LDAPMessage *entry, const char *type,
void
windows_conn_set_timeout(Repl_Connection *conn, long timeout)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_set_timeout\n", 0, 0, 0 );
PR_ASSERT(NULL != conn);
PR_ASSERT(timeout >= 0);
PR_Lock(conn->lock);
conn->timeout.tv_sec = timeout;
PR_Unlock(conn->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_timeout\n", 0, 0, 0 );
}
void windows_conn_set_agmt_changed(Repl_Connection *conn)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_set_agmt_changed\n", 0, 0, 0 );
PR_ASSERT(NULL != conn);
PR_Lock(conn->lock);
if (NULL != conn->agmt)
conn->flag_agmt_changed = 1;
PR_Unlock(conn->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed\n", 0, 0, 0 );
}
/*
@@ -1287,6 +1468,8 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
char * optype; /* ldap_simple_bind or slapd_SSL_client_bind */
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_conn_set_agmt_changed\n", 0, 0, 0 );
+
if ( conn->transport_flags == TRANSPORT_FLAG_SSL )
{
char *auth;
@@ -1319,6 +1502,8 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
ldap_err2string(rc));
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed - CONN_OPERATION_FAILED\n", 0, 0, 0 );
+
return (CONN_OPERATION_FAILED);
}
}
@@ -1326,6 +1511,7 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
{
if( ( msgid = do_simple_bind( conn, ld, binddn, password ) ) == -1 )
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed - CONN_OPERATION_FAILED\n", 0, 0, 0 );
return (CONN_OPERATION_FAILED);
}
}
@@ -1335,6 +1521,7 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
optype = "ldap_simple_bind";
if( ( msgid = do_simple_bind( conn, ld, binddn, password ) ) == -1 )
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed - CONN_OPERATION_FAILED\n", 0, 0, 0 );
return (CONN_OPERATION_FAILED);
}
}
@@ -1344,7 +1531,9 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
{
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"%s: Received error from consumer for %s operation\n",
+
agmt_get_long_name(conn->agmt), optype);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed - CONN_OPERATION_FAILED\n", 0, 0, 0 );
return (CONN_OPERATION_FAILED);
}
@@ -1358,6 +1547,8 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
"%s: Received error from consumer for %s operation\n",
agmt_get_long_name(conn->agmt), optype);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed - CONN_OPERATION_FAILED\n", 0, 0, 0 );
+
return (CONN_OPERATION_FAILED);
}
@@ -1393,6 +1584,8 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
ldap_controls_free( ctrls );
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed - CONN_OPERATION_SUCCESS\n", 0, 0, 0 );
+
return (CONN_OPERATION_SUCCESS);
}
else
@@ -1404,6 +1597,7 @@ bind_and_check_pwp(Repl_Connection *conn, char * binddn, char *password)
agmt_get_long_name(conn->agmt), binddn, rc, errmsg);
conn->last_ldap_error = rc; /* specific error */
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_conn_set_agmt_changed - CONN_OPERATION_FAILED\n", 0, 0, 0 );
return (CONN_OPERATION_FAILED);
}
}
@@ -1413,6 +1607,8 @@ do_simple_bind (Repl_Connection *conn, LDAP *ld, char * binddn, char *password)
{
int msgid;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> do_simple_bind\n", 0, 0, 0 );
+
if( ( msgid = ldap_simple_bind( ld, binddn, password ) ) == -1 )
{
char *ldaperrtext = NULL;
@@ -1440,6 +1636,7 @@ do_simple_bind (Repl_Connection *conn, LDAP *ld, char * binddn, char *password)
"%s: Simple bind resumed\n",
agmt_get_long_name(conn->agmt));
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= do_simple_bind\n", 0, 0, 0 );
return msgid;
}
@@ -1449,10 +1646,14 @@ PRTime2time_t (PRTime tm)
{
PRInt64 rt;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> PRTime2time_t\n", 0, 0, 0 );
+
PR_ASSERT (tm);
LL_DIV(rt, tm, PR_USEC_PER_SEC);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= PRTime2time_t\n", 0, 0, 0 );
+
return (time_t)rt;
}
@@ -1460,11 +1661,15 @@ static Slapi_Eq_Context
repl5_start_debug_timeout(int *setlevel)
{
Slapi_Eq_Context eqctx = 0;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> repl5_start_debug_timeout\n", 0, 0, 0 );
+
if (s_debug_timeout && s_debug_level) {
time_t now = time(NULL);
eqctx = slapi_eq_once(repl5_debug_timeout_callback, setlevel,
s_debug_timeout + now);
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= repl5_start_debug_timeout\n", 0, 0, 0 );
return eqctx;
}
@@ -1474,25 +1679,31 @@ repl5_stop_debug_timeout(Slapi_Eq_Context eqctx, int *setlevel)
char buf[20];
char msg[SLAPI_DSE_RETURNTEXT_SIZE];
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> repl5_stop_debug_timeout\n", 0, 0, 0 );
+
if (eqctx && !*setlevel) {
int found = slapi_eq_cancel(eqctx);
}
if (s_debug_timeout && s_debug_level && *setlevel) {
- void config_set_errorlog_level(const char *type, char *buf, char *msg, int apply);
+ /* No longer needed as we are including the one in slap.h */
sprintf(buf, "%d", 0);
config_set_errorlog_level("nsslapd-errorlog-level", buf, msg, 1);
}
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= repl5_stop_debug_timeout\n", 0, 0, 0 );
}
static void
repl5_debug_timeout_callback(time_t when, void *arg)
{
int *setlevel = (int *)arg;
- void config_set_errorlog_level(const char *type, char *buf, char *msg, int apply);
+ /* No longer needed as we are including the one in slap.h */
char buf[20];
char msg[SLAPI_DSE_RETURNTEXT_SIZE];
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> repl5_debug_timeout_callback\n", 0, 0, 0 );
+
*setlevel = 1;
sprintf(buf, "%d", s_debug_level);
config_set_errorlog_level("nsslapd-errorlog-level", buf, msg, 1);
@@ -1500,4 +1711,6 @@ repl5_debug_timeout_callback(time_t when, void *arg)
slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
"repl5_debug_timeout_callback: set debug level to %d at %d\n",
s_debug_level, when);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= repl5_debug_timeout_callback\n", 0, 0, 0 );
}
diff --git a/ldap/servers/plugins/replication/windows_inc_protocol.c b/ldap/servers/plugins/replication/windows_inc_protocol.c
index 1de3fb2a..f588d6ba 100644
--- a/ldap/servers/plugins/replication/windows_inc_protocol.c
+++ b/ldap/servers/plugins/replication/windows_inc_protocol.c
@@ -32,59 +32,6 @@ Perhaps these events should be properties of the main protocol.
#include "slapi-plugin.h"
extern int slapi_log_urp;
-typedef struct attribute_map
-{
- char *old_name;
- char *new_name;
- int map_to;
-
-} attribute_map;
-
-static attribute_map mapping[] =
-{ /* map the attribute from , to, which platform we going to? */
- { "ntUserDomainId", "sAMAccountName", REPLICA_TYPE_WINDOWS},
- { "ntUserHomeDir", "homeDirectory", REPLICA_TYPE_WINDOWS},
- { "ntUserScriptPath", "scriptPath", REPLICA_TYPE_WINDOWS},
- { "ntUserLastLogon", "lastLogon", REPLICA_TYPE_WINDOWS},
- { "ntUserLastLogoff", "lastLogoff", REPLICA_TYPE_WINDOWS},
- { "cn", "description", REPLICA_TYPE_WINDOWS}, /* temporary */
- { "uid", "cn", REPLICA_TYPE_WINDOWS},
- { "dn", "dn", REPLICA_TYPE_WINDOWS},
- { "sn", "sn", REPLICA_TYPE_WINDOWS},
-
- { "sAMAccountName", "ntUserDomainId", REPLICA_TYPE_MULTIMASTER},
- { "homeDirectory", "ntUserHomeDir", REPLICA_TYPE_MULTIMASTER},
- { "scriptPath", "ntUserScriptPath", REPLICA_TYPE_MULTIMASTER},
- { "lastLogon", "ntUserLastLogon", REPLICA_TYPE_MULTIMASTER},
- { "lastLogoff", "ntUserLastLogoff", REPLICA_TYPE_MULTIMASTER},
- { "sAMAccountName", "uid", REPLICA_TYPE_MULTIMASTER},
- { "dn", "dn", REPLICA_TYPE_MULTIMASTER},
- { "sAMAccountName", "sn", REPLICA_TYPE_MULTIMASTER},
- { "sAMAccountName", "cn", REPLICA_TYPE_MULTIMASTER},
-
- {NULL, NULL, -1}
-};
-
-static attribute_map group_map[] =
-{
- { "ntGroupDomainId ", "name", REPLICA_TYPE_WINDOWS},
- { "ntGroupDomainId ", "sAMAccountName", REPLICA_TYPE_WINDOWS},
- { "ntGroupType", "groupType", REPLICA_TYPE_WINDOWS},
-
- { "sAMAccountName", "ntGroupDomainId ", REPLICA_TYPE_MULTIMASTER},
- { "groupType", "ntGroupType", REPLICA_TYPE_MULTIMASTER},
-
- {NULL, NULL, -1}
-
-};
-
-void map_entry_user(Slapi_Entry **e, int map_to, char** password);
-static Slapi_Entry* windows_entry_already_exists(Slapi_Entry *e);
-
-static Slapi_DN* map_dn_user(Slapi_DN *sdn, int map_to, const Slapi_DN *root);
-static Slapi_DN* map_dn_group(Slapi_DN *sdn, int map_to, const Slapi_DN *root);
-static void make_mods_from_entries(Slapi_Entry *new_entry, Slapi_Entry *existing_entry, LDAPMod ***attrs);
-static void alter_mods(LDAPMod ***m, char** password);
/*** from proto-slap.h ***/
void ava_done(struct ava *ava);
@@ -119,6 +66,7 @@ typedef struct windows_inc_private
#define EVENT_REPLICATE_NOW 16
#define EVENT_PROTOCOL_SHUTDOWN 32
#define EVENT_AGMT_CHANGED 64
+#define EVENT_RUN_DIRSYNC 128
#define UPDATE_NO_MORE_UPDATES 201
#define UPDATE_TRANSIENT_ERROR 202
@@ -142,7 +90,11 @@ typedef struct windows_inc_private
* we go ahead and start a replication session, just to be safe
*/
#define MAX_WAIT_BETWEEN_SESSIONS PR_SecondsToInterval(60 * 5) /* 5 minutes */
-
+/*
+ * Periodic synchronization interval. This is used for scheduling the periodic_dirsync event.
+ * The time is in milliseconds.
+ */
+#define PERIODIC_DIRSYNC_INTERVAL 5 * 60 * 1000 /* DBDB this should probably be configurable. 5 mins fixed for now */
/*
* tests if the protocol has been shutdown and we need to quit
* event_occurred resets the bits in the bit flag, so whoever tests for shutdown
@@ -161,8 +113,10 @@ static int windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *ruv);
static PRBool ignore_error_and_keep_going(int error);
static const char* state2name (int state);
static const char* event2name (int event);
-static const char* op2string (int op);
+static const char* acquire2name (int code);
+static void periodic_dirsync(time_t when, void *arg);
+static Slapi_Eq_Context dirsync;
/*
* It's specifically ok to delete a protocol instance that
* is currently running. The instance will be shut down, and
@@ -172,14 +126,18 @@ static const char* op2string (int op);
static void
windows_inc_delete(Private_Repl_Protocol **prpp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_delete\n", 0, 0, 0 );
/* First, stop the protocol if it isn't already stopped */
/* Then, delete all resources used by the protocol */
+ slapi_eq_cancel(dirsync);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_delete\n", 0, 0, 0 );
}
/* helper function */
void
w_set_pause_and_busy_time(long *pausetime, long *busywaittime)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> w_set_pause_and_busy_time\n", 0, 0, 0 );
/* If neither are set, set busy time to its default */
if (!*pausetime && !*busywaittime)
{
@@ -216,6 +174,7 @@ w_set_pause_and_busy_time(long *pausetime, long *busywaittime)
*/
*pausetime = *busywaittime + 1;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= w_set_pause_and_busy_time\n", 0, 0, 0 );
}
/*
@@ -267,435 +226,472 @@ w_set_pause_and_busy_time(long *pausetime, long *busywaittime)
static void
windows_inc_run(Private_Repl_Protocol *prp)
{
- int current_state = STATE_START;
- int next_state = STATE_START;
- windows_inc_private *prp_priv = (windows_inc_private *)prp->private;
- int done;
- int e1;
- RUV *ruv = NULL;
- CSN *cons_schema_csn;
- Replica *replica;
- int wait_change_timer_set = 0;
- time_t last_start_time;
- PRUint32 num_changes_sent;
- char *hostname = NULL;
- int portnum = 0;
- /* use a different backoff timer strategy for ACQUIRE_REPLICA_BUSY errors */
- PRBool use_busy_backoff_timer = PR_FALSE;
- long pausetime = 0;
- long busywaittime = 0;
-
- prp->stopped = 0;
- prp->terminate = 0;
- hostname = agmt_get_hostname(prp->agmt);
- portnum = agmt_get_port(prp->agmt);
-
- /* establish_protocol_callbacks(prp); */
- done = 0;
- do {
- int rc;
-
- /* Take action, based on current state, and compute new state. */
- switch (current_state)
- {
- case STATE_START:
-
- dev_debug("windows_inc_run(STATE_START)");
- if (PROTOCOL_IS_SHUTDOWN(prp))
- {
- done = 1;
- break;
- }
+ int current_state = STATE_START;
+ int next_state = STATE_START;
+ windows_inc_private *prp_priv = (windows_inc_private *)prp->private;
+ int done = 0;
+ int e1 = 0;
+ RUV *ruv = NULL;
+ Replica *replica = NULL;
+ int wait_change_timer_set = 0;
+ time_t last_start_time = 0;
+ PRUint32 num_changes_sent = 0;
+ char *hostname = NULL;
+ int portnum = 0;
+ /* use a different backoff timer strategy for ACQUIRE_REPLICA_BUSY errors */
+ PRBool use_busy_backoff_timer = PR_FALSE;
+ long pausetime = 0;
+ long busywaittime = 0;
+ // Some operations should only be done the first time STATE_START is true.
+ static PRBool is_first_start = PR_TRUE;
+
+ PRBool run_dirsync = PR_FALSE;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_run\n", 0, 0, 0 );
- /*
- * Our initial state. See if we're in a schedule window. If
- * so, then we're ready to acquire the replica and see if it
- * needs any updates from us. If not, then wait for the window
- * to open.
- */
- if (agmt_schedule_in_window_now(prp->agmt))
- {
- next_state = STATE_READY_TO_ACQUIRE;
- }
- else
- {
- next_state = STATE_WAIT_WINDOW_OPEN;
- }
+ prp->stopped = 0;
+ prp->terminate = 0;
+ hostname = agmt_get_hostname(prp->agmt);
+ portnum = agmt_get_port(prp->agmt);
- /* we can get here from other states because some events happened and were
- not cleared. For instance when we wake up in STATE_WAIT_CHANGES state.
- Since this is a fresh start state, we should clear all events */
- /* ONREPL - this does not feel right - we should take another look
- at this state machine */
- reset_events (prp);
-
- /* Cancel any linger timer that might be in effect... */
- windows_conn_cancel_linger(prp->conn);
- /* ... and disconnect, if currently connected */
- windows_conn_disconnect(prp->conn);
- /* get the new pause time, if any */
- pausetime = agmt_get_pausetime(prp->agmt);
- /* get the new busy wait time, if any */
- busywaittime = agmt_get_busywaittime(prp->agmt);
- if (pausetime || busywaittime)
- {
- /* helper function to make sure they are set correctly */
- w_set_pause_and_busy_time(&pausetime, &busywaittime);
- }
- break;
- case STATE_WAIT_WINDOW_OPEN:
- /*
- * We're waiting for a schedule window to open. If one did,
- * or we receive a "replicate now" event, then start a protocol
- * session immediately. If the replication schedule changed, go
- * back to start. Otherwise, go back to sleep.
- */
- dev_debug("windows_inc_run(STATE_WAIT_WINDOW_OPEN)");
- if (PROTOCOL_IS_SHUTDOWN(prp))
- {
- done = 1;
- break;
- }
- else if (event_occurred(prp, EVENT_WINDOW_OPENED))
- {
- next_state = STATE_READY_TO_ACQUIRE;
- }
- else if (event_occurred(prp, EVENT_REPLICATE_NOW))
- {
- next_state = STATE_READY_TO_ACQUIRE;
- }
- else if (event_occurred(prp, EVENT_AGMT_CHANGED))
- {
- next_state = STATE_START;
- windows_conn_set_agmt_changed(prp->conn);
- }
- else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET)) /* change available */
- {
- /* just ignore it and go to sleep */
- protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
- }
- else if (e1 = event_occurred(prp, EVENT_WINDOW_CLOSED) ||
- event_occurred(prp, EVENT_BACKOFF_EXPIRED))
- {
- /* this events - should not occur - log a warning and go to sleep */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "%s: Incremental protocol: "
- "event %s should not occur in state %s; going to sleep\n",
- agmt_get_long_name(prp->agmt),
- e1 ? event2name(EVENT_WINDOW_CLOSED) : event2name(EVENT_BACKOFF_EXPIRED),
- state2name(current_state));
- protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
- }
- else
- {
- /* wait until window opens or an event occurs */
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "%s: Incremental protocol: "
- "waiting for update window to open\n", agmt_get_long_name(prp->agmt));
- protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
- }
- break;
- case STATE_WAIT_CHANGES:
- /*
- * We're in a replication window, but we're waiting for more
- * changes to accumulate before we actually hook up and send
- * them.
- */
- dev_debug("windows_inc_run(STATE_WAIT_CHANGES)");
- if (PROTOCOL_IS_SHUTDOWN(prp))
- {
- dev_debug("windows_inc_run(STATE_WAIT_CHANGES): PROTOCOL_IS_SHUTING_DOWN -> end windows_inc_run\n");
- done = 1;
- break;
- }
- else if (event_occurred(prp, EVENT_REPLICATE_NOW))
- {
- dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_REPLICATE_NOW received -> STATE_READY_TO_ACQUIRE\n");
- next_state = STATE_READY_TO_ACQUIRE;
- wait_change_timer_set = 0;
- }
- else if (event_occurred(prp, EVENT_AGMT_CHANGED))
- {
- dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_AGMT_CHANGED received -> STATE_START\n");
- next_state = STATE_START;
- windows_conn_set_agmt_changed(prp->conn);
- wait_change_timer_set = 0;
- }
- else if (event_occurred(prp, EVENT_WINDOW_CLOSED))
- {
- dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_WINDOW_CLOSED received -> STATE_WAIT_WINDOW_OPEN\n");
- next_state = STATE_WAIT_WINDOW_OPEN;
- wait_change_timer_set = 0;
- }
- else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET))
- {
- dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_TRIGGERING_CRITERIA_MET received -> STATE_READY_TO_ACQUIRE\n");
- next_state = STATE_READY_TO_ACQUIRE;
- wait_change_timer_set = 0;
- }
- else if (e1 = event_occurred(prp, EVENT_WINDOW_OPENED) ||
- event_occurred(prp, EVENT_BACKOFF_EXPIRED))
- {
- /* this events - should not occur - log a warning and clear the event */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: "
- "event %s should not occur in state %s\n",
- agmt_get_long_name(prp->agmt),
- e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED),
- state2name(current_state));
- wait_change_timer_set = 0;
- }
- else
- {
- if (wait_change_timer_set)
- {
- /* We are here because our timer expired */
- dev_debug("windows_inc_run(STATE_WAIT_CHANGES): wait_change_timer_set expired -> STATE_START\n");
- next_state = STATE_START;
- wait_change_timer_set = 0;
- }
- else
+ windows_private_load_dirsync_cookie(prp->agmt);
+
+ do {
+ int rc = 0;
+
+ /* Take action, based on current state, and compute new state. */
+ switch (current_state)
{
- /* We are here because the last replication session
- * finished or aborted.
- */
- wait_change_timer_set = 1;
- protocol_sleep(prp, MAX_WAIT_BETWEEN_SESSIONS);
- }
- }
- break;
- case STATE_READY_TO_ACQUIRE:
-
- dev_debug("windows_inc_run(STATE_READY_TO_ACQUIRE)");
- if (PROTOCOL_IS_SHUTDOWN(prp))
- {
- done = 1;
- break;
- }
+ case STATE_START:
- /* ONREPL - at this state we unconditionally acquire the replica
- ignoring all events. Not sure if this is good */
- object_acquire(prp->replica_object);
- replica = object_get_data(prp->replica_object);
-
- rc = windows_acquire_replica(prp, &ruv);
+ dev_debug("windows_inc_run(STATE_START)");
+ if (PROTOCOL_IS_SHUTDOWN(prp))
+ {
+ done = 1;
+ break;
+ }
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "windows_acquire_replica returned %s (%d)\n",
- state2name(rc),
- rc);
+ /*
+ * Our initial state. See if we're in a schedule window. If
+ * so, then we're ready to acquire the replica and see if it
+ * needs any updates from us. If not, then wait for the window
+ * to open.
+ */
+ if (agmt_schedule_in_window_now(prp->agmt))
+ {
+ next_state = STATE_READY_TO_ACQUIRE;
+ } else
+ {
+ next_state = STATE_WAIT_WINDOW_OPEN;
+ }
- use_busy_backoff_timer = PR_FALSE; /* default */
- if (rc == ACQUIRE_SUCCESS)
- {
- next_state = STATE_SENDING_UPDATES;
- }
- else if (rc == ACQUIRE_REPLICA_BUSY)
- {
- next_state = STATE_BACKOFF_START;
- use_busy_backoff_timer = PR_TRUE;
- }
- else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE)
- {
- next_state = STATE_WAIT_CHANGES;
- }
- else if (rc == ACQUIRE_TRANSIENT_ERROR)
- {
- next_state = STATE_BACKOFF_START;
- }
- else if (rc == ACQUIRE_FATAL_ERROR)
- {
- next_state = STATE_STOP_FATAL_ERROR;
- }
- if (rc != ACQUIRE_SUCCESS)
- {
- int optype, ldaprc;
- windows_conn_get_error(prp->conn, &optype, &ldaprc);
- agmt_set_last_update_status(prp->agmt, ldaprc,
- prp->last_acquire_response_code, NULL);
- }
-
- object_release(prp->replica_object); replica = NULL;
- break;
- case STATE_BACKOFF_START:
- dev_debug("windows_inc_run(STATE_BACKOFF_START)");
- if (PROTOCOL_IS_SHUTDOWN(prp))
- {
- done = 1;
- break;
- }
- if (event_occurred(prp, EVENT_REPLICATE_NOW))
- {
- next_state = STATE_READY_TO_ACQUIRE;
- }
- else if (event_occurred(prp, EVENT_AGMT_CHANGED))
- {
- next_state = STATE_START;
- windows_conn_set_agmt_changed(prp->conn);
- }
- else if (event_occurred (prp, EVENT_WINDOW_CLOSED))
- {
- next_state = STATE_WAIT_WINDOW_OPEN;
- }
- else if (event_occurred (prp, EVENT_TRIGGERING_CRITERIA_MET))
- {
- /* consume and ignore */
- }
- else if (e1 = event_occurred (prp, EVENT_WINDOW_OPENED) ||
- event_occurred (prp, EVENT_BACKOFF_EXPIRED))
- {
- /* This should never happen */
- /* this events - should not occur - log a warning and go to sleep */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "%s: Incremental protocol: event %s should not occur in state %s\n",
- agmt_get_long_name(prp->agmt),
- e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED),
- state2name(current_state));
- }
- else
- {
- /* Set up the backoff timer to wake us up at the appropriate time */
- if (use_busy_backoff_timer)
- {
- /* we received a busy signal from the consumer, wait for a while */
- if (!busywaittime)
- {
- busywaittime = PROTOCOL_BUSY_BACKOFF_MINIMUM;
- }
- prp_priv->backoff = backoff_new(BACKOFF_FIXED, busywaittime,
- busywaittime);
- }
- else
- {
- prp_priv->backoff = backoff_new(BACKOFF_EXPONENTIAL, PROTOCOL_BACKOFF_MINIMUM,
- PROTOCOL_BACKOFF_MAXIMUM);
- }
- next_state = STATE_BACKOFF;
- backoff_reset(prp_priv->backoff, windows_inc_backoff_expired, (void *)prp);
- protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
- use_busy_backoff_timer = PR_FALSE;
- }
- break;
- case STATE_BACKOFF:
- /*
- * We're in a backoff state.
- */
- dev_debug("windows_inc_run(STATE_BACKOFF)");
- if (PROTOCOL_IS_SHUTDOWN(prp))
- {
- if (prp_priv->backoff)
- backoff_delete(&prp_priv->backoff);
- done = 1;
- break;
- }
- else if (event_occurred(prp, EVENT_REPLICATE_NOW))
- {
- next_state = STATE_READY_TO_ACQUIRE;
- }
- else if (event_occurred(prp, EVENT_AGMT_CHANGED))
- {
- next_state = STATE_START;
+ /* we can get here from other states because some events happened and were
+ not cleared. For instance when we wake up in STATE_WAIT_CHANGES state.
+ Since this is a fresh start state, we should clear all events */
+ /* ONREPL - this does not feel right - we should take another look
+ at this state machine */
+ reset_events (prp);
+
+ /* Cancel any linger timer that might be in effect... */
+ windows_conn_cancel_linger(prp->conn);
+ /* ... and disconnect, if currently connected */
+ windows_conn_disconnect(prp->conn);
+ /* get the new pause time, if any */
+ pausetime = agmt_get_pausetime(prp->agmt);
+ /* get the new busy wait time, if any */
+ busywaittime = agmt_get_busywaittime(prp->agmt);
+ if (pausetime || busywaittime)
+ {
+ /* helper function to make sure they are set correctly */
+ w_set_pause_and_busy_time(&pausetime, &busywaittime);
+ }
- windows_conn_set_agmt_changed(prp->conn);
- /* Destroy the backoff timer, since we won't need it anymore */
- if (prp_priv->backoff)
- backoff_delete(&prp_priv->backoff);
- }
- else if (event_occurred(prp, EVENT_WINDOW_CLOSED))
- {
- next_state = STATE_WAIT_WINDOW_OPEN;
- /* Destroy the backoff timer, since we won't need it anymore */
- if (prp_priv->backoff)
- backoff_delete(&prp_priv->backoff);
- }
- else if (event_occurred(prp, EVENT_BACKOFF_EXPIRED))
- {
- rc = windows_acquire_replica(prp, &ruv);
- use_busy_backoff_timer = PR_FALSE;
- if (rc == ACQUIRE_SUCCESS)
- {
- next_state = STATE_SENDING_UPDATES;
- }
- else if (rc == ACQUIRE_REPLICA_BUSY)
- {
- next_state = STATE_BACKOFF;
- use_busy_backoff_timer = PR_TRUE;
- }
- else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE)
- {
- next_state = STATE_WAIT_CHANGES;
- }
- else if (rc == ACQUIRE_TRANSIENT_ERROR)
- {
- next_state = STATE_BACKOFF;
- }
- else if (rc == ACQUIRE_FATAL_ERROR)
- {
- next_state = STATE_STOP_FATAL_ERROR;
- }
- if (rc != ACQUIRE_SUCCESS)
- {
- int optype, ldaprc;
- windows_conn_get_error(prp->conn, &optype, &ldaprc);
- agmt_set_last_update_status(prp->agmt, ldaprc,
- prp->last_acquire_response_code, NULL);
- }
+
+ if (is_first_start) {
+ /*
+ * The function, the arguments, the time (hence) when it is first to be called,
+ * and the repeat interval.
+ */
+ /* DBDB: we should probably make this polling interval configurable */
+ dirsync = slapi_eq_repeat(periodic_dirsync, (void*) prp, (time_t)0 , PERIODIC_DIRSYNC_INTERVAL);
+ is_first_start = PR_FALSE;
+ }
+ break;
+
+ case STATE_WAIT_WINDOW_OPEN:
/*
- * We either need to step the backoff timer, or
- * destroy it if we don't need it anymore.
+ * We're waiting for a schedule window to open. If one did,
+ * or we receive a "replicate now" event, then start a protocol
+ * session immediately. If the replication schedule changed, go
+ * back to start. Otherwise, go back to sleep.
*/
- if (STATE_BACKOFF == next_state)
- {
- time_t next_fire_time;
- time_t now;
- /* Step the backoff timer */
- time(&now);
- next_fire_time = backoff_step(prp_priv->backoff);
- /* And go back to sleep */
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "%s: Replication session backing off for %d seconds\n",
- agmt_get_long_name(prp->agmt),
- next_fire_time - now);
+ dev_debug("windows_inc_run(STATE_WAIT_WINDOW_OPEN)");
+ if (PROTOCOL_IS_SHUTDOWN(prp))
+ {
+ done = 1;
+ break;
+ }
+ else if (event_occurred(prp, EVENT_WINDOW_OPENED))
+ {
+ next_state = STATE_READY_TO_ACQUIRE;
+ }
+ else if (event_occurred(prp, EVENT_REPLICATE_NOW))
+ {
+ next_state = STATE_READY_TO_ACQUIRE;
+ }
+ else if (event_occurred(prp, EVENT_AGMT_CHANGED))
+ {
+ next_state = STATE_START;
+ run_dirsync = PR_TRUE;
+ windows_conn_set_agmt_changed(prp->conn);
+ }
+ else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET)) /* change available */
+ {
+ /* just ignore it and go to sleep */
+ protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
+ }
+ else if (e1 = event_occurred(prp, EVENT_WINDOW_CLOSED) ||
+ event_occurred(prp, EVENT_BACKOFF_EXPIRED))
+ {
+ /* this events - should not occur - log a warning and go to sleep */
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "%s: Incremental protocol: "
+ "event %s should not occur in state %s; going to sleep\n",
+ agmt_get_long_name(prp->agmt),
+ e1 ? event2name(EVENT_WINDOW_CLOSED) : event2name(EVENT_BACKOFF_EXPIRED),
+ state2name(current_state));
+ protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
+ }
+ else
+ {
+ /* wait until window opens or an event occurs */
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: Incremental protocol: "
+ "waiting for update window to open\n", agmt_get_long_name(prp->agmt));
+ protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
+ }
+ break;
- protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
- }
- else
- {
- /* Destroy the backoff timer, since we won't need it anymore */
- backoff_delete(&prp_priv->backoff);
- }
- use_busy_backoff_timer = PR_FALSE;
- }
- else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET))
- {
- /* changes are available */
- if ( prp_priv->backoff == NULL || backoff_expired (prp_priv->backoff, 60) )
- {
- /*
- * Have seen cases that the agmt stuck here forever since
- * somehow the backoff timer was not in event queue anymore.
- * If the backoff timer has expired more than 60 seconds,
- * destroy it.
- */
- if ( prp_priv->backoff )
- backoff_delete(&prp_priv->backoff);
- next_state = STATE_READY_TO_ACQUIRE;
- }
- else
- {
- /* ignore changes and go to sleep */
- protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
- }
- }
- else if (event_occurred(prp, EVENT_WINDOW_OPENED))
- {
- /* this should never happen - log an error and go to sleep */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: "
- "event %s should not occur in state %s; going to sleep\n",
- agmt_get_long_name(prp->agmt),
- event2name(EVENT_WINDOW_OPENED), state2name(current_state));
- protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
- }
- break;
+ case STATE_WAIT_CHANGES:
+ /*
+ * We're in a replication window, but we're waiting for more
+ * changes to accumulate before we actually hook up and send
+ * them.
+ */
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES)");
+ if (PROTOCOL_IS_SHUTDOWN(prp))
+ {
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES): PROTOCOL_IS_SHUTING_DOWN -> end windows_inc_run\n");
+ done = 1;
+ break;
+ }
+ else if (event_occurred(prp, EVENT_REPLICATE_NOW))
+ {
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_REPLICATE_NOW received -> STATE_READY_TO_ACQUIRE\n");
+ next_state = STATE_READY_TO_ACQUIRE;
+ wait_change_timer_set = 0;
+ /* We also want to run dirsync on a 'replicate now' event */
+ run_dirsync = PR_TRUE;
+ }
+ else if ( event_occurred(prp, EVENT_RUN_DIRSYNC))
+ {
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_REPLICATE_NOW received -> STATE_READY_TO_ACQUIRE\n");
+ next_state = STATE_READY_TO_ACQUIRE;
+ wait_change_timer_set = 0;
+ run_dirsync = PR_TRUE;
+
+ }
+ else if (event_occurred(prp, EVENT_AGMT_CHANGED))
+ {
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_AGMT_CHANGED received -> STATE_START\n");
+ next_state = STATE_START;
+ windows_conn_set_agmt_changed(prp->conn);
+ wait_change_timer_set = 0;
+ /* We also want to run dirsync on a 'agreement changed' event, because that's how we receive 'send updates now' */
+ run_dirsync = PR_TRUE;
+ }
+ else if (event_occurred(prp, EVENT_WINDOW_CLOSED))
+ {
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_WINDOW_CLOSED received -> STATE_WAIT_WINDOW_OPEN\n");
+ next_state = STATE_WAIT_WINDOW_OPEN;
+ wait_change_timer_set = 0;
+ }
+ else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET) )
+ {
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES): EVENT_TRIGGERING_CRITERIA_MET received -> STATE_READY_TO_ACQUIRE\n");
+ next_state = STATE_READY_TO_ACQUIRE;
+ wait_change_timer_set = 0;
+ }
+ else if (e1 = event_occurred(prp, EVENT_WINDOW_OPENED) ||
+ event_occurred(prp, EVENT_BACKOFF_EXPIRED))
+ {
+ /* this events - should not occur - log a warning and clear the event */
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: "
+ "event %s should not occur in state %s\n",
+ agmt_get_long_name(prp->agmt),
+ e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED),
+ state2name(current_state));
+ wait_change_timer_set = 0;
+ }
+ else
+ {
+ if (wait_change_timer_set)
+ {
+ /* We are here because our timer expired */
+ dev_debug("windows_inc_run(STATE_WAIT_CHANGES): wait_change_timer_set expired -> STATE_START\n");
+ next_state = STATE_START;
+ run_dirsync = PR_TRUE;
+ wait_change_timer_set = 0;
+ }
+ else
+ {
+ /* We are here because the last replication session
+ * finished or aborted.
+ */
+ wait_change_timer_set = 1;
+ protocol_sleep(prp, MAX_WAIT_BETWEEN_SESSIONS);
+ }
+ }
+ break;
+
+ case STATE_READY_TO_ACQUIRE:
+
+ dev_debug("windows_inc_run(STATE_READY_TO_ACQUIRE)");
+ if (PROTOCOL_IS_SHUTDOWN(prp))
+ {
+ done = 1;
+ break;
+ }
+
+ /* ONREPL - at this state we unconditionally acquire the replica
+ ignoring all events. Not sure if this is good */
+ object_acquire(prp->replica_object);
+ replica = object_get_data(prp->replica_object);
+
+ rc = windows_acquire_replica(prp, &ruv , 1 /* yes, check the consumer RUV for incremental */);
+
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "windows_acquire_replica returned %s (%d)\n",
+ acquire2name(rc),
+ rc);
+
+ use_busy_backoff_timer = PR_FALSE; /* default */
+ if (rc == ACQUIRE_SUCCESS)
+ {
+ next_state = STATE_SENDING_UPDATES;
+ }
+ else if (rc == ACQUIRE_REPLICA_BUSY)
+ {
+ next_state = STATE_BACKOFF_START;
+ use_busy_backoff_timer = PR_TRUE;
+ }
+ else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE)
+ {
+ next_state = STATE_WAIT_CHANGES;
+
+ }
+ else if (rc == ACQUIRE_TRANSIENT_ERROR)
+ {
+ next_state = STATE_BACKOFF_START;
+ }
+ else if (rc == ACQUIRE_FATAL_ERROR)
+ {
+ next_state = STATE_STOP_FATAL_ERROR;
+ }
+ if (rc != ACQUIRE_SUCCESS)
+ {
+ int optype, ldaprc;
+ windows_conn_get_error(prp->conn, &optype, &ldaprc);
+ agmt_set_last_update_status(prp->agmt, ldaprc,
+ prp->last_acquire_response_code, NULL);
+ }
+
+ object_release(prp->replica_object); replica = NULL;
+ break;
+
+ case STATE_BACKOFF_START:
+ dev_debug("windows_inc_run(STATE_BACKOFF_START)");
+ if (PROTOCOL_IS_SHUTDOWN(prp))
+ {
+ done = 1;
+ break;
+ }
+ if (event_occurred(prp, EVENT_REPLICATE_NOW) || event_occurred(prp, EVENT_RUN_DIRSYNC))
+ {
+ next_state = STATE_READY_TO_ACQUIRE;
+ }
+ else if (event_occurred(prp, EVENT_AGMT_CHANGED))
+ {
+ next_state = STATE_START;
+ run_dirsync = PR_TRUE; /* Also trigger dirsync for the 'send updates now' feature */
+ windows_conn_set_agmt_changed(prp->conn);
+ }
+ else if (event_occurred (prp, EVENT_WINDOW_CLOSED))
+ {
+ next_state = STATE_WAIT_WINDOW_OPEN;
+ }
+ else if (event_occurred (prp, EVENT_TRIGGERING_CRITERIA_MET))
+ {
+ /* consume and ignore */
+ }
+ else if (e1 = event_occurred (prp, EVENT_WINDOW_OPENED) ||
+ event_occurred (prp, EVENT_BACKOFF_EXPIRED))
+ {
+ /* This should never happen */
+ /* this events - should not occur - log a warning and go to sleep */
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "%s: Incremental protocol: event %s should not occur in state %s\n",
+ agmt_get_long_name(prp->agmt),
+ e1 ? event2name(EVENT_WINDOW_OPENED) : event2name(EVENT_BACKOFF_EXPIRED),
+ state2name(current_state));
+ }
+ else
+ {
+ /* Set up the backoff timer to wake us up at the appropriate time */
+ if (use_busy_backoff_timer)
+ {
+ /* we received a busy signal from the consumer, wait for a while */
+ if (!busywaittime)
+ {
+ busywaittime = PROTOCOL_BUSY_BACKOFF_MINIMUM;
+ }
+ prp_priv->backoff = backoff_new(BACKOFF_FIXED, busywaittime,
+ busywaittime);
+ }
+ else
+ {
+ prp_priv->backoff = backoff_new(BACKOFF_EXPONENTIAL, PROTOCOL_BACKOFF_MINIMUM,
+ PROTOCOL_BACKOFF_MAXIMUM);
+ }
+ next_state = STATE_BACKOFF;
+ backoff_reset(prp_priv->backoff, windows_inc_backoff_expired, (void *)prp);
+ protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
+ use_busy_backoff_timer = PR_FALSE;
+ }
+ break;
+
+ case STATE_BACKOFF:
+ /*
+ * We're in a backoff state.
+ */
+ dev_debug("windows_inc_run(STATE_BACKOFF)");
+ if (PROTOCOL_IS_SHUTDOWN(prp))
+ {
+ if (prp_priv->backoff)
+ backoff_delete(&prp_priv->backoff);
+ done = 1;
+ break;
+ }
+ else if (event_occurred(prp, EVENT_REPLICATE_NOW) || event_occurred(prp, EVENT_RUN_DIRSYNC))
+ {
+ next_state = STATE_READY_TO_ACQUIRE;
+ }
+ else if (event_occurred(prp, EVENT_AGMT_CHANGED))
+ {
+ next_state = STATE_START;
+ run_dirsync = PR_TRUE;
+
+ windows_conn_set_agmt_changed(prp->conn);
+ /* Destroy the backoff timer, since we won't need it anymore */
+ if (prp_priv->backoff)
+ backoff_delete(&prp_priv->backoff);
+ }
+ else if (event_occurred(prp, EVENT_WINDOW_CLOSED))
+ {
+ next_state = STATE_WAIT_WINDOW_OPEN;
+ /* Destroy the backoff timer, since we won't need it anymore */
+ if (prp_priv->backoff)
+ backoff_delete(&prp_priv->backoff);
+ }
+ else if (event_occurred(prp, EVENT_BACKOFF_EXPIRED))
+ {
+ rc = windows_acquire_replica(prp, &ruv, 1 /* check RUV for incremental */);
+ use_busy_backoff_timer = PR_FALSE;
+ if (rc == ACQUIRE_SUCCESS)
+ {
+ next_state = STATE_SENDING_UPDATES;
+ }
+ else if (rc == ACQUIRE_REPLICA_BUSY)
+ {
+ next_state = STATE_BACKOFF;
+ use_busy_backoff_timer = PR_TRUE;
+ }
+ else if (rc == ACQUIRE_CONSUMER_WAS_UPTODATE)
+ {
+ next_state = STATE_WAIT_CHANGES;
+ }
+ else if (rc == ACQUIRE_TRANSIENT_ERROR)
+ {
+ next_state = STATE_BACKOFF;
+ }
+ else if (rc == ACQUIRE_FATAL_ERROR)
+ {
+ next_state = STATE_STOP_FATAL_ERROR;
+ }
+ if (rc != ACQUIRE_SUCCESS)
+ {
+ int optype, ldaprc;
+ windows_conn_get_error(prp->conn, &optype, &ldaprc);
+ agmt_set_last_update_status(prp->agmt, ldaprc,
+ prp->last_acquire_response_code, NULL);
+ }
+ /*
+ * We either need to step the backoff timer, or
+ * destroy it if we don't need it anymore.
+ */
+ if (STATE_BACKOFF == next_state)
+ {
+ time_t next_fire_time;
+ time_t now;
+ /* Step the backoff timer */
+ time(&now);
+ next_fire_time = backoff_step(prp_priv->backoff);
+ /* And go back to sleep */
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "%s: Replication session backing off for %d seconds\n",
+ agmt_get_long_name(prp->agmt),
+ next_fire_time - now);
+
+ protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
+ }
+ else
+ {
+ /* Destroy the backoff timer, since we won't need it anymore */
+ backoff_delete(&prp_priv->backoff);
+ }
+ use_busy_backoff_timer = PR_FALSE;
+ }
+ else if (event_occurred(prp, EVENT_TRIGGERING_CRITERIA_MET))
+ {
+ /* changes are available */
+ if ( prp_priv->backoff == NULL || backoff_expired (prp_priv->backoff, 60) )
+ {
+ /*
+ * Have seen cases that the agmt stuck here forever since
+ * somehow the backoff timer was not in event queue anymore.
+ * If the backoff timer has expired more than 60 seconds,
+ * destroy it.
+ */
+ if ( prp_priv->backoff )
+ backoff_delete(&prp_priv->backoff);
+ next_state = STATE_READY_TO_ACQUIRE;
+ }
+ else
+ {
+ /* ignore changes and go to sleep */
+ protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
+ }
+ }
+ else if (event_occurred(prp, EVENT_WINDOW_OPENED))
+ {
+ /* this should never happen - log an error and go to sleep */
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: Incremental protocol: "
+ "event %s should not occur in state %s; going to sleep\n",
+ agmt_get_long_name(prp->agmt),
+ event2name(EVENT_WINDOW_OPENED), state2name(current_state));
+ protocol_sleep(prp, PR_INTERVAL_NO_TIMEOUT);
+ }
+ break;
case STATE_SENDING_UPDATES:
dev_debug("windows_inc_run(STATE_SENDING_UPDATES)");
agmt_set_update_in_progress(prp->agmt, PR_TRUE);
@@ -724,29 +720,6 @@ windows_inc_run(Private_Repl_Protocol *prp)
agmt_set_last_update_status(prp->agmt, 0, 0, "Incremental update started");
- /* ONREPL - in this state we send changes no matter what other events occur.
- This is because we can get because of the REPLICATE_NOW event which
- has high priority. Is this ok? */
- /* First, push new schema to the consumer if needed */
- /* ONREPL - should we push schema after we examine the RUV? */
- /*
- * GGOOREPL - I don't see why we should wait until we've
- * examined the RUV. The schema entry has its own CSN that is
- * used to decide if the remote schema needs to be updated.
- */
- cons_schema_csn = agmt_get_consumer_schema_csn ( prp->agmt );
- // rc = windows_conn_push_schema(prp->conn, &cons_schema_csn); XXX
- if ( cons_schema_csn != agmt_get_consumer_schema_csn ( prp->agmt ))
- {
- agmt_set_consumer_schema_csn ( prp->agmt, cons_schema_csn );
- }
- if (CONN_SCHEMA_UPDATED != rc && CONN_SCHEMA_NO_UPDATE_NEEDED != rc)
- {
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "%s: Warning: unable to replicate schema: rc=%d\n",
- agmt_get_long_name(prp->agmt), rc);
- /* But keep going */
- }
dev_debug("windows_inc_run(STATE_SENDING_UPDATES) -> windows_examine_update_vector");
rc = windows_examine_update_vector(prp, ruv);
/*
@@ -842,10 +815,14 @@ windows_inc_run(Private_Repl_Protocol *prp)
last_start_time = 0UL;
break;
}
-/* if (NULL != ruv)
- {
- ruv_destroy(&ruv); ruv = NULL;
- } XXX elliot commented this out */
+
+ if ( run_dirsync )
+ {
+ windows_dirsync_inc_run(prp);
+ windows_private_save_dirsync_cookie(prp->agmt);
+ run_dirsync = PR_FALSE;
+ }
+
agmt_set_last_update_end(prp->agmt, current_time());
agmt_set_update_in_progress(prp->agmt, PR_FALSE);
/* If timed out, close the connection after released the replica */
@@ -882,7 +859,6 @@ windows_inc_run(Private_Repl_Protocol *prp)
/* DS_Sleep ( PR_SecondsToInterval(1) ); */
}
}
- windows_dirsync_inc_run(prp);
break;
case STATE_STOP_FATAL_ERROR:
@@ -960,6 +936,7 @@ windows_inc_run(Private_Repl_Protocol *prp)
conn_cancel_linger(prp->conn);
/* ... and disconnect, if currently connected */
conn_disconnect(prp->conn);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_run\n", 0, 0, 0 );
}
@@ -970,6 +947,7 @@ windows_inc_run(Private_Repl_Protocol *prp)
static void
protocol_sleep(Private_Repl_Protocol *prp, PRIntervalTime duration)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> protocol_sleep\n", 0, 0, 0 );
PR_ASSERT(NULL != prp);
PR_Lock(prp->lock);
/* we should not go to sleep if there are events available to be processed.
@@ -983,6 +961,7 @@ protocol_sleep(Private_Repl_Protocol *prp, PRIntervalTime duration)
agmt_get_long_name(prp->agmt), prp->eventbits);
}
PR_Unlock(prp->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= protocol_sleep\n", 0, 0, 0 );
}
@@ -995,11 +974,13 @@ protocol_sleep(Private_Repl_Protocol *prp, PRIntervalTime duration)
static void
event_notify(Private_Repl_Protocol *prp, PRUint32 event)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> event_notify\n", 0, 0, 0 );
PR_ASSERT(NULL != prp);
PR_Lock(prp->lock);
prp->eventbits |= event;
PR_NotifyCondVar(prp->cvar);
PR_Unlock(prp->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= event_notify\n", 0, 0, 0 );
}
@@ -1011,187 +992,36 @@ static PRUint32
event_occurred(Private_Repl_Protocol *prp, PRUint32 event)
{
PRUint32 return_value;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> event_occurred\n", 0, 0, 0 );
+
PR_ASSERT(NULL != prp);
PR_Lock(prp->lock);
return_value = (prp->eventbits & event);
prp->eventbits &= ~event; /* Clear event */
PR_Unlock(prp->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= event_occurred\n", 0, 0, 0 );
return return_value;
}
static void
reset_events (Private_Repl_Protocol *prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> reset_events\n", 0, 0, 0 );
PR_ASSERT(NULL != prp);
PR_Lock(prp->lock);
prp->eventbits = 0;
PR_Unlock(prp->lock);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= reset_events\n", 0, 0, 0 );
}
-/*
- * Replay the actual update to the consumer. Construct an appropriate LDAP
- * operation, attach the baggage LDAPv3 control that contains the CSN, etc.,
- * and send the operation to the consumer.
- */
-ConnResult
-w_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op)
-{
- ConnResult return_value;
- LDAPControl *update_control = NULL;
- char csn_str[CSN_STRSIZE]; /* For logging only */
- char *old_dn;
- char *password = NULL;
-
- old_dn = slapi_ch_strdup(op->target_address.dn);
-
- csn_as_string(op->csn, PR_FALSE, csn_str);
-
- if ( windows_private_get_windows_replarea(prp->agmt) && windows_private_get_directory_replarea(prp->agmt) )
- {
- Slapi_DN *sdn;
-
- sdn = slapi_sdn_new_dn_passin( op->target_address.dn );
- sdn = map_dn_user(sdn, REPLICA_TYPE_WINDOWS, windows_private_get_windows_replarea( prp->agmt) );
-
- op->target_address.dn = slapi_ch_strdup(slapi_sdn_get_ndn(sdn));
-
- }
-
- /* Construct the replication info control that accompanies the operation */
- if (SLAPI_OPERATION_ADD == op->operation_type)
- {
-
- map_entry_user(&(op->p.p_add.target_entry), REPLICA_TYPE_WINDOWS, &password);
-
-
- }
- else if (SLAPI_OPERATION_MODRDN == op->operation_type)
- {
- /* op->p.p_modrdn.modrdn_newrdn needs to change from
- uid=fbar to cn=fbar */
-
-
- }
- else if (SLAPI_OPERATION_MODIFY == op->operation_type)
- {
- alter_mods(& op->p.p_modify.modify_mods, &password) ;
- /* if the entry already exists, modify_mods will be null.
- attempting to modifiy null will return LDAP_PARAM_ERROR.
- The password still might be set. bail */
- if ( op->p.p_modify.modify_mods == NULL)
- {
- return_value = CONN_OPERATION_SUCCESS;
- goto skipchange;
- }
-
- }
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "%s: replay_update: Sending %s operation (dn=\"%s\" csn=%s)\n",
- agmt_get_long_name(prp->agmt),
- op2string(op->operation_type), op->target_address.dn, csn_str);
- /* What type of operation is it? */
- switch (op->operation_type)
- {
- case SLAPI_OPERATION_ADD:
- {
- LDAPMod **entryattrs;
- /* Convert entry to mods */
- (void)slapi_entry2mods (op->p.p_add.target_entry,
- NULL /* &entrydn : We don't need it */,
- &entryattrs);
- if (NULL == entryattrs)
- {
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "%s: replay_update: Cannot convert entry to LDAPMods.\n",
- agmt_get_long_name(prp->agmt));
- return_value = CONN_LOCAL_ERROR;
- }
- else
- {
- return_value = windows_conn_send_add(prp->conn, op->target_address.dn,
- entryattrs, update_control, NULL /* returned controls */);
- ldap_mods_free(entryattrs, 1);
- }
- break;
- }
- case SLAPI_OPERATION_MODIFY:
- return_value = windows_conn_send_modify(prp->conn, op->target_address.dn,
- op->p.p_modify.modify_mods, update_control,
- NULL /* returned controls */);
- break;
- case SLAPI_OPERATION_DELETE:
- return_value = windows_conn_send_delete(prp->conn, op->target_address.dn,
- update_control, NULL /* returned controls */);
- break;
- case SLAPI_OPERATION_MODRDN:
- /* XXXggood need to pass modrdn mods in update control! */
- return_value = windows_conn_send_rename(prp->conn, op->target_address.dn,
- op->p.p_modrdn.modrdn_newrdn,
- op->p.p_modrdn.modrdn_newsuperior_address.dn,
- op->p.p_modrdn.modrdn_deloldrdn,
- update_control, NULL /* returned controls */);
- break;
- default:
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: replay_update: Unknown "
- "operation type %d found in changelog - skipping change.\n",
- agmt_get_long_name(prp->agmt), op->operation_type);
- }
-
-skipchange:
- if (NULL != password)
- { /* this entry had a password, handle it seperately */
- /* http://support.microsoft.com/?kbid=269190 */
-
- int pw_return;
- LDAPMod *pw_mods[2];
- LDAPMod pw_mod;
-
- char *pw[2];
- pw[0] = password;
- pw[1] = NULL;
-
- pw_mod.mod_type = "UnicodePwd";
- pw_mod.mod_op = LDAP_MOD_REPLACE;
- pw_mod.mod_values = pw;
-
- pw_mods[0] = &pw_mod;
- pw_mods[1] = NULL;
-
-
- pw_return = windows_conn_send_modify(prp->conn, op->target_address.dn,
- pw_mods, NULL, NULL );
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "%s: replay_update: update password returned %d\n",
- agmt_get_long_name(prp->agmt), pw_return );
-
-
- // slapi_ch_free((void**) &password);
-
- }
-
- /* XXX
- what else should be 'ignored' here?. and in which cases?
- Or should this go in a different part of the file? */
- if ( CONN_OPERATION_SUCCESS == return_value )
- {
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "%s: replay_update: Consumer successfully replayed operation with csn %s\n",
- agmt_get_long_name(prp->agmt), csn_str);
- }
- else
- {
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "%s: replay_update: Consumer could not replay operation with csn %s\n",
- agmt_get_long_name(prp->agmt), csn_str);
- }
- return return_value;
-}
static PRBool
is_dummy_operation (const slapi_operation_parameters *op)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> is_dummy_operation\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= is_dummy_operation\n", 0, 0, 0 );
return (strcmp (op->target_address.uniqueid, START_ITERATION_ENTRY_UNIQUEID) == 0);
}
@@ -1200,6 +1030,7 @@ is_dummy_operation (const slapi_operation_parameters *op)
void
w_cl5_operation_parameters_done (struct slapi_operation_parameters *sop)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> w_cl5_operation_parameters_done\n", 0, 0, 0 );
if(sop!=NULL) {
switch(sop->operation_type)
{
@@ -1234,7 +1065,7 @@ w_cl5_operation_parameters_done (struct slapi_operation_parameters *sop)
}
}
operation_parameters_done(sop);
-
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= w_cl5_operation_parameters_done\n", 0, 0, 0 );
}
@@ -1258,6 +1089,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
int rc;
CL5ReplayIterator *changelog_iterator = NULL;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> send_updates\n", 0, 0, 0 );
+
*num_changes_sent = 0;
/*
* Iterate over the changelog. Retrieve each update,
@@ -1265,8 +1098,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
* attaching the CSN, and send the change.
*/
- //rc = cl5CreateReplayIterator( prp, remote_update_vector, &changelog_iterator); // XXX fixme
- rc = cl5CreateReplayIteratorEx( prp, remote_update_vector, &changelog_iterator, agmt_get_consumerRID(prp->agmt)); // XXX fixme
+
+ rc = cl5CreateReplayIteratorEx( prp, remote_update_vector, &changelog_iterator, agmt_get_consumerRID(prp->agmt));
if (CL5_SUCCESS != rc)
{
switch (rc)
@@ -1388,7 +1221,8 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
agmt_get_long_name(prp->agmt), csn_as_string(entry.op->csn, PR_FALSE, csn_str));
continue;
}
- replay_crc = w_replay_update(prp, entry.op);
+ /* This is where the work actually happens: */
+ replay_crc = windows_replay_update(prp, entry.op);
if (CONN_OPERATION_SUCCESS != replay_crc)
{
int operation, error;
@@ -1459,6 +1293,9 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
/* Positive response received */
(*num_changes_sent)++;
agmt_inc_last_update_changecount (prp->agmt, csn_get_replicaid(entry.op->csn), 0 /*replayed*/);
+
+ /* bring the consumers (AD) RUV up to date */
+ /* DBDB removed because it breaks server startup ruv_set_max_csn(remote_update_vector,entry.op->csn, NULL ); */
}
break;
case CL5_BAD_DATA:
@@ -1515,6 +1352,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
w_cl5_operation_parameters_done ( entry.op );
cl5DestroyReplayIterator(&changelog_iterator);
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= send_updates\n", 0, 0, 0 );
return return_value;
}
@@ -1531,6 +1369,8 @@ windows_inc_stop(Private_Repl_Protocol *prp)
PRIntervalTime start, maxwait, now;
int seconds = 1200;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_stop\n", 0, 0, 0 );
+
maxwait = PR_SecondsToInterval(seconds);
prp->terminate = 1;
event_notify(prp, EVENT_PROTOCOL_SHUTDOWN);
@@ -1557,6 +1397,7 @@ windows_inc_stop(Private_Repl_Protocol *prp)
agmt_get_long_name(prp->agmt),
PR_IntervalToSeconds(now-start));
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_stop\n", 0, 0, 0 );
return return_value;
}
@@ -1567,6 +1408,10 @@ windows_inc_status(Private_Repl_Protocol *prp)
{
int return_value = 0;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_status\n", 0, 0, 0 );
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_status\n", 0, 0, 0 );
+
return return_value;
}
@@ -1575,40 +1420,54 @@ windows_inc_status(Private_Repl_Protocol *prp)
static void
windows_inc_notify_update(Private_Repl_Protocol *prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_update\n", 0, 0, 0 );
event_notify(prp, EVENT_TRIGGERING_CRITERIA_MET);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_update\n", 0, 0, 0 );
}
static void
windows_inc_update_now(Private_Repl_Protocol *prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_update_now\n", 0, 0, 0 );
event_notify(prp, EVENT_REPLICATE_NOW);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_update_now\n", 0, 0, 0 );
}
static void
windows_inc_notify_agmt_changed(Private_Repl_Protocol *prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_agmt_changed\n", 0, 0, 0 );
event_notify(prp, EVENT_AGMT_CHANGED);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_agmt_changed\n", 0, 0, 0 );
}
static void
windows_inc_notify_window_opened (Private_Repl_Protocol *prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_window_opened\n", 0, 0, 0 );
event_notify(prp, EVENT_WINDOW_OPENED);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_window_opened\n", 0, 0, 0 );
}
static void
windows_inc_notify_window_closed (Private_Repl_Protocol *prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_notify_window_closed\n", 0, 0, 0 );
event_notify(prp, EVENT_WINDOW_CLOSED);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_notify_window_closed\n", 0, 0, 0 );
}
+
Private_Repl_Protocol *
Windows_Inc_Protocol_new(Repl_Protocol *rp)
{
windows_inc_private *rip = NULL;
Private_Repl_Protocol *prp = (Private_Repl_Protocol *)slapi_ch_malloc(sizeof(Private_Repl_Protocol));
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> Windows_Inc_Protocol_new\n", 0, 0, 0 );
+
prp->delete = windows_inc_delete;
prp->run = windows_inc_run;
prp->stop = windows_inc_stop;
@@ -1639,9 +1498,14 @@ Windows_Inc_Protocol_new(Repl_Protocol *rp)
rip->rp = rp;
prp->private = (void *)rip;
prp->replica_acquired = PR_FALSE;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= Windows_Inc_Protocol_new\n", 0, 0, 0 );
+
return prp;
+
loser:
windows_inc_delete(&prp);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= Windows_Inc_Protocol_new (loser)\n", 0, 0, 0 );
return NULL;
}
@@ -1652,8 +1516,13 @@ static void
windows_inc_backoff_expired(time_t timer_fire_time, void *arg)
{
Private_Repl_Protocol *prp = (Private_Repl_Protocol *)arg;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_inc_backoff_expired\n", 0, 0, 0 );
+
PR_ASSERT(NULL != prp);
event_notify(prp, EVENT_BACKOFF_EXPIRED);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_inc_backoff_expired\n", 0, 0, 0 );
}
@@ -1679,6 +1548,8 @@ windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *remote_ruv)
{
int return_value;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_examine_update_vector\n", 0, 0, 0 );
+
PR_ASSERT(NULL != prp);
if (NULL == prp)
{
@@ -1718,6 +1589,7 @@ windows_examine_update_vector(Private_Repl_Protocol *prp, RUV *remote_ruv)
slapi_ch_free((void**)&remote_gen);
slapi_ch_free((void**)&local_gen);
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_examine_update_vector\n", 0, 0, 0 );
return return_value;
}
@@ -1742,6 +1614,8 @@ ignore_error_and_keep_going(int error)
{
int return_value;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ignore_error_and_keep_going\n", 0, 0, 0 );
+
switch (error)
{
/* Cases where we keep going */
@@ -1811,13 +1685,32 @@ ignore_error_and_keep_going(int error)
return_value = PR_FALSE;
break;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ignore_error_and_keep_going\n", 0, 0, 0 );
return return_value;
}
+/* this function converts an aquisition code to a string - for debug output */
+static const char*
+acquire2name (int code)
+{
+ switch (code)
+ {
+ case ACQUIRE_SUCCESS: return "success";
+ case ACQUIRE_REPLICA_BUSY: return "replica_busy";
+ case ACQUIRE_FATAL_ERROR: return "fatal_error";
+ case ACQUIRE_CONSUMER_WAS_UPTODATE: return "consumer_was_uptodate";
+ case ACQUIRE_TRANSIENT_ERROR: return "transient_error";
+ default: return "invalid_code";
+ }
+}
+
+
/* this function converts a state to its name - for debug output */
static const char*
state2name (int state)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> state2name\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= state2name\n", 0, 0, 0 );
switch (state)
{
case STATE_START: return "start";
@@ -1838,6 +1731,8 @@ state2name (int state)
static const char*
event2name (int event)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> event2name\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= event2name\n", 0, 0, 0 );
switch (event)
{
case EVENT_WINDOW_OPENED: return "update_window_opened";
@@ -1847,763 +1742,20 @@ event2name (int event)
case EVENT_REPLICATE_NOW: return "replicate_now";
case EVENT_PROTOCOL_SHUTDOWN: return "protocol_shutdown";
case EVENT_AGMT_CHANGED: return "agreement_changed";
+ case EVENT_RUN_DIRSYNC: return "run_dirsync";
default: return "invalid_event";
}
}
-static const char*
-op2string(int op)
-{
- switch (op) {
- case SLAPI_OPERATION_ADD:
- return "add";
- case SLAPI_OPERATION_MODIFY:
- return "modify";
- case SLAPI_OPERATION_DELETE:
- return "delete";
- case SLAPI_OPERATION_MODRDN:
- return "rename";
- case SLAPI_OPERATION_EXTENDED:
- return "extended";
- }
-
- return "unknown";
-}
-
-
-
-void map_entry_user(Slapi_Entry **e, int map_to, char** password) {
- /* do schema changes */
-
- Slapi_Entry *new_entry;
- Slapi_Attr *a;
- Slapi_Attr **attr = &a;
- Slapi_Attr *prevattr = NULL;
- int rc;
- char* ldif = ""; /* for debugging only */
- int ldif_len=0; /* for debugging only */
-
- a = slapi_attr_new();
-
- new_entry = slapi_entry_alloc();
-
-
- rc =slapi_entry_first_attr( *e, attr );
-
- while (rc == 0)
- {
- char* attr_type;
- Slapi_Value *old_value;
- int i=-1;
- int ret = 0;
- slapi_attr_get_type(*attr, &attr_type);
-
-
- while ( mapping[++i].old_name != NULL)
- {
-
-
- if ((mapping[i].map_to == map_to) && strcasecmp(attr_type, mapping[i].old_name) == 0 )
- {
-
- slapi_attr_first_value( *attr, &old_value);
- slapi_entry_add_value (new_entry, mapping[i].new_name, old_value);
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "translate_attrib \n\t%s\n\t%s\n", mapping[i].old_name, mapping[i].new_name);
-
- }
-
- }
-
- if ((map_to == REPLICA_TYPE_WINDOWS) && (
- slapi_attr_type_cmp(attr_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD , 1) == 0))
- {
- int b;
- const char* pw;
- pw = slapi_value_get_string(old_value);
-
- *password = (char*) slapi_ch_malloc(strlen( pw ) + 3); /* "%s"\0 */
- b = sprintf(*password, "\"%s\"", pw);
-
- }
-
-
- if (mapping[i].old_name != NULL) {
- slapi_attr_first_value( *attr, &old_value);
- ret = slapi_entry_add_value (new_entry, mapping[i].new_name, old_value);
- }
-
- prevattr = *attr;
- rc = slapi_entry_next_attr( *e, prevattr, attr );
-
- }
- /* replace the existing entry with our duplicate */
- {
- char *ad_objectclass[] = {"top", "person", "organizationalperson", "user", NULL};
- char *ds_objectclass[] = {"top", "person", "organizationalperson", "inetorgperson", "ntuser", NULL};
-
- Slapi_ValueSet *vs = slapi_valueset_new();
- Slapi_Value * addval;
- int j = -1;
-
- if (map_to == REPLICA_TYPE_WINDOWS) {
-
- while (ad_objectclass[++j]!= NULL)
- {
- addval = slapi_value_new_string(ad_objectclass[j]);
- slapi_valueset_add_value(vs,addval);
- slapi_value_free(&addval);
- }
- }
- else
- {
- while (ds_objectclass[++j]!= NULL)
- {
- addval = slapi_value_new_string(ds_objectclass[j]);
- slapi_valueset_add_value(vs,addval);
- slapi_value_free(&addval);
- }
- }
-
- slapi_entry_add_valueset(new_entry,"objectclass", vs);
- slapi_valueset_free(vs);
-
- }
-
- /*
- ldif = slapi_entry2str( *e, &ldif_len );
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(*e), ldif);
- ldif = slapi_entry2str( new_entry, &ldif_len );
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(new_entry), ldif);
- slapi_ch_free_string(&ldif);
-*/
-
-
- *e = slapi_entry_dup( new_entry );
-
-}
-
-
-void map_entry_group(Slapi_Entry **e, int map_to) {
- /* do schema changes */
-
- Slapi_Entry *new_entry;
- Slapi_Attr *a;
- Slapi_Attr **attr = &a;
- Slapi_Attr *prevattr = NULL;
- int rc;
- char* ldif = ""; /* for debugging only */
- int ldif_len=0; /* for debugging only */
-
- a = slapi_attr_new();
-
- new_entry = slapi_entry_alloc();
-
-
- rc =slapi_entry_first_attr( *e, attr );
-
- while (rc == 0)
- {
- char* attr_type;
- Slapi_Value *old_value;
- int i=-1;
- int ret = 0;
- slapi_attr_get_type(*attr, &attr_type);
-
-
- while ( group_map[++i].old_name != NULL)
- {
-
-
- if ((group_map[i].map_to == map_to) && strcasecmp(attr_type, group_map[i].old_name) == 0 )
- {
-
- slapi_attr_first_value( *attr, &old_value);
- slapi_entry_add_value (new_entry, group_map[i].new_name, old_value);
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "translate_attrib \n\t%s\n\t%s\n", group_map[i].old_name, group_map[i].new_name);
-
- }
-
- }
-
- if (group_map[i].old_name != NULL) {
- slapi_attr_first_value( *attr, &old_value);
- ret = slapi_entry_add_value (new_entry, group_map[i].new_name, old_value);
- }
-
- prevattr = *attr;
- rc = slapi_entry_next_attr( *e, prevattr, attr );
-
- }
- /* replace the existing entry with our duplicate */
- {
- char *ad_objectclass[] = {"top", "group", NULL};
- char *ds_objectclass[] = {"top", "ntGroup", NULL};
-
- Slapi_ValueSet *vs = slapi_valueset_new();
- Slapi_Value * addval;
- int j = -1;
-
- if (map_to == REPLICA_TYPE_WINDOWS) {
-
- while (ad_objectclass[++j]!= NULL)
- {
- addval = slapi_value_new_string(ad_objectclass[j]);
- slapi_valueset_add_value(vs,addval);
- slapi_value_free(&addval);
- }
- }
- else
- {
- while (ds_objectclass[++j]!= NULL)
- {
- addval = slapi_value_new_string(ds_objectclass[j]);
- slapi_valueset_add_value(vs,addval);
- slapi_value_free(&addval);
- }
- }
-
- slapi_entry_add_valueset(new_entry,"objectclass", vs);
- slapi_valueset_free(vs);
-
- }
-
-
- ldif = slapi_entry2str( *e, &ldif_len );
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(*e), ldif);
- ldif = slapi_entry2str( new_entry, &ldif_len );
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "found entry %s from windows:\n%s\n", slapi_entry_get_ndn(new_entry), ldif);
- slapi_ch_free_string(&ldif);
-
-
-
- *e = slapi_entry_dup( new_entry );
-
-}
-
-static Slapi_DN* map_dn_user(Slapi_DN *sdn, int map_to, const Slapi_DN *root)
-{
- /* function operation
- convert to rdn
- pop off naming attribute of sdn "{ cn | uid }"
- replace with other naming attribute "{ uid | cn }"
- append root
- return sdn by reference
- */
- Slapi_RDN *old_rdn = NULL;
- Slapi_RDN *new_rdn = NULL;
- char* naming_type = "";
- char* naming_value= "";
- Slapi_DN *return_sdn = NULL;
- int rc = 0;
- char* tempdn;
-
- PR_ASSERT(sdn);
- PR_ASSERT(root);
-
- old_rdn = slapi_rdn_new_sdn(sdn); /* cn=administrator */
-
- new_rdn = slapi_rdn_new();
-
- rc = slapi_rdn_get_first(old_rdn, &naming_type, &naming_value); /* cn administrator */
-
- if (map_to == REPLICA_TYPE_MULTIMASTER)
- naming_type = slapi_ch_strdup("uid"); /* uid administrator */
- else if (map_to == REPLICA_TYPE_WINDOWS)
- naming_type = slapi_ch_strdup("cn");
-
-
- rc = slapi_rdn_add(new_rdn, naming_type, naming_value); /* uid=administrator */
-
- /* XXX this should be done with SDN and not char* */
-
- tempdn = (char*) slapi_ch_malloc( strlen (naming_type) + strlen(naming_value) +
- slapi_sdn_get_ndn_len(root) + 4);
-
- sprintf(tempdn, "%s=%s, %s", naming_type, naming_value, slapi_sdn_get_ndn(root) );
-
-
- return_sdn = slapi_sdn_new_dn_byref(tempdn);
-
-
- return return_sdn;
-
-}
-
-static Slapi_DN* map_dn_group(Slapi_DN *sdn, int map_to, const Slapi_DN *root)
-{
- /* function operation
- convert to rdn
- append root
- return sdn by reference
- */
- Slapi_RDN *old_rdn = NULL;
- Slapi_RDN *new_rdn = NULL;
- char* naming_type = "";
- char* naming_value= "";
- Slapi_DN *return_sdn = NULL;
- int rc = 0;
- char* tempdn;
-
- PR_ASSERT(sdn);
- PR_ASSERT(root);
-
- old_rdn = slapi_rdn_new_sdn(sdn); /* cn=administrator */
-
- new_rdn = slapi_rdn_new();
-
- rc = slapi_rdn_get_first(old_rdn, &naming_type, &naming_value); /* cn administrator */
-
- rc = slapi_rdn_add(new_rdn, naming_type, naming_value);
-
- /* XXX this should be done with SDN and not char* */
-
- tempdn = (char*) slapi_ch_malloc( strlen (naming_type) + strlen(naming_value) +
- slapi_sdn_get_ndn_len(root) + 4);
-
- sprintf(tempdn, "%s=%s, %s", naming_type, naming_value, slapi_sdn_get_ndn(root) );
-
-
- return_sdn = slapi_sdn_new_dn_passin(tempdn);
-
-
- return return_sdn;
-
-}
-
-static void alter_mods(LDAPMod ***m, char** password)
+static void
+periodic_dirsync(time_t when, void *arg)
{
- LDAPMod **mods = *m;
- int i=0;
-
- while (NULL != mods && NULL != mods[i])
- {
- int j=-1; /* index of the attribute mapping array */
- char* attr_type;
- attr_type = slapi_ch_strdup(mods[i]->mod_type);
- while ( mapping[++j].old_name != NULL)
- {
-
- if ( (mapping[j].map_to == REPLICA_TYPE_WINDOWS) &&
- (slapi_attr_type_cmp(attr_type, mapping[j].old_name, 1) == 0 ) )
- {
- mods[i]->mod_type = slapi_ch_strdup(mapping[j].new_name);
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "alter_mods \n\t%s\n\t%s\n", mapping[j].old_name, mapping[j].new_name);
- break;
-
- }
- }
-
- if (slapi_attr_type_cmp(attr_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD , 1) == 0)
- {
- int b;
- char *pw;
- if (mods[i]->mod_op | LDAP_MOD_BVALUES)
- {
- *password = (char*) slapi_ch_malloc(strlen( mods[i]->mod_bvalues[0]->bv_val) + 3); /* "%s"\0 */
- pw = mods[i]->mod_bvalues[0]->bv_val;
- }
- else
- {
- *password = (char*) slapi_ch_malloc(strlen( mods[i]->mod_values[0]) + 3); /* "%s"\0 */
- pw = mods[i]->mod_values[0];
- }
-
- b = sprintf(*password, "\"%s\"", pw);
-
-
- }
-
- if (mapping[j].old_name == NULL)
- {
- LDAPMod *this_mod = mods[i];
-
- /* Move down all subsequent mods */
- int k = 0;
- for (k = i; mods[k+1] ; k++)
- {
- mods[k] = mods[k+1];
- }
- /* Zero the end of the array */
- mods[k] = NULL;
- /* Adjust value of j, implicit in not incrementing it */
- /* Free this mod */
- ber_bvecfree(this_mod->mod_bvalues);
- slapi_ch_free((void **)&(this_mod->mod_type));
- slapi_ch_free((void **)&this_mod);
- }
- else
- i++;
- }
-}
-
-
-/* the entry has already been translated, so be sure to search for ntuserid
- and not samaccountname or anything else. */
-
-static Slapi_Entry* windows_entry_already_exists(Slapi_Entry *e){
-
- int rc = 0;
- Slapi_DN *sdn = NULL;
- Slapi_Entry *entry = NULL;
-
- sdn = slapi_entry_get_sdn(e);
- rc = slapi_search_internal_get_entry( sdn, NULL, &entry, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION));
-
- if (rc == LDAP_SUCCESS)
- {
- return entry;
- }
- else
- {
- return NULL;
- }
-
-}
-
-static PRBool entry_is_tombstone(Slapi_Entry *e){
- return PR_FALSE;
-}
-
-static int delete_user(Slapi_Entry *e){
- const char* dn;
- const char* new_dn;
- Slapi_PBlock *pb = NULL;
- Slapi_DN *sdn = NULL;
- int return_value = 0;
-
- PR_ASSERT(e);
-
- dn = slapi_ch_strdup( slapi_entry_get_ndn(e) );
- new_dn = slapi_ch_strdup(dn);
-
- /* XXX dn parsing in this if block could use some improvement */
- if ( strstr(new_dn, "\ndel:") != NULL )
- {
- char* comma;
- const char* c = ",";
- pb = slapi_pblock_new();
-
- comma = strstr(dn, c);
-
- strcpy( strstr(new_dn, "\ndel:"), comma);
-
- slapi_delete_internal_set_pb(pb, new_dn, NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_delete_internal_pb(pb);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value);
- slapi_pblock_destroy(pb);
-
-
- }
- else
- {
- return_value = -1;
- }
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "delete operation of entry %s returned: %d\n", new_dn, return_value);
-
- slapi_ch_free((void**) &dn);
- slapi_ch_free((void**) &new_dn);
-
- return return_value;
-}
-
-
-static void make_mods_from_entries(Slapi_Entry *new_entry, Slapi_Entry *existing_entry, LDAPMod ***attrs){
- Slapi_Attr *attr;
- int rc = 0;
- Slapi_Mods smods;
-
- PR_ASSERT (new_entry && attrs && existing_entry);
-
- slapi_mods_init (&smods, 0);
-
- rc =slapi_entry_first_attr( new_entry, &attr );
-
- while (rc == 0)
- {
- char* attr_type;
- Slapi_Attr *existing_attr;
- int i=-1;
- Slapi_Value *v1 = NULL;
- Slapi_Value *v2 = NULL;
-
- slapi_attr_get_type(attr, &attr_type);
-
- slapi_attr_first_value( attr, &v1);
-
- if (slapi_entry_attr_find(existing_entry, attr_type, &existing_attr) == 0)
- {
- /* found */
- slapi_attr_first_value( existing_attr, &v2);
-
- if (slapi_value_compare(existing_attr, v1, v2) == 0)
- {
- /* same, do nothing */
- /* slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "make_mods_from_entries: %s has same value (%s) on both sides\n", attr_type, slapi_value_get_string(v1)); */
-
- }
- else
- {
- /* attributes different -- create CHANGE */
- /* slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "make_mods_from_entries: %s has different value (%s, %s)\n",
- attr_type, slapi_value_get_string(v1),slapi_value_get_string(v2)); */
-
- slapi_mods_add_mod_values(&smods, LDAP_MOD_REPLACE, attr_type, &v1 );
- }
-
-
- }
- else
- {
- /* not found -- create ADD */
- /*slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "make_mods_from_entries: %s has no value ( will be %s)\n",
- attr_type, slapi_value_get_string(v1)); */
-
-
- slapi_mods_add_mod_values(&smods, LDAP_MOD_ADD, attr_type, &v1 );
-
- }
-
- /* XXX TODO:
- delete an attribute */
-
- rc = slapi_entry_next_attr(new_entry, attr, &attr);
-
-
- }
- *attrs = slapi_mods_get_ldapmods_passout (&smods);
- slapi_mods_done (&smods);
-
-
-}
-
-int add_or_modify_user(Slapi_Entry *e){
- Slapi_PBlock *pb = NULL;
- int return_value = 0;
- char *dn;
- Slapi_Entry *existing = NULL;
-
- pb = slapi_pblock_new();
- dn = slapi_ch_strdup( slapi_entry_get_ndn(e) );
-
- existing = windows_entry_already_exists(e);
- if ( existing == NULL)
- {
- slapi_add_entry_internal_set_pb(pb, e, NULL,
- repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
- 0);
- slapi_add_internal_pb(pb);
-
- }
- else
- {
- LDAPMod **mods;
- make_mods_from_entries(e, existing, &mods);
- if (NULL == mods)
- { /* also get null if there are no differences, so this is ok. */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "add_or_modify_user: Cannot convert entry %s to LDAPMods.\n", dn );
- return_value = 0;
- goto bail;
- }
-
- slapi_modify_internal_set_pb (pb, slapi_entry_get_ndn(e), mods, NULL, NULL,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- ldap_mods_free(mods, 1);
- }
-
-
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value);
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> periodic_dirsync\n", 0, 0, 0 );
slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "operation of entry %s returned: %d\n", dn, return_value);
-
-bail:
-
- if (pb)
- slapi_pblock_destroy(pb);
+ "Running Dirsync \n");
- return return_value;
+ event_notify( (Private_Repl_Protocol*) arg, EVENT_RUN_DIRSYNC);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= periodic_dirsync\n", 0, 0, 0 );
}
-
-
-int add_or_modify_group(Slapi_Entry *e){
- Slapi_PBlock *pb = NULL;
- int return_value = 0;
- char *dn;
- Slapi_Entry *existing = NULL;
-
- pb = slapi_pblock_new();
- dn = slapi_ch_strdup( slapi_entry_get_ndn(e) );
-
- existing = windows_entry_already_exists(e);
- if ( existing == NULL)
- {
- slapi_add_entry_internal_set_pb(pb, e, NULL,
- repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
- 0);
- slapi_add_internal_pb(pb);
-
- }
- else
- {
- LDAPMod **mods;
- make_mods_from_entries(e, existing, &mods);
- if (NULL == mods)
- { /* also get null if there are no differences, so this is ok. */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "add_or_modify_user: Cannot convert entry %s to LDAPMods.\n", dn );
- return_value = 0;
- goto bail;
- }
-
- slapi_modify_internal_set_pb (pb, slapi_entry_get_ndn(e), mods, NULL, NULL,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- ldap_mods_free(mods, 1);
- }
-
-
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value);
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "operation of entry %s returned: %d\n", dn, return_value);
-
-bail:
-
- if (pb)
- slapi_pblock_destroy(pb);
-
- return return_value;
-}
-
-
-
-void windows_dirsync_inc_run(Private_Repl_Protocol *prp)
- {
-
- int rc;
- int msgid=0;
- Slapi_PBlock *pb = NULL;
- Slapi_Filter *filter_user = NULL;
- Slapi_Filter *filter_user_deleted = NULL;
- Slapi_Filter *filter_group = NULL;
- Slapi_Filter *filter_group_deleted = NULL;
-
- rc = perform_search(prp->conn);
- if (rc == CONN_OPERATION_SUCCESS)
- {
-
- Slapi_Entry *e;
- int filter_ret = 0;
-
-
-#define FILTER_USER "(objectclass=user)"
-#define FILTER_GROUP "(objectclass=group)"
-#define FILTER_USER_DELETED "(&(isdeleted=*)(objectclass=user))"
-#define FILTER_GROUP_DELETED "(&(isdeleted=*)(objectclass=group))"
-
- filter_user = slapi_str2filter( slapi_ch_strdup( FILTER_USER ) );
- filter_user_deleted = slapi_str2filter( slapi_ch_strdup( FILTER_USER_DELETED ) );
- filter_group = slapi_str2filter( slapi_ch_strdup( FILTER_GROUP ) );
- filter_group_deleted = slapi_str2filter( slapi_ch_strdup( FILTER_GROUP_DELETED ) );
-
-
-
- while ((e = windows_conn_get_search_result(prp->conn)) != NULL)
- {
- const Slapi_DN* sdn = NULL;
- /* deleted users are outside the 'correct container'.
- They live in cn=deleted objects, windows_private_get_directory_replarea( prp->agmt) */
-
- if ( slapi_filter_test( pb, e, filter_user_deleted, 0 ) == 0 )
- {
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "entry %s marked for deletion\n", slapi_entry_get_ndn(e));
-
- sdn = map_dn_user(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) );
- slapi_entry_set_sdn(e, sdn);
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "entry %s marked for deletion\n", slapi_entry_get_ndn(e));
-
-
- delete_user(e); /* CN is "garbled" if the entry is deleted */
- }
- else if ( slapi_filter_test( pb, e, filter_group_deleted, 0 ) == 0 )
- {
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "group %s marked for deletion\n", slapi_entry_get_ndn(e));
-
- sdn = map_dn_group(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) );
- slapi_entry_set_sdn(e, sdn);
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "entry %s marked for deletion\n", slapi_entry_get_ndn(e));
-
- delete_user(e); /* CN is "garbled" if the entry is deleted */
-
-
- }
- /* must be in the previously specified container to be replicated, lest it is ignored */
- else if (slapi_sdn_isparent(windows_private_get_windows_replarea( prp->agmt ), slapi_entry_get_sdn(e)) )
- {
- if (0 == slapi_filter_test( pb, e, filter_user, 0))
- {
- sdn = map_dn_user(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) );
- map_entry_user(&e, REPLICA_TYPE_MULTIMASTER, NULL);
-
- slapi_entry_set_sdn(e, sdn);
- /* if (windows_private_create_users(prp->ra)) */
- add_or_modify_user(e);
- }
- else if (0 == slapi_filter_test( pb, e, filter_group, 0))
- {
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "group %s marked for addition\n", slapi_entry_get_ndn(e));
-
- sdn = map_dn_group(slapi_entry_get_sdn(e),REPLICA_TYPE_MULTIMASTER, windows_private_get_directory_replarea( prp->agmt) );
- slapi_entry_set_sdn(e, sdn);
-
- map_entry_group(&e, REPLICA_TYPE_MULTIMASTER);
-
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "group %s marked for addition\n", slapi_entry_get_ndn(e));
-
- add_or_modify_group(e);
- }
- else
- {
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "entry %s in %s ignored\n", slapi_entry_get_ndn(e), slapi_sdn_get_dn(windows_private_get_directory_replarea( prp->agmt)) );
- }
- /* inside container */
- }
- else
- {
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
- "entry %s ignored\n", slapi_entry_get_ndn(e));
- }
- }
- }
-}
-
diff --git a/ldap/servers/plugins/replication/windows_private.c b/ldap/servers/plugins/replication/windows_private.c
index 63a30fe5..001e57bb 100644
--- a/ldap/servers/plugins/replication/windows_private.c
+++ b/ldap/servers/plugins/replication/windows_private.c
@@ -8,121 +8,213 @@
#include "repl.h"
#include "repl5.h"
-
+#include "slap.h"
+#include "slapi-plugin.h"
+#include "windowsrepl.h"
struct windowsprivate {
- Slapi_DN *windows_replarea; /* DN of replicated area (on the windows side) */
- Slapi_DN *directory_replarea; /* DN of replicated area on directory 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 */
-
int dirsync_flags;
int dirsync_maxattributecount;
char *dirsync_cookie;
int dirsync_cookie_len;
PRBool dirsync_cookie_has_more;
-
PRBool create_users_from_dirsync;
+ PRBool create_groups_from_dirsync;
+ char *windows_domain;
};
+void
+windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e)
+{
+ char *tmpstr = NULL;
+ agmt_set_priv(ra,windows_private_new());
+
+ /* DN of entry at root of replicated area */
+ tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsReplicaArea);
+ if (NULL != tmpstr)
+ {
+ windows_private_set_windows_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
+ }
+ tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7DirectoryReplicaArea);
+ if (NULL != tmpstr)
+ {
+ windows_private_set_directory_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
+ }
-
+ tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7CreateNewUsers);
+ if (NULL != tmpstr)
+ {
+ windows_private_set_create_users(ra, PR_TRUE);
+ slapi_ch_free((void**)&tmpstr);
+ }
+ else
+ {
+ windows_private_set_create_users(ra, PR_FALSE);
+ }
+ tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsDomain);
+ if (NULL != tmpstr)
+ {
+ windows_private_set_windows_domain(ra,tmpstr);
+ }
+}
Dirsync_Private* windows_private_new()
{
Dirsync_Private *dp;
- dp = (Dirsync_Private *)slapi_ch_malloc(sizeof(Dirsync_Private));
- dp->windows_replarea = NULL;
- dp->dirsync_flags = 0;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_new\n", 0, 0, 0 );
+
+ dp = (Dirsync_Private *)slapi_ch_calloc(sizeof(Dirsync_Private),1);
+
dp->dirsync_maxattributecount = -1;
- dp->dirsync_cookie = NULL;
- dp->dirsync_cookie_len = 0;
- dp->dirsync_cookie_has_more = 0;
dp->create_users_from_dirsync = PR_TRUE;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_new\n", 0, 0, 0 );
return dp;
}
-void windows_private_delete(Dirsync_Private **dp)
+void windows_agreement_delete(Repl_Agmt *ra)
{
+ Dirsync_Private *dp = (Dirsync_Private *) agmt_get_priv(ra);
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_delete\n", 0, 0, 0 );
+
PR_ASSERT(dp != NULL);
- PR_ASSERT(*dp != NULL);
- /* TODO: free cookie */
+ /* DBDB: need to free payoad here */
- /* slapi_sdn_done((**dp).windows_replarea); */
slapi_ch_free((void **)dp);
-}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_delete\n", 0, 0, 0 );
+}
-const Slapi_DN* windows_private_get_windows_replarea (const Repl_Agmt *ra)
+/* 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;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_subtree\n", 0, 0, 0 );
+
PR_ASSERT(ra);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_subtree\n", 0, 0, 0 );
- if(dp->windows_replarea)
- return slapi_sdn_dup (dp->windows_replarea);
- else
- return NULL;
+ return dp->windows_subtree;
}
-const Slapi_DN* windows_private_get_directory_replarea (const Repl_Agmt *ra)
+const char *
+windows_private_get_windows_domain(const Repl_Agmt *ra)
{
Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_domain\n", 0, 0, 0 );
+
PR_ASSERT(ra);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_domain\n", 0, 0, 0 );
- if(dp->directory_replarea)
- return slapi_sdn_dup (dp->directory_replarea);
- else
- return NULL;
+ return dp->windows_domain;
}
+static void
+windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain)
+{
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_domain\n", 0, 0, 0 );
-void windows_private_set_windows_replarea (const Repl_Agmt *ra,const Slapi_DN* sdn )
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ dp->windows_domain = domain;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_domain\n", 0, 0, 0 );
+ }
+
+/* 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;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_replarea\n", 0, 0, 0 );
+
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_replarea\n", 0, 0, 0 );
+
+ return dp->directory_subtree;
+}
+
+/* Takes a copy of the sdn passed in */
+void windows_private_set_windows_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn )
{
Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_replarea\n", 0, 0, 0 );
+
PR_ASSERT(ra);
PR_ASSERT(sdn);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
- dp->windows_replarea = slapi_sdn_dup(sdn);
+ dp->windows_subtree = slapi_sdn_dup(sdn);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_replarea\n", 0, 0, 0 );
}
-void windows_private_set_directory_replarea (const Repl_Agmt *ra,const Slapi_DN* sdn )
+/* Takes a copy of the sdn passed in */
+void windows_private_set_directory_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn )
{
Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_directory_replarea\n", 0, 0, 0 );
+
PR_ASSERT(ra);
PR_ASSERT(sdn);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
- dp->directory_replarea = slapi_sdn_dup(sdn);
+ dp->directory_subtree = slapi_sdn_dup(sdn);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_directory_replarea\n", 0, 0, 0 );
}
PRBool windows_private_create_users(const Repl_Agmt *ra)
{
Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_create_users\n", 0, 0, 0 );
+
PR_ASSERT(ra);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_create_users\n", 0, 0, 0 );
+
return dp->create_users_from_dirsync;
}
@@ -131,12 +223,17 @@ PRBool windows_private_create_users(const Repl_Agmt *ra)
void windows_private_set_create_users(const Repl_Agmt *ra, PRBool value)
{
Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_create_users\n", 0, 0, 0 );
+
PR_ASSERT(ra);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
dp->create_users_from_dirsync = value;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_create_users\n", 0, 0, 0 );
+
}
@@ -145,16 +242,19 @@ void windows_private_set_create_users(const Repl_Agmt *ra, PRBool value)
Repl_Agmt ra as a ldap control.
*/
-LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra){
+LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
+{
LDAPControl *control = NULL;
LDAPControl **lc = &control ;
BerElement *ber;
Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_dirsync_control\n", 0, 0, 0 );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
ber = ber_alloc();
@@ -162,6 +262,10 @@ LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra){
slapi_build_control( REPL_DIRSYNC_CONTROL_OID, ber, PR_TRUE, &control);
+ ber_free(ber,1);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_dirsync_control\n", 0, 0, 0 );
+
return control;
@@ -172,7 +276,8 @@ LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra){
Dirsync_Private if the dirsync control is found.
*/
-void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **controls ){
+void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **controls )
+{
Dirsync_Private *dp;
int foundDirsyncControl;
@@ -181,13 +286,14 @@ void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **co
BerElement *ber;
int hasMoreData;
int maxAttributeCount;
-
-
- BerValue *serverCookie;
+ BerValue *serverCookie;
+ int return_value = LDAP_SUCCESS;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_update_dirsync_control\n", 0, 0, 0 );
PR_ASSERT(ra);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
if (NULL != controls )
@@ -198,13 +304,22 @@ void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **co
}
if ( !foundDirsyncControl )
- return;
+ {
+ return_value = LDAP_CONTROL_NOT_FOUND;
+ goto choke;
+ }
else
+ {
dirsync = slapi_dup_control( controls[i-1]);
+ }
ber = ber_init( &dirsync->ldctl_value ) ;
- ber_scanf( ber, "{iiO}", &hasMoreData, &maxAttributeCount, &serverCookie);
+ if (ber_scanf( ber, "{iiO}", &hasMoreData, &maxAttributeCount, &serverCookie) == LBER_ERROR)
+ {
+ return_value = LDAP_CONTROL_NOT_FOUND;
+ goto choke;
+ }
slapi_ch_free(&dp->dirsync_cookie);
dp->dirsync_cookie = ( char* ) slapi_ch_malloc(serverCookie->bv_len + 1);
@@ -212,34 +327,187 @@ void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **co
memcpy(dp->dirsync_cookie, serverCookie->bv_val, serverCookie->bv_len);
dp->dirsync_cookie_len = (int) serverCookie->bv_len; /* XXX shouldn't cast? */
- dp->dirsync_maxattributecount = maxAttributeCount;
+ /* dp->dirsync_maxattributecount = maxAttributeCount; We don't need to keep this */
dp->dirsync_cookie_has_more = hasMoreData;
+choke:
ber_bvfree(serverCookie);
ber_free(ber,1);
}
+ else
+ {
+ return_value = LDAP_CONTROL_NOT_FOUND;
+ }
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_update_dirsync_control\n", 0, 0, 0 );
+ /* return return_value; */
}
PRBool windows_private_dirsync_has_more(const Repl_Agmt *ra)
{
- Dirsync_Private *dp;
+ Dirsync_Private *dp;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_dirsync_has_more\n", 0, 0, 0 );
+
PR_ASSERT(ra);
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_dirsync_has_more\n", 0, 0, 0 );
+
return dp->dirsync_cookie_has_more;
}
-void windows_private_null_dirsync_control(const Repl_Agmt *ra){
-
+void windows_private_null_dirsync_cookie(const Repl_Agmt *ra)
+{
Dirsync_Private *dp;
- dp = (Dirsync_Private *) get_priv_from_agmt(ra);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_null_dirsync_control\n", 0, 0, 0 );
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
PR_ASSERT (dp);
dp->dirsync_cookie_len = 0;
- /* XXX should this value be free'd? */
+ slapi_ch_free(&dp->dirsync_cookie);
dp->dirsync_cookie = NULL;
-} \ No newline at end of file
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_null_dirsync_control\n", 0, 0, 0 );
+}
+
+static
+Slapi_Mods *windows_private_get_cookie_mod(Dirsync_Private *dp, int modtype)
+{
+ Slapi_Mods *smods = NULL;
+ smods = slapi_mods_new();
+
+ slapi_mods_add( smods, modtype,
+ "nsds7DirsyncCookie", dp->dirsync_cookie_len , dp->dirsync_cookie);
+
+ return smods;
+
+}
+
+
+/* writes the current cookie into dse.ldif under the replication agreement entry
+ returns: ldap result code of the operation. */
+int
+windows_private_save_dirsync_cookie(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp = NULL;
+ Slapi_PBlock *pb = NULL;
+ const char* dn = NULL;
+ Slapi_DN* sdn = NULL;
+ int rc = 0;
+ Slapi_Mods *mods = NULL;
+
+
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_save_dirsync_cookie\n", 0, 0, 0 );
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+
+ pb = slapi_pblock_new ();
+
+ mods = windows_private_get_cookie_mod(dp, LDAP_MOD_REPLACE);
+ sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) );
+ dn = slapi_sdn_get_dn(sdn);
+
+ slapi_modify_internal_set_pb (pb, dn, slapi_mods_get_ldapmods_byref(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);
+
+ if (rc == LDAP_NO_SUCH_ATTRIBUTE)
+ { /* try again, but as an add instead */
+ mods = windows_private_get_cookie_mod(dp, LDAP_MOD_ADD);
+ slapi_modify_internal_set_pb (pb, dn, slapi_mods_get_ldapmods_byref(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);
+ }
+
+ slapi_pblock_destroy (pb);
+ slapi_mods_free(&mods);
+ slapi_sdn_free(&sdn);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_save_dirsync_cookie\n", 0, 0, 0 );
+ return rc;
+}
+
+/* reads the cookie in dse.ldif to the replication agreement entry
+ returns: ldap result code of ldap operation, or
+ LDAP_NO_SUCH_ATTRIBUTE. (this is the equilivent of a null cookie) */
+int windows_private_load_dirsync_cookie(const Repl_Agmt *ra)
+{
+ Dirsync_Private *dp = NULL;
+ Slapi_PBlock *pb = NULL;
+
+ Slapi_DN* sdn = NULL;
+ int rc = 0;
+ Slapi_Entry *entry = NULL;
+ char* cookie = NULL;
+ Slapi_Attr *attr = NULL;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_load_dirsync_cookie\n", 0, 0, 0 );
+ PR_ASSERT(ra);
+
+ dp = (Dirsync_Private *) agmt_get_priv(ra);
+ PR_ASSERT (dp);
+
+
+ pb = slapi_pblock_new ();
+ sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) );
+
+
+ rc = slapi_search_internal_get_entry(sdn, NULL, &entry,
+ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION));
+
+ if (rc == 0)
+ {
+ rc= slapi_entry_attr_find( entry, type_nsds7DirsyncCookie, &attr );
+ if (attr)
+ {
+ struct berval **vals;
+ rc = slapi_attr_get_bervals_copy(attr, &vals );
+
+ if (vals)
+ {
+ dp->dirsync_cookie_len = (int) (vals[0])->bv_len;
+ slapi_ch_free(&dp->dirsync_cookie);
+
+ dp->dirsync_cookie = ( char* ) slapi_ch_malloc(dp->dirsync_cookie_len + 1);
+ memcpy(dp->dirsync_cookie,(vals[0]->bv_val), (vals[0])->bv_len+1);
+
+ }
+
+ ber_bvecfree(vals);
+ /* we do not free attr */
+
+ }
+ else
+ {
+ rc = LDAP_NO_SUCH_ATTRIBUTE;
+ }
+ }
+
+ if (entry)
+ {
+ slapi_entry_free(entry);
+ }
+
+ slapi_sdn_free( &sdn);
+ slapi_pblock_destroy (pb);
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_load_dirsync_cookie\n", 0, 0, 0 );
+
+ return rc;
+}
+
diff --git a/ldap/servers/plugins/replication/windows_prot_private.h b/ldap/servers/plugins/replication/windows_prot_private.h
index d9832cb3..424f52e8 100644
--- a/ldap/servers/plugins/replication/windows_prot_private.h
+++ b/ldap/servers/plugins/replication/windows_prot_private.h
@@ -66,5 +66,7 @@ CSN *get_current_csn(Slapi_DN *replarea_sdn);
char* protocol_response2string (int response);
void windows_dirsync_inc_run(Private_Repl_Protocol *prp);
+ConnResult windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op);
+int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e);
#endif /* _REPL5_PROT_PRIVATE_H_ */
diff --git a/ldap/servers/plugins/replication/windows_protocol_util.c b/ldap/servers/plugins/replication/windows_protocol_util.c
index bb09c05d..4f37af87 100644
--- a/ldap/servers/plugins/replication/windows_protocol_util.c
+++ b/ldap/servers/plugins/replication/windows_protocol_util.c
@@ -12,13 +12,297 @@ Code common to both incremental and total protocols.
*/
#include "repl5.h"
-// #include "windows_prot_private.h"
#include "repl5_prot_private.h"
#include "windowsrepl.h"
+#include "slap.h"
+
+#include <unicode/ustring.h> /* UTF8 conversion */
int ruv_private_new( RUV **ruv, RUV *clone );
+
+static Slapi_Entry* windows_entry_already_exists(Slapi_Entry *e);
+static void windows_dirsync_now (Private_Repl_Protocol *prp);
+static Slapi_DN* map_dn_user(Slapi_DN *sdn, int map_to, const Slapi_DN *root);
+static Slapi_DN* map_dn_group(Slapi_DN *sdn, int map_to, const Slapi_DN *root);
+static void make_mods_from_entries(Slapi_Entry *new_entry, Slapi_Entry *existing_entry, LDAPMod ***attrs);
+static void windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods, LDAPMod ***returned_mods, int is_user, char** password);
+static int is_subject_of_agreemeent_local(const Slapi_Entry *local_entry,const Repl_Agmt *ra);
+static int windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_entry, Slapi_DN *remote_sdn, Slapi_Entry **remote_entry, char** password);
+static int windows_get_local_entry(const Slapi_DN* local_dn,Slapi_Entry **local_entry);
+static int windows_get_local_entry_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry);
+static int map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry);
+static char* extract_ntuserdomainid_from_entry(Slapi_Entry *e);
+static int windows_get_remote_entry (Private_Repl_Protocol *prp, Slapi_DN* remote_dn,Slapi_Entry **remote_entry);
+static const char* op2string (int op);
+static int is_subject_of_agreemeent_remote(Slapi_Entry *e, const Repl_Agmt *ra);
+static int map_entry_dn_inbound(Slapi_Entry *e, const Slapi_DN **dn, const Repl_Agmt *ra);
+
+
+/* Controls the direction of flow for mapped attributes */
+typedef enum mapping_types {
+ bidirectional,
+ fromwindowsonly,
+ towindowsonly,
+ disabled
+} mapping_types;
+
+/* Controls if we sync the attibute always, or only when we're creating new entries */
+/* Used for attributes like samaccountname, where we want to fill it in on a new entry, but
+ * we never want to change it on an existing entry */
+typedef enum creation_types {
+ always,
+ createonly
+} creation_types;
+
+typedef enum attr_types {
+ normal,
+ dnmap
+} attr_types;
+
+typedef struct _windows_attribute_map
+{
+ char *windows_attribute_name;
+ char *ldap_attribute_name;
+ mapping_types map_type;
+ creation_types create_type;
+ attr_types attr_type;
+} windows_attribute_map;
+
+/* List of attributes that are common to AD and LDAP, so we simply copy them over in both directions */
+static char* windows_user_matching_attributes[] =
+{
+ "destinationIndicator",
+ "facsimileTelephoneNumber",
+ "givenName",
+ "homePhone",
+ "homePostalAddress",
+ "initials",
+ "l",
+ "mail",
+ "manager",
+ "mobile",
+ "o",
+ "ou",
+ "pager",
+ "physicalDeliveryOfficeName",
+ "postOfficeBox",
+ "postalAddress",
+ "postalCode",
+ "preferredDeliveryMethod",
+ "registeredAddress",
+ "seeAlso",
+ "sn",
+ "st",
+ "street",
+ "telephoneNumber",
+ "teletexTerminalIdentifier",
+ "telexNumber",
+ "title",
+ "userCertificate",
+ "x121Address",
+ NULL
+};
+
+static char* windows_group_matching_attributes[] =
+{
+ "description",
+ "destinationIndicator",
+ "facsimileTelephoneNumber",
+ "givenName",
+ "homePhone",
+ "homePostalAddress",
+ "initials",
+ "l",
+ "mail",
+ "manager",
+ "mobile",
+ "o",
+ "ou",
+ "pager",
+ "physicalDeliveryOfficeName",
+ "postOfficeBox",
+ "postalAddress",
+ "postalCode",
+ "preferredDeliveryMethod",
+ "registeredAddress",
+ "seeAlso",
+ "sn",
+ "st",
+ "street",
+ "telephoneNumber",
+ "teletexTerminalIdentifier",
+ "telexNumber",
+ "title",
+ "userCertificate",
+ "x121Address",
+ NULL
+};
+
+static windows_attribute_map user_attribute_map[] =
+{
+ { "homeDirectory", "ntUserHomeDir", bidirectional, always, normal},
+ { "scriptPath", "ntUserScriptPath", bidirectional, always, normal},
+ { "lastLogon", "ntUserLastLogon", bidirectional, always, normal},
+ { "lastLogoff", "ntUserLastLogoff", bidirectional, always, normal},
+ { "sAMAccountName", "ntUserDomainId", bidirectional, createonly, normal},
+ /* cn is a naming attribute in AD, so we don't want to change it after entry creation */
+ { "cn", "cn", towindowsonly, createonly, normal},
+ /* However, it isn't a naming attribute in DS (we use uid) so it's safe to accept changes inbound */
+ { "name", "cn", fromwindowsonly, always, normal},
+ { "manager", "manager", bidirectional, always, dnmap},
+ { "secretary", "secretary", bidirectional, always, dnmap},
+ {NULL, NULL, -1}
+};
+
+static windows_attribute_map group_attribute_map[] =
+{
+ { "ntGroupType", "groupType", bidirectional, createonly, normal},
+ { "sAMAccountName", "ntUserDomainId", bidirectional, createonly, normal},
+ { "member", "uniquemember", bidirectional, always, dnmap},
+ {NULL, NULL, -1}
+};
+
+static const char*
+op2string(int op)
+{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> op2string\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= op2string\n", 0, 0, 0 );
+ switch (op) {
+ case SLAPI_OPERATION_ADD:
+ return "add";
+ case SLAPI_OPERATION_MODIFY:
+ return "modify";
+ case SLAPI_OPERATION_DELETE:
+ return "delete";
+ case SLAPI_OPERATION_MODRDN:
+ return "rename";
+ case SLAPI_OPERATION_EXTENDED:
+ return "extended";
+ }
+
+ return "unknown";
+}
+
+
+static void
+windows_dump_entry(const char *string, Slapi_Entry *e)
+{
+ int length = 0;
+ char *buffer = NULL;
+ buffer = slapi_entry2str(e,&length);
+ slapi_log_error(SLAPI_LOG_REPL, NULL, "Windows sync entry: %s %s\n", string, buffer);
+ if (buffer)
+ {
+ slapi_ch_free((void**)&buffer);
+ }
+}
+
+static void
+map_dn_values(Private_Repl_Protocol *prp,Slapi_ValueSet *original_values, Slapi_ValueSet **mapped_values, int to_windows)
+{
+ Slapi_ValueSet *new_vs = NULL;
+ Slapi_Value *original_value = NULL;
+ int retval = 0;
+ int i = 0;
+ /* For each value: */
+ i= slapi_valueset_first_value(original_values,&original_value);
+ while ( i != -1 ) {
+
+ int is_ours = 0;
+ char *new_dn_string = NULL;
+ const char *original_dn_string = NULL;
+ int original_dn_string_length = 0;
+ Slapi_DN *original_dn = NULL;
+
+ original_dn_string = slapi_value_get_string(original_value);
+ /* Sanity check the data was a valid string */
+ original_dn_string_length = slapi_value_get_length(original_value);
+ /* Make a sdn from the string */
+ original_dn = slapi_sdn_new_dn_byref(original_dn_string);
+ if (to_windows)
+ {
+ Slapi_Entry *local_entry = NULL;
+ /* Try to get the local entry */
+ retval = windows_get_local_entry(original_dn,&local_entry);
+ if (0 == retval && local_entry)
+ {
+ int missing_entry = 0;
+ Slapi_DN *remote_dn = NULL;
+ /* Now map the DN */
+ is_ours = is_subject_of_agreemeent_local(local_entry,prp->agmt);
+ if (is_ours)
+ {
+ map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry);
+ if (remote_dn)
+ {
+ if (!missing_entry)
+ {
+ /* Success */
+ new_dn_string = slapi_ch_strdup(slapi_sdn_get_dn(remote_dn));
+ }
+ slapi_sdn_free(&remote_dn);
+ }
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_REPL, NULL, "map_dn_values: no local entry found for %s\n", original_dn_string);
+ }
+ if (local_entry)
+ {
+ slapi_entry_free(local_entry);
+ local_entry = NULL;
+ }
+ } else
+ {
+ Slapi_Entry *remote_entry = NULL;
+ Slapi_DN *local_dn = NULL;
+ /* Try to get the remote entry */
+ retval = windows_get_remote_entry(prp,original_dn,&remote_entry);
+ is_ours = is_subject_of_agreemeent_remote(remote_entry,prp->agmt);
+ if (is_ours)
+ {
+ retval = map_entry_dn_inbound(remote_entry,&local_dn,prp->agmt);
+ if (0 == retval && local_dn)
+ {
+ new_dn_string = slapi_ch_strdup(slapi_sdn_get_dn(local_dn));
+ slapi_sdn_free(&local_dn);
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_REPL, NULL, "map_dn_values: no remote entry found for %s\n", original_dn_string);
+ }
+ }
+ if (remote_entry)
+ {
+ slapi_entry_free(remote_entry);
+ remote_entry = NULL;
+ }
+ }
+ /* Extract the dn string and store in the new value */
+ if (new_dn_string)
+ {
+ Slapi_Value *new_value = NULL;
+ if (NULL == new_vs)
+ {
+ new_vs = slapi_valueset_new();
+ }
+ new_value = slapi_value_new_string_passin(new_dn_string);
+ slapi_valueset_add_value(new_vs,new_value);
+ slapi_value_free(&new_value);
+ }
+ /* If not then we skip it */
+ i = slapi_valueset_next_value(original_values,i,&original_value);
+ if (original_dn)
+ {
+ slapi_sdn_free(&original_dn);
+ }
+ }/* while */
+ if (new_vs)
+ {
+ *mapped_values = new_vs;
+ }
+}
+
/*
* Acquire exclusive access to a replica. Send a start replication extended
* operation to the replica. The response will contain a success code, and
@@ -36,13 +320,15 @@ int ruv_private_new( RUV **ruv, RUV *clone );
* an error).
*/
int
-windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv)
+windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv, int check_ruv)
{
- char * prot_oid = REPL_NSDS50_INCREMENTAL_PROTOCOL_OID; //xXX get rid of this
+
int return_value = ACQUIRE_SUCCESS;
ConnResult crc;
Repl_Connection *conn;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_acquire_replica\n", 0, 0, 0 );
+
PR_ASSERT(prp);
if (prp->replica_acquired) /* we already acquire replica */
@@ -51,12 +337,10 @@ windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv)
"%s: Remote replica already acquired\n",
agmt_get_long_name(prp->agmt));
return_value = ACQUIRE_FATAL_ERROR;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_acquire_replica\n", 0, 0, 0 );
return ACQUIRE_SUCCESS;
}
- //if (NULL != ruv)
- //{ ruv_destroy ( ruv ); }
-
{
Replica *replica;
Object *supl_ruv_obj, *cons_ruv_obj;
@@ -90,22 +374,23 @@ windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv)
slapi_log_error(SLAPI_LOG_REPL, NULL, "acquire_replica, consumer RUV:\n");
- if (cons_ruv_obj) {
+ if (cons_ruv_obj)
+ {
RUV* con;
object_acquire(cons_ruv_obj);
con = (RUV*) object_get_data ( cons_ruv_obj );
ruv_dump (con,"consumer", NULL);
object_release( cons_ruv_obj );
- }else
+ } else {
slapi_log_error(SLAPI_LOG_REPL, NULL, "acquire_replica, consumer RUV = null\n");
-
+ }
is_newer = ruv_is_newer ( supl_ruv_obj, cons_ruv_obj );
/* This follows ruv_is_newer, since it's always newer if it's null */
if (cons_ruv_obj == NULL)
{
- RUV *s; // int rc;
+ RUV *s;
s = (RUV*) object_get_data ( replica_get_ruv ( replica ) );
agmt_set_consumer_ruv(prp->agmt, s );
@@ -123,8 +408,9 @@ windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv)
object_release (prp->replica_object);
replica = NULL;
- if (is_newer == PR_FALSE) {
- prp->last_acquire_response_code = NSDS50_REPL_UPTODATE;
+ if (is_newer == PR_FALSE && check_ruv) {
+ prp->last_acquire_response_code = NSDS50_REPL_UPTODATE;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_acquire_replica - ACQUIRE_CONSUMER_WAS_UPTODATE\n", 0, 0, 0 );
return ACQUIRE_CONSUMER_WAS_UPTODATE;
}
}
@@ -166,15 +452,7 @@ windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv)
current_csn = get_current_csn(replarea_sdn);
if (NULL != current_csn)
{
-
- /* Save consumer's RUV in the replication agreement.
- It is used by the changelog trimming code */
- // if (ruv && *ruv) agmt_set_consumer_ruv (prp->agmt, *ruv); XXX deadlock?
-// XXX
return_value = ACQUIRE_SUCCESS;
-
-
-
}
else
{
@@ -201,6 +479,8 @@ windows_acquire_replica(Private_Repl_Protocol *prp, RUV **ruv)
prp->replica_acquired = PR_TRUE;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_acquire_replica\n", 0, 0, 0 );
+
return return_value;
}
@@ -213,6 +493,8 @@ windows_release_replica(Private_Repl_Protocol *prp)
struct berval *payload = NULL;
Slapi_DN *replarea_sdn = NULL;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_release_replica\n", 0, 0, 0 );
+
PR_ASSERT(NULL != prp);
PR_ASSERT(NULL != prp->conn);
@@ -223,4 +505,1972 @@ windows_release_replica(Private_Repl_Protocol *prp)
prp->replica_acquired = PR_FALSE;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_release_replica\n", 0, 0, 0 );
+
+}
+
+/* this entry had a password, handle it seperately */
+/* http://support.microsoft.com/?kbid=269190 */
+static int
+send_password_modify(Slapi_DN *sdn, char *password, Private_Repl_Protocol *prp)
+{
+ ConnResult pw_return = 0;
+ LDAPMod *pw_mods[2];
+ LDAPMod pw_mod;
+ struct berval bv = {0};
+ UChar *unicode_password = NULL;
+ int32_t unicode_password_length = 0; /* Length in _characters_ */
+ int32_t buffer_size = 0; /* Size in _characters_ */
+ UErrorCode error = 0;
+ char *quoted_password = NULL;
+ struct berval *bvals[2];
+
+ /* AD wants the password in quotes ! */
+ quoted_password = PR_smprintf("\"%s\"",password);
+ if (quoted_password)
+ {
+ /* Need to UNICODE encode the password here */
+ /* It's one of those 'ask me first and I will tell you the buffer size' functions */
+ u_strFromUTF8(NULL, 0, &unicode_password_length, quoted_password, strlen(quoted_password), &error);
+ buffer_size = unicode_password_length;
+ unicode_password = (UChar *)slapi_ch_malloc(unicode_password_length * sizeof(UChar));
+ if (unicode_password) {
+ u_strFromUTF8(unicode_password, buffer_size, &unicode_password_length, quoted_password, strlen(quoted_password), &error);
+
+ bv.bv_len = unicode_password_length * sizeof(UChar);
+ bv.bv_val = (char*)unicode_password;
+
+ bvals[0] = &bv;
+ bvals[1] = NULL;
+
+ pw_mod.mod_type = "UnicodePwd";
+ pw_mod.mod_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
+ pw_mod.mod_bvalues = bvals;
+
+ pw_mods[0] = &pw_mod;
+ pw_mods[1] = NULL;
+
+ pw_return = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(sdn), pw_mods, NULL, NULL );
+
+ slapi_ch_free((void**)&unicode_password);
+ }
+ PR_smprintf_free(quoted_password);
+ }
+
+ return pw_return;
+}
+
+static int
+windows_entry_has_attr_and_value(Slapi_Entry *e, const char *attrname, char *value)
+{
+ int retval = 0;
+ Slapi_Attr *attr = 0;
+ if (!e || !attrname)
+ return retval;
+
+ /* see if the entry has the specified attribute name */
+ if (!slapi_entry_attr_find(e, attrname, &attr) && attr)
+ {
+ /* if value is not null, see if the attribute has that
+ value */
+ if (!value)
+ {
+ retval = 1;
+ }
+ else
+ {
+ Slapi_Value *v = 0;
+ int index = 0;
+ for (index = slapi_attr_first_value(attr, &v);
+ v && (index != -1);
+ index = slapi_attr_next_value(attr, index, &v))
+ {
+ const char *s = slapi_value_get_string(v);
+ if (!s)
+ continue;
+
+ if (!strcasecmp(s, value))
+ {
+ retval = 1;
+ break;
+ }
+ }
+ }
+ }
+ return retval;
+}
+
+static void
+windows_is_local_entry_user_or_group(Slapi_Entry *e, int *is_user, int *is_group)
+{
+ *is_user = windows_entry_has_attr_and_value(e,"objectclass","ntuser");
+ *is_group = windows_entry_has_attr_and_value(e,"objectclass","ntgroup");
+}
+
+static void
+windows_is_remote_entry_user_or_group(Slapi_Entry *e, int *is_user, int *is_group)
+{
+ *is_user = windows_entry_has_attr_and_value(e,"objectclass","person");
+ *is_group = windows_entry_has_attr_and_value(e,"objectclass","group");
+}
+
+static int
+add_remote_entry_allowed(Slapi_Entry *e)
+{
+ /* We say yes if the entry has the ntUserCreateNewAccount attribute set in the case of a user, or the ntGroupDeleteGroup
+ * attribute set in the case of a group
+ */
+ /* Is this a user or a group ? */
+ int is_user = 0;
+ int is_group = 0;
+ char *delete_attr = NULL;
+
+ windows_is_local_entry_user_or_group(e,&is_user,&is_group);
+ if (!is_user && !is_group)
+ {
+ /* Neither fish nor foul.. */
+ return -1;
+ }
+ if (is_user && is_group)
+ {
+ /* Now that's just really strange... */
+ return -1;
+ }
+ if (is_user)
+ {
+ delete_attr = "ntUserCreateNewAccount";
+ } else
+ {
+ delete_attr = "ntGroupCreateNewGroup";
+ }
+ /* Now test if the attribute value is set */
+ return windows_entry_has_attr_and_value(e,delete_attr,"true");
+}
+
+static int
+delete_remote_entry_allowed(Slapi_Entry *e)
+{
+ /* We say yes if the entry has the ntUserDeleteAccount attribute set in the case of a user, or the ntGroupDeleteGroup
+ * attribute set in the case of a group
+ */
+ /* Is this a user or a group ? */
+ int is_user = 0;
+ int is_group = 0;
+ char *delete_attr = NULL;
+
+ windows_is_local_entry_user_or_group(e,&is_user,&is_group);
+ if (!is_user && !is_group)
+ {
+ /* Neither fish nor foul.. */
+ return -1;
+ }
+ if (is_user && is_group)
+ {
+ /* Now that's just really strange... */
+ return -1;
+ }
+ if (is_user)
+ {
+ delete_attr = "ntUserDeleteAccount";
+ } else
+ {
+ delete_attr = "ntGroupDeleteGroup";
+ }
+ /* Now test if the attribute value is set */
+ return windows_entry_has_attr_and_value(e,delete_attr,"true");
+}
+
+static void
+windows_make_mods_for_add_retry(Slapi_Entry *local_entry, Slapi_Entry *remote_entry, LDAPMod ***result_mods, int is_user)
+{
+}
+
+static void
+windows_log_add_entry_remote(const Slapi_DN *local_dn,const Slapi_DN *remote_dn)
+{
+ const char* local_dn_string = slapi_sdn_get_dn(local_dn);
+ const char* remote_dn_string = slapi_sdn_get_dn(remote_dn);
+ slapi_log_error(SLAPI_LOG_REPL, NULL, "Attempting to add entry %s to AD for local entry %s\n",remote_dn_string,local_dn_string);
+}
+
+static ConnResult
+process_replay_add(Private_Repl_Protocol *prp, slapi_operation_parameters *op, Slapi_Entry *local_entry, Slapi_DN *local_dn, Slapi_DN *remote_dn, int is_user, int missing_entry, char **password)
+{
+ int remote_add_allowed = add_remote_entry_allowed(local_entry);
+ ConnResult return_value = 0;
+ int rc = 0;
+
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "%s: process_replay_add: dn=\"%s\" (%s,%s)\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(remote_dn), missing_entry ? "not present" : "already present" , remote_add_allowed ? "add allowed" : "add not allowed");
+
+ if (missing_entry)
+ {
+ if (remote_add_allowed) {
+ LDAPMod **entryattrs = NULL;
+ Slapi_Entry *mapped_entry = NULL;
+ /* First map the entry */
+ rc = windows_create_remote_entry(prp,op->p.p_add.target_entry, remote_dn, &mapped_entry, password);
+ /* Convert entry to mods */
+ if (0 == rc && mapped_entry)
+ {
+ (void)slapi_entry2mods (mapped_entry , NULL /* &entrydn : We don't need it */, &entryattrs);
+ slapi_entry_free(mapped_entry);
+ mapped_entry = NULL;
+ 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));
+ return_value = CONN_LOCAL_ERROR;
+ }
+ else
+ {
+ windows_log_add_entry_remote(local_dn, remote_dn);
+ return_value = windows_conn_send_add(prp->conn, slapi_sdn_get_dn(remote_dn), entryattrs, NULL, NULL);
+ /* It's possible that the entry already exists in AD, in which case we fall back to modify it */
+ if (return_value)
+ {
+ 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));
+ }
+ ldap_mods_free(entryattrs, 1);
+ entryattrs = NULL;
+ }
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: process_replay_add: failed to create mapped entry dn=\"%s\"\n",agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(remote_dn));
+ }
+ }
+ } else
+ {
+ /* Need to re-play this as a mod */
+ LDAPMod **mapped_mods = NULL;
+ Slapi_Entry *remote_entry = NULL;
+
+ /* Fetch the remote entry */
+ rc = windows_get_remote_entry(prp, remote_dn,&remote_entry);
+ if (0 == rc && remote_entry) {
+ windows_make_mods_for_add_retry(op->p.p_add.target_entry, remote_entry, &mapped_mods, is_user);
+ /* It's possible that the mapping process results in an empty mod list, in which case we don't bother with the replay */
+ if ( mapped_mods == NULL || *(mapped_mods)== NULL )
+ {
+ return_value = CONN_OPERATION_SUCCESS;
+ } else
+ {
+ return_value = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(remote_dn),mapped_mods, NULL,NULL);
+ }
+ if (mapped_mods)
+ {
+ ldap_mods_free(mapped_mods,1);
+ mapped_mods = NULL;
+ }
+ slapi_entry_free(remote_entry);
+ }
+ }
+ return return_value;
+}
+
+/*
+ * Given a changelog entry, construct the appropriate LDAP operations to sync
+ * the operation to AD.
+ */
+ConnResult
+windows_replay_update(Private_Repl_Protocol *prp, slapi_operation_parameters *op)
+{
+ ConnResult return_value = 0;
+ LDAPControl *update_control = NULL; /* No controls used for AD */
+ int rc = 0;
+ char *password = NULL;
+ int is_ours = 0;
+ int is_user = 0;
+ int is_group = 0;
+ Slapi_DN *remote_dn = NULL;
+ Slapi_DN *local_dn = NULL;
+ Slapi_Entry *local_entry = NULL;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_replay_update\n", 0, 0, 0 );
+
+ local_dn = slapi_sdn_new_dn_byref( op->target_address.dn );
+
+ /* Since we have the target uniqueid in the op structure, let's
+ * fetch the local entry here using it.
+ */
+
+ rc = windows_get_local_entry_by_uniqueid(prp, op->target_address.uniqueid, &local_entry);
+
+ if (rc)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: windows_replay_update: failed to fetch local entry for %s operation dn=\"%s\"\n",
+ agmt_get_long_name(prp->agmt),
+ op2string(op->operation_type), op->target_address.dn);
+ goto error;
+ }
+
+ is_ours = is_subject_of_agreemeent_local(local_entry, prp->agmt);
+ windows_is_local_entry_user_or_group(local_entry,&is_user,&is_group);
+
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "%s: windows_replay_update: Looking at %s operation dn=\"%s\" (%s,%s,%s)\n",
+ agmt_get_long_name(prp->agmt),
+ op2string(op->operation_type), op->target_address.dn, is_ours ? "ours" : "not ours",
+ is_user ? "user" : "not user", is_group ? "group" : "not group");
+
+ if (is_ours && (is_user || is_group) ) {
+ int missing_entry = 0;
+ /* Make the entry's DN */
+ rc = map_entry_dn_outbound(local_entry,&remote_dn,prp,&missing_entry);
+ if (rc || NULL == remote_dn)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: windows_replay_update: failed map dn for %s operation dn=\"%s\"\n",
+ agmt_get_long_name(prp->agmt),
+ op2string(op->operation_type), op->target_address.dn);
+ goto error;
+ }
+ switch (op->operation_type) {
+ /* For an ADD operation, we map the entry and then send the operation, which may fail if the peer entry already existed */
+ case SLAPI_OPERATION_ADD:
+ return_value = process_replay_add(prp,op,local_entry,local_dn,remote_dn,is_user,missing_entry,&password);
+ break;
+ case SLAPI_OPERATION_MODIFY:
+ {
+ LDAPMod **mapped_mods = NULL;
+
+ windows_map_mods_for_replay(prp,op->p.p_modify.modify_mods, &mapped_mods, is_user, &password);
+ /* It's possible that the mapping process results in an empty mod list, in which case we don't bother with the replay */
+ if ( mapped_mods == NULL || *(mapped_mods)== NULL )
+ {
+ return_value = CONN_OPERATION_SUCCESS;
+ } else
+ {
+ return_value = windows_conn_send_modify(prp->conn, slapi_sdn_get_dn(remote_dn), mapped_mods, update_control,NULL /* returned controls */);
+ }
+ if (mapped_mods)
+ {
+ ldap_mods_free(mapped_mods,1);
+ mapped_mods = NULL;
+ }
+ }
+ break;
+ case SLAPI_OPERATION_DELETE:
+ if (delete_remote_entry_allowed(local_entry))
+ {
+ return_value = windows_conn_send_delete(prp->conn, slapi_sdn_get_dn(remote_dn), update_control, NULL /* returned controls */);
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "%s: windows_replay_update: deleted remote entry, dn=\"%s\", result=%d\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(remote_dn), return_value);
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "%s: windows_replay_update: delete not allowed on remote entry, dn=\"%s\"\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(remote_dn));
+ }
+ break;
+ case SLAPI_OPERATION_MODRDN:
+ return_value = windows_conn_send_rename(prp->conn, op->target_address.dn,
+ op->p.p_modrdn.modrdn_newrdn,
+ op->p.p_modrdn.modrdn_newsuperior_address.dn,
+ op->p.p_modrdn.modrdn_deloldrdn,
+ update_control, NULL /* returned controls */);
+ break;
+ default:
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "%s: replay_update: Unknown "
+ "operation type %d found in changelog - skipping change.\n",
+ agmt_get_long_name(prp->agmt), op->operation_type);
+ }
+ if (password)
+ {
+ return_value = send_password_modify(remote_dn, password, prp);
+ if (return_value)
+ {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "%s: windows_replay_update: update password returned %d\n",
+ agmt_get_long_name(prp->agmt), return_value );
+ }
+ }
+ } else {
+ /* We ignore operations that target entries outside of our sync'ed subtree, or which are not Windows users or groups */
+ }
+error:
+ if (local_entry)
+ {
+ slapi_entry_free(local_entry);
+ }
+ if (local_dn)
+ {
+ slapi_sdn_free (&local_dn);
+ }
+ if (remote_dn)
+ {
+ slapi_sdn_free(&remote_dn);
+ }
+ return return_value;
+}
+
+static int
+is_straight_mapped_attr(const char *type, int is_user /* or group */)
+{
+ int found = 0;
+ size_t offset = 0;
+ char *this_attr = NULL;
+ char **list = is_user ? windows_user_matching_attributes : windows_group_matching_attributes;
+ /* Look for the type in the list of straight mapped attrs for the appropriate object type */
+ while (this_attr = list[offset])
+ {
+ if (0 == slapi_attr_type_cmp(this_attr, type, SLAPI_TYPE_CMP_SUBTYPE))
+ {
+ found = 1;
+ break;
+ }
+ offset++;
+ }
+ return found;
+}
+
+static void
+windows_map_attr_name(const char *original_type , int to_windows, int is_user, int is_create, char **mapped_type, int *map_dn)
+{
+ char *new_type = NULL;
+ windows_attribute_map *our_map = is_user ? user_attribute_map : group_attribute_map;
+ windows_attribute_map *this_map = NULL;
+ size_t offset = 0;
+
+ *mapped_type = NULL;
+
+ /* Iterate over the map entries looking for the type we have */
+ while(this_map = &(our_map[offset]))
+ {
+ char *their_name = to_windows ? this_map->windows_attribute_name : this_map->ldap_attribute_name;
+ char *our_name = to_windows ? this_map->ldap_attribute_name : this_map->windows_attribute_name;
+
+ if (NULL == their_name)
+ {
+ /* End of the list */
+ break;
+ }
+ if (0 == slapi_attr_type_cmp(original_type, our_name, SLAPI_TYPE_CMP_SUBTYPE))
+ {
+ if (!is_create && (this_map->create_type == createonly))
+ {
+ /* Skip create-only entries if we're not creating */
+ } else
+ {
+ if ( (this_map->map_type == towindowsonly && to_windows) || (this_map->map_type == fromwindowsonly && !to_windows)
+ || (this_map->map_type == bidirectional) )
+ {
+ new_type = slapi_ch_strdup(their_name);
+ *map_dn = (this_map->attr_type == dnmap);
+ break;
+ }
+ }
+ }
+ offset++;
+ }
+
+ if (new_type)
+ {
+ *mapped_type = new_type;
+ }
+}
+
+/*
+ * Make a new entry suitable for the sync destination (indicated by the to_windows argument).
+ * Returns the new entry ready to be passed to an LDAP ADD operation, either remote or local.
+ * Also returns the plaintext value of any password contained in the original entry (only for the
+ * to_windows direction). This is because passwords must be added to entries after they are added in AD.
+ * Caller must free the new entry and any password returned.
+ */
+static int
+windows_create_remote_entry(Private_Repl_Protocol *prp,Slapi_Entry *original_entry, Slapi_DN *remote_sdn, Slapi_Entry **remote_entry, char** password)
+{
+ int retval = 0;
+ char *entry_string = NULL;
+ Slapi_Entry *new_entry = NULL;
+ Slapi_PBlock* pb = NULL;
+ int rc = 0;
+ int is_user = 1; /* DBDB need to add code to test for group here */
+ Slapi_Attr *attr = NULL;
+ char *username = NULL;
+ const char *dn_string = NULL;
+ char *remote_entry_template = NULL;
+ char *fqusername = NULL;
+ const char *domain_name = windows_private_get_windows_domain(prp->agmt);
+
+ char *remote_user_entry_template =
+ "dn: %s\n"
+ "objectclass:top\n"
+ "objectclass:person\n"
+ "objectclass:organizationalperson\n"
+ "objectclass:user\n"
+ "userPrincipalName:%s\n"
+ "userAccountControl:512\n";
+
+ char *remote_group_entry_template =
+ "dn: %s\n"
+ "objectclass:top\n"
+ "objectclass:group\n";
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_create_remote_entry\n", 0, 0, 0 );
+
+ remote_entry_template = is_user ? remote_user_entry_template : remote_group_entry_template;
+
+ /* Create a new entry */
+ /* Give it its DN and samaccountname */
+ username = extract_ntuserdomainid_from_entry(original_entry);
+ if (NULL == username)
+ {
+ goto error;
+ }
+ fqusername = PR_smprintf("%s@%s",username,domain_name);
+ dn_string = slapi_sdn_get_dn(remote_sdn);
+ entry_string = slapi_ch_smprintf(remote_entry_template, dn_string, fqusername);
+ PR_smprintf_free(fqusername);
+ if (NULL == entry_string)
+ {
+ goto error;
+ }
+ new_entry = slapi_str2entry(entry_string, 0);
+ slapi_ch_free((void**)&entry_string);
+ if (NULL == new_entry)
+ {
+ goto error;
+ }
+ /* Map the appropriate attributes sourced from the remote entry */
+ /* Iterate over the local entry's attributes */
+ for (rc = slapi_entry_first_attr(original_entry, &attr); rc == 0;
+ rc = slapi_entry_next_attr(original_entry, attr, &attr))
+ {
+ Slapi_Value *value = NULL;
+ char *type = NULL;
+ Slapi_ValueSet *vs = NULL;
+ int mapdn = 0;
+
+ slapi_attr_get_type( attr, &type );
+ slapi_attr_get_valueset(attr,&vs);
+
+ if ( is_straight_mapped_attr(type,is_user) )
+ {
+ /* copy over the attr values */
+ slapi_entry_add_valueset(new_entry,type,vs);
+ } else
+ {
+ char *new_type = NULL;
+
+ windows_map_attr_name(type , 1 /* to windows */, is_user, 1 /* create */, &new_type, &mapdn);
+ if (new_type)
+ {
+ if (mapdn)
+ {
+ Slapi_ValueSet *mapped_values = NULL;
+ map_dn_values(prp,vs,&mapped_values, 1 /* to windows */);
+ if (mapped_values)
+ {
+ slapi_entry_add_valueset(new_entry,new_type,mapped_values);
+ slapi_valueset_free(mapped_values);
+ mapped_values = NULL;
+ }
+ } else
+ {
+ slapi_entry_add_valueset(new_entry,new_type,vs);
+ }
+ slapi_ch_free((void**)&new_type);
+ }
+ /* password mods are treated specially */
+ if (0 == slapi_attr_type_cmp(type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD, SLAPI_TYPE_CMP_SUBTYPE) )
+ {
+ const char *password_value = NULL;
+ Slapi_Value *value = NULL;
+
+ slapi_valueset_first_value(vs,&value);
+ password_value = slapi_value_get_string(value);
+ *password = slapi_ch_strdup(password_value);
+ }
+
+ }
+ if (vs)
+ {
+ slapi_valueset_free(vs);
+ vs = NULL;
+ }
+ }
+ if (remote_entry)
+ {
+ *remote_entry = new_entry;
+ }
+error:
+ if (username)
+ {
+ slapi_ch_free((void**)&username);
+ }
+ windows_dump_entry("Created new remote entry:\n",new_entry);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_create_remote_entry: %d\n", retval, 0, 0 );
+ return retval;
+}
+
+/* the entry has already been translated, so be sure to search for ntuserid
+ and not samaccountname or anything else. */
+
+static Slapi_Entry*
+windows_entry_already_exists(Slapi_Entry *e){
+
+ int rc = 0;
+ Slapi_DN *sdn = NULL;
+ Slapi_Entry *entry = NULL;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_entry_already_exists\n", 0, 0, 0 );
+
+ sdn = slapi_entry_get_sdn(e);
+ rc = slapi_search_internal_get_entry( sdn, NULL, &entry, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION));
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_entry_already_exists\n", 0, 0, 0 );
+
+ if (rc == LDAP_SUCCESS)
+ {
+ return entry;
+ }
+ else
+ {
+ return NULL;
+ }
+
+}
+
+static int
+windows_delete_local_entry(Slapi_DN *sdn){
+
+ Slapi_PBlock *pb = NULL;
+ int return_value = 0;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_delete_local_entry\n", 0, 0, 0 );
+
+ pb = slapi_pblock_new();
+ slapi_delete_internal_set_pb(pb, slapi_sdn_get_dn(sdn), NULL, NULL, repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_delete_internal_pb(pb);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value);
+ slapi_pblock_destroy(pb);
+
+ if (return_value) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "delete operation on local entry %s returned: %d\n", slapi_sdn_get_dn(sdn), return_value);
+ }
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_delete_local_entry: %d\n", return_value, 0, 0 );
+
+ return return_value;
+}
+
+static void
+windows_map_mods_for_replay(Private_Repl_Protocol *prp,LDAPMod **original_mods, LDAPMod ***returned_mods, int is_user, char** password)
+{
+ Slapi_Mods smods = {0};
+ Slapi_Mods mapped_smods = {0};
+ LDAPMod *mod = NULL;
+ int i=0;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_map_mods_for_replay\n", 0, 0, 0 );
+
+ /* Iterate through the original mods, looking each attribute type up in the maps for either user or group */
+
+ slapi_mods_init_byref(&smods, original_mods);
+ slapi_mods_init(&mapped_smods,10);
+ mod = slapi_mods_get_first_mod(&smods);
+ while(mod)
+ {
+ char *attr_type = mod->mod_type;
+ int mapdn = 0;
+
+ /* Check to see if this attribute is passed through */
+ if (is_straight_mapped_attr(attr_type,is_user)) {
+ /* If so then just copy over the mod */
+ slapi_mods_add_modbvps(&mapped_smods,mod->mod_op,attr_type,mod->mod_bvalues);
+ } else
+ {
+ char *mapped_type = NULL;
+ /* Check if this mod has its attribute type mapped */
+ windows_map_attr_name(attr_type,1,is_user,0,&mapped_type, &mapdn);
+ if (mapped_type)
+ {
+ /* If so copy over the mod with new type name */
+ if (mapdn)
+ {
+ Slapi_ValueSet *mapped_values = NULL;
+ Slapi_ValueSet *vs = NULL;
+ Slapi_Mod smod;
+
+ vs = slapi_valueset_new();
+ slapi_mod_init_byref(&smod,mod);
+ slapi_valueset_set_from_smod(vs, &smod);
+ map_dn_values(prp,vs,&mapped_values, 1 /* to windows */);
+ if (mapped_values)
+ {
+ slapi_mods_add_mod_values(&mapped_smods,mod->mod_op,mapped_type,valueset_get_valuearray(mapped_values));
+ slapi_valueset_free(mapped_values);
+ mapped_values = NULL;
+ }
+ slapi_mod_done(&smod);
+ slapi_valueset_free(vs);
+ } else
+ {
+ slapi_mods_add_modbvps(&mapped_smods,mod->mod_op,mapped_type,mod->mod_bvalues);
+ }
+ slapi_ch_free((void**)&mapped_type);
+ } else
+ {
+ /* password mods are treated specially */
+ if (0 == slapi_attr_type_cmp(attr_type, PSEUDO_ATTR_UNHASHEDUSERPASSWORD, SLAPI_TYPE_CMP_SUBTYPE) )
+ {
+ char *password_value = NULL;
+ password_value = mod->mod_bvalues[0]->bv_val;
+ *password = slapi_ch_strdup(password_value);
+ }
+ }
+ }
+ /* Otherwise we do not copy this mod at all */
+ mod = slapi_mods_get_next_mod(&smods);
+ }
+ slapi_mods_done (&smods);
+ /* Extract the mods for the caller */
+ *returned_mods = slapi_mods_get_ldapmods_passout(&mapped_smods);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_map_mods_for_replay\n", 0, 0, 0 );
+}
+
+/* Returns non-zero if the attribute value sets are identical */
+static int
+attr_compare_equal(Slapi_Attr *a, Slapi_Attr *b)
+{
+ /* For now only handle single values */
+ Slapi_Value *va = NULL;
+ Slapi_Value *vb = NULL;
+ int num_a = 0;
+ int num_b = 0;
+ int match = 1;
+
+ slapi_attr_get_numvalues(a,&num_a);
+ slapi_attr_get_numvalues(b,&num_b);
+
+ if (num_a == num_b)
+ {
+ slapi_attr_first_value(a, &va);
+ slapi_attr_first_value(b, &vb);
+
+ if (va->bv.bv_len == va->bv.bv_len)
+ {
+ if (0 != memcmp(va->bv.bv_val,vb->bv.bv_val,va->bv.bv_len))
+ {
+ match = 0;
+ }
+ } else
+ {
+ match = 0;
+ }
+ } else
+ {
+ match = 0;
+ }
+ return match;
+}
+
+/* Helper functions for dirsync result processing */
+
+/* Is this entry a tombstone ? */
+static int
+is_tombstone(Slapi_Entry *e)
+{
+ int retval = 0;
+
+ char *string_deleted = "(isdeleted=*)";
+
+ /* DBDB: we should allocate these filters once and keep them around for better performance */
+ Slapi_Filter *filter_deleted = slapi_str2filter( string_deleted );
+
+ /* DBDB: this should be one filter, the code originally tested separately and hasn't been fixed yet */
+ if ( (slapi_filter_test_simple( e, filter_deleted ) == 0) )
+ {
+ retval = 1;
+ }
+
+ slapi_filter_free(filter_deleted,1);
+ filter_deleted = NULL;
+
+ return retval;
+}
+
+#define ENTRY_NOTFOUND -1
+#define ENTRY_NOT_UNIQUE -2
+
+/* Search for an entry in AD */
+static int
+find_entry_by_attr_value_remote(const char *attribute, const char *value, Slapi_Entry **e, Private_Repl_Protocol *prp)
+{
+ int retval = 0;
+ ConnResult cres = 0;
+ char *filter = NULL;
+ const char *searchbase = NULL;
+ Slapi_Entry *found_entry = NULL;
+
+ filter = PR_smprintf("(%s=%s)",attribute,value);
+ searchbase = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ cres = windows_search_entry(prp->conn, (char*)searchbase, filter, &found_entry);
+ if (cres)
+ {
+ retval = -1;
+ } else
+ {
+ if (found_entry)
+ {
+ *e = found_entry;
+ }
+ }
+ if (filter)
+ {
+ PR_smprintf_free(filter);
+ filter = NULL;
+ }
+ return retval;
+}
+
+/* Search for an entry in AD by DN */
+static int
+windows_get_remote_entry (Private_Repl_Protocol *prp, Slapi_DN* remote_dn,Slapi_Entry **remote_entry)
+{
+ int retval = 0;
+ ConnResult cres = 0;
+ char *filter = "(objectclass=*)";
+ const char *searchbase = NULL;
+ Slapi_Entry *found_entry = NULL;
+
+ searchbase = slapi_sdn_get_dn(remote_dn);
+ cres = windows_search_entry(prp->conn, (char*)searchbase, filter, &found_entry);
+ if (cres)
+ {
+ retval = -1;
+ } else
+ {
+ if (found_entry)
+ {
+ *remote_entry = found_entry;
+ }
+ }
+ return retval;
+}
+
+static int
+find_entry_by_attr_value(const char *attribute, const char *value, Slapi_Entry **e, const Repl_Agmt *ra)
+{
+ Slapi_PBlock *pb = slapi_pblock_new();
+ Slapi_Entry **entries = NULL, **ep = NULL;
+ Slapi_Entry *entry_found = NULL;
+ char *query = NULL;
+ int found_or_not = ENTRY_NOTFOUND;
+ int rval = 0;
+ const char *subtree_dn = NULL;
+ int not_unique = 0;
+
+ if (pb == NULL)
+ goto done;
+
+ query = slapi_ch_smprintf("(%s=%s)", attribute, value);
+
+ if (query == NULL)
+ goto done;
+
+ subtree_dn = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
+
+ slapi_search_internal_set_pb(pb, subtree_dn,
+ LDAP_SCOPE_SUBTREE, query, NULL, 0, NULL, NULL,
+ (void *)plugin_get_default_component_id(), 0);
+ slapi_search_internal_pb(pb);
+ slapi_ch_free((void **)&query);
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rval);
+ if (rval != LDAP_SUCCESS)
+ {
+ goto done;
+ }
+
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ if ((entries == NULL) || (entries[0] == NULL))
+ {
+ goto done;
+ }
+ entry_found = entries[0];
+ for (ep = entries; *ep; ep++) {
+ if (not_unique)
+ {
+ found_or_not = ENTRY_NOT_UNIQUE;
+ }
+ not_unique = 1;
+ }
+done:
+ if (entry_found && (found_or_not != ENTRY_NOT_UNIQUE))
+ {
+ found_or_not = 0;
+ *e = slapi_entry_dup(entry_found);
+ }
+ if (pb)
+ {
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+ }
+ return found_or_not;
+}
+
+static int
+find_entry_by_username(const char *username, Slapi_Entry **e, const Repl_Agmt *ra)
+{
+ return find_entry_by_attr_value("ntUserDomainId",username,e,ra);
+}
+
+/* Find an entry in the local server given its GUID, or return ENTRY_NOTFOUND */
+static int
+find_entry_by_guid(const char *guid, Slapi_Entry **e, const Repl_Agmt *ra)
+{
+ return find_entry_by_attr_value("ntUniqueId",guid,e,ra);
+}
+
+/* Remove dashes from a GUID string */
+static void
+dedash(char *str)
+{
+ char *p = str;
+ char c = '\0';
+
+ while (c = *p)
+ {
+ if ('-' == c)
+ {
+ /* Move on down please */
+ char *q = p;
+ char *r = q + 1;
+ while (*r)
+ {
+ *q++ = *r++;
+ }
+ *q = '\0';
+ }
+ p++;
+ }
+}
+
+/* For reasons not clear, the GUID returned in the tombstone DN is all
+ * messed up, like the guy in the movie 'the fly' after he want in the tranporter device */
+static void
+decrypt(char *guid)
+{
+ static int decrypt_offsets[] = {6,7,4,5,2,3,0,1,10,11,8,9,14,15,12,13,16,17,18,19,
+ 20,21,22,23,24,25,26,27,28,29,30,31};
+
+ char *p = guid;
+ int i = 0;
+ char *cpy = slapi_ch_strdup(guid);
+
+ while (*p && i < (sizeof(decrypt_offsets)/sizeof(int)))
+ {
+ *p = cpy[decrypt_offsets[i]];
+ p++;
+ i++;
+ }
+ slapi_ch_free((void**)&cpy);
+}
+
+static char*
+extract_guid_from_tombstone_dn(const char *dn)
+{
+ char *guid = NULL;
+ char *colon_offset = NULL;
+ char *comma_offset = NULL;
+
+ /* example DN of tombstone:
+ "CN=WDel Userdb1\\\nDEL:551706bc-ecf2-4b38-9284-9a8554171d69,CN=Deleted Objects,DC=magpie,DC=com" */
+
+ /* First find the 'DEL:' */
+ colon_offset = strchr(dn,':');
+ /* Then scan forward to the next ',' */
+ comma_offset = strchr(dn,',');
+ /* The characters inbetween are the GUID, copy them to a new string and return to the caller */
+ if (comma_offset && colon_offset && comma_offset > colon_offset) {
+ guid = slapi_ch_malloc(comma_offset - colon_offset);
+ strncpy(guid,colon_offset+1,(comma_offset-colon_offset)-1);
+ guid[comma_offset-colon_offset-1] = '\0';
+ /* Finally remove the dashes since we don't store them on our side */
+ dedash(guid);
+ decrypt(guid);
+ }
+ return guid;
+}
+
+static char *
+convert_to_hex(Slapi_Value *val)
+{
+ int offset = 0;
+ const struct berval *bvp = NULL;
+ int length = 0;
+ char *result = NULL;
+
+ bvp = slapi_value_get_berval(val);
+ if (bvp)
+ {
+ char *new_buffer = NULL;
+ length = bvp->bv_len;
+
+ for (offset = 0; offset < length; offset++)
+ {
+ unsigned char byte = ((unsigned char*)(bvp->bv_val))[offset];
+ new_buffer = PR_sprintf_append(new_buffer, "%02x", byte );
+ }
+ if (new_buffer)
+ {
+ result = new_buffer;
+ }
+ }
+ return result;
+}
+
+static char*
+extract_guid_from_entry(Slapi_Entry *e)
+{
+ char *guid = NULL;
+ Slapi_Value *val = NULL;
+ Slapi_Attr *attr = NULL;
+
+ slapi_entry_attr_find(e, "objectGUID", &attr);
+ if (attr)
+ {
+ slapi_attr_first_value(attr, &val);
+ if (val) {
+ guid = convert_to_hex(val);
+ }
+ }
+ return guid;
+}
+
+static void
+extract_guid_from_entry_bv(Slapi_Entry *e, const struct berval **bv)
+{
+ Slapi_Value *val = NULL;
+ Slapi_Attr *attr = NULL;
+
+ slapi_entry_attr_find(e, "objectGUID", &attr);
+ if (attr)
+ {
+ slapi_attr_first_value(attr, &val);
+ if (val) {
+ *bv = slapi_value_get_berval(val);
+ }
+ }
+}
+
+static char*
+extract_username_from_entry(Slapi_Entry *e)
+{
+ char *uid = NULL;
+ uid = slapi_entry_attr_get_charptr(e,"samAccountName");
+ return uid;
+}
+
+static char*
+extract_ntuserdomainid_from_entry(Slapi_Entry *e)
+{
+ char *uid = NULL;
+ uid = slapi_entry_attr_get_charptr(e,"ntuserdomainid");
+ return uid;
+}
+
+static Slapi_DN *make_dn_from_guid(char *guid)
+{
+ Slapi_DN *new_dn = NULL;
+ char *dn_string = NULL;
+ if (guid)
+ {
+ new_dn = slapi_sdn_new();
+ dn_string = PR_smprintf("<GUID=%s>",guid);
+ slapi_sdn_init_dn_byval(new_dn,dn_string);
+ PR_smprintf_free(dn_string);
+ }
+ /* dn string is now inside the Slapi_DN, and will be freed by its owner */
+ return new_dn;
}
+
+/* Given a non-tombstone entry, return the DN of its peer in AD (whether present or not) */
+static int
+map_entry_dn_outbound(Slapi_Entry *e, const Slapi_DN **dn, Private_Repl_Protocol *prp, int *missing_entry)
+{
+ int retval = 0;
+ char *guid = NULL;
+ Slapi_DN *new_dn = NULL;
+ /* 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
+ * on the entry. If that's present we attempt to search for an entry with
+ * that samaccountName attribute value in AD. If we don't find any matching
+ * entry we generate a new DN using the entry's cn. If later, we find that
+ * this entry already exists, we handle that problem at the time. We don't
+ * check here.
+ */
+
+ *missing_entry = 0;
+
+ guid = slapi_entry_attr_get_charptr(e,"ntUniqueId");
+ if (guid)
+ {
+ new_dn = make_dn_from_guid(guid);
+ slapi_ch_free((void**)&guid);
+ } else
+ {
+ /* No GUID found, try ntUserDomainId */
+ Slapi_Entry *remote_entry = NULL;
+ char *username = slapi_entry_attr_get_charptr(e,"ntUserDomainId");
+ if (username) {
+ retval = find_entry_by_attr_value_remote("samAccountName",username,&remote_entry,prp);
+ if (0 == retval && remote_entry)
+ {
+ /* Get the entry's DN */
+ new_dn = slapi_sdn_new();
+ slapi_sdn_copy(slapi_entry_get_sdn_const(remote_entry), new_dn);
+ } else {
+ if (0 == retval)
+ {
+ const char *suffix = slapi_sdn_get_dn(windows_private_get_windows_subtree(prp->agmt));
+ char *new_dn_string = NULL;
+ char *cn_string = NULL;
+
+ *missing_entry = 1;
+ /* This means that we failed to find a peer entry */
+ /* In that case we need to generate the DN that we want to use */
+ /* Generated DN's take the form :
+ cn=<cn from local entry>, ... in the case that the local entry has a cn, OR
+ cn=<ntuserdomainid attribute value>, ... in the case that the local entry doesn't have a CN
+ */
+ cn_string = slapi_entry_attr_get_charptr(e,"cn");
+ if (!cn_string)
+ {
+ cn_string = slapi_entry_attr_get_charptr(e,"ntuserdomainid");
+ }
+ if (cn_string)
+ {
+ new_dn_string = PR_smprintf("cn=%s,%s",cn_string,suffix);
+ if (new_dn_string)
+ {
+ new_dn = slapi_sdn_new_dn_byval(new_dn_string);
+ PR_smprintf_free(new_dn_string);
+ }
+ slapi_ch_free((void**)&cn_string);
+ }
+ } else
+ {
+ /* This means that we failed to talk to the AD for some reason, the operation should be re-tried */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: map_entry_dn_outbound: failed to fetch entry from AD: dn=\"%s\", err=%d\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)), retval);
+
+ retval = -1;
+ }
+ }
+ slapi_ch_free((void**)&username);
+ }
+ if (remote_entry)
+ {
+ slapi_entry_free(remote_entry);
+ }
+ }
+ if (new_dn)
+ {
+ *dn = new_dn;
+ }
+ return retval;
+}
+
+/* Given a tombstone entry, return the DN of its peer in this server (if present) */
+static int
+map_tombstone_dn_inbound(Slapi_Entry *e, const Slapi_DN **dn, const Repl_Agmt *ra)
+{
+ int retval = 0;
+ Slapi_DN *new_dn = NULL;
+ char *guid = NULL;
+ const char *dn_string = NULL;
+ Slapi_Entry *matching_entry = NULL;
+
+ /* To map a tombstone's DN we need to first extract the entry's objectGUID from the DN
+ * CN=vpdxtAD_07\
+ DEL:d4ca4e16-e35b-400d-834a-f02db600f3fa,CN=Deleted Objects,DC=magpie,DC=com
+ */
+ *dn = NULL;
+
+ dn_string = slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)); /* This is a pointer from inside the sdn, no need to free */
+ guid = extract_guid_from_tombstone_dn(dn_string);
+
+ if (guid)
+ {
+ retval = find_entry_by_guid(guid,&matching_entry,ra);
+ if (retval)
+ {
+ if (ENTRY_NOTFOUND == retval)
+ {
+ } else
+ {
+ if (ENTRY_NOT_UNIQUE == retval)
+ {
+ } else
+ {
+ /* A real error */
+ }
+ }
+ } else
+ {
+ /* We found the matching entry : get its DN */
+ new_dn = slapi_sdn_dup(slapi_entry_get_sdn_const(matching_entry));
+ }
+ }
+
+ if (new_dn)
+ {
+ *dn = new_dn;
+ }
+
+ if (guid)
+ {
+ slapi_ch_free((void**)&guid);
+ }
+ if (matching_entry)
+ {
+ slapi_entry_free(matching_entry);
+ }
+ return retval;
+}
+
+/* Given a non-tombstone entry, return the DN of its peer in this server (whether present or not) */
+static int
+map_entry_dn_inbound(Slapi_Entry *e, const Slapi_DN **dn, const Repl_Agmt *ra)
+{
+ int retval = 0;
+ Slapi_DN *new_dn = NULL;
+ char *guid = NULL;
+ char *username = NULL;
+ Slapi_Entry *matching_entry = NULL;
+ int is_user = 0;
+ int is_group = 0;
+
+ /* 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.
+ */
+ *dn = NULL;
+
+ windows_is_remote_entry_user_or_group(e,&is_user,&is_group);
+
+ guid = extract_guid_from_entry(e);
+ if (guid)
+ {
+ retval = find_entry_by_guid(guid,&matching_entry,ra);
+ if (retval)
+ {
+ if (ENTRY_NOTFOUND == retval)
+ {
+ } else
+ {
+ if (ENTRY_NOT_UNIQUE == retval)
+ {
+ } else
+ {
+ /* A real error */
+ goto error;
+ }
+ }
+ } else
+ {
+ /* We found the matching entry : get its DN */
+ new_dn = slapi_sdn_dup(slapi_entry_get_sdn_const(matching_entry));
+ }
+ }
+ /* If we failed to lookup by guid, try samaccountname */
+ if (NULL == new_dn)
+ {
+ username = extract_username_from_entry(e);
+ if (username) {
+ retval = find_entry_by_username(username,&matching_entry,ra);
+ if (retval)
+ {
+ if (ENTRY_NOTFOUND == retval)
+ {
+ } else
+ {
+ if (ENTRY_NOT_UNIQUE == retval)
+ {
+ } else
+ {
+ /* A real error */
+ goto error;
+ }
+ }
+ } else
+ {
+ /* We found the matching entry : get its DN */
+ new_dn = slapi_sdn_dup(slapi_entry_get_sdn_const(matching_entry));
+ }
+ }
+ }
+ /* If we couldn't find a matching entry by either method, then we need to invent a new DN */
+ if (NULL == new_dn)
+ {
+ /* The new DN has the form: uid=<samaccountname>,<sync'ed subtree> */
+ /* If an entry with this DN already exists, we fail and return no DN
+ * this is because we don't want to second-guess what the admin wants here:
+ * they may want to associate this existing entry with the peer AD entry,
+ * but if they intend that we say they must add the ntDomainUserId attribute to
+ * that entry.
+ */
+ char *new_dn_string = NULL;
+ if (username)
+ {
+ const char *suffix = slapi_sdn_get_dn(windows_private_get_directory_subtree(ra));
+ /* Local DNs for users and groups are different */
+ if (is_user)
+ {
+ new_dn_string = PR_smprintf("uid=%s,%s",username,suffix);
+ } else
+ {
+ new_dn_string = PR_smprintf("cn=%s,%s",username,suffix);
+ }
+ new_dn = slapi_sdn_new_dn_byval(new_dn_string);
+ PR_smprintf_free(new_dn_string);
+ /* Clear any earlier error */
+ retval = 0;
+ } else
+ {
+ /* Error, no username */
+ }
+ }
+ if (new_dn)
+ {
+ *dn = new_dn;
+ }
+error:
+ if (guid)
+ {
+ PR_smprintf_free(guid);
+ }
+ if (matching_entry)
+ {
+ slapi_entry_free(matching_entry);
+ }
+ if (username)
+ {
+ slapi_ch_free((void **) &username);
+ }
+ return retval;
+}
+
+/* Tests if the entry is subject to our agreement (i.e. is it in the sync'ed subtree in this server, and is it the right objectclass
+ * and does it have the right attribute values for sync ?)
+ */
+static int
+is_subject_of_agreemeent_local(const Slapi_Entry *local_entry, const Repl_Agmt *ra)
+{
+ int retval = 0;
+ int is_in_subtree = 0;
+ const Slapi_DN *agreement_subtree = NULL;
+
+ /* First test for the sync'ed subtree */
+ agreement_subtree = windows_private_get_directory_subtree(ra);
+ if (NULL == agreement_subtree)
+ {
+ 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) {
+ /* DBDB: we should allocate these filters once and keep them around for better performance */
+ char *string_filter = "(&(|(objectclass=ntuser)(objectclass=ntgroup))(ntUserDomainId=*))";
+ Slapi_Filter *filter = slapi_str2filter( string_filter );
+
+ if (slapi_filter_test_simple( (Slapi_Entry*)local_entry, filter ) == 0)
+ {
+ retval = 1;
+ }
+
+ slapi_filter_free(filter,1);
+ filter = NULL;
+ } 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_agreemeent_local: %d\n", retval);
+ retval = 0;
+ }
+ }
+error:
+ return retval;
+}
+
+/* Tests if the entry is subject to our agreement (i.e. is it in the sync'ed subtree in AD and either a user or a group ?) */
+static int
+is_subject_of_agreemeent_remote(Slapi_Entry *e, const Repl_Agmt *ra)
+{
+ int retval = 0;
+ int is_in_subtree = 0;
+ const Slapi_DN *agreement_subtree = NULL;
+
+ /* First test for the sync'ed subtree */
+ agreement_subtree = windows_private_get_windows_subtree(ra);
+ if (NULL == agreement_subtree)
+ {
+ goto error;
+ }
+ is_in_subtree = slapi_sdn_scope_test(slapi_entry_get_sdn_const(e), agreement_subtree, LDAP_SCOPE_SUBTREE);
+ if (is_in_subtree)
+ {
+ retval = 1;
+ }
+error:
+ return retval;
+}
+
+static int
+windows_create_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,const Slapi_DN* local_sdn)
+{
+ int retval = 0;
+ char *entry_string = NULL;
+ Slapi_Entry *local_entry = NULL;
+ Slapi_PBlock* pb = NULL;
+ int is_user = 0;
+ int is_group = 0;
+ char *local_entry_template = NULL;
+ char *username = extract_username_from_entry(remote_entry);
+ Slapi_Attr *attr = NULL;
+ int rc = 0;
+ char *guid_str = NULL;
+
+ char *local_user_entry_template =
+ "dn: %s\n"
+ "objectclass:top\n"
+ "objectclass:organizationalperson\n"
+ "objectclass:inetOrgPerson\n"
+ "objectclass:ntUser\n"
+ "ntUserDeleteAccount:true\n"
+ "uid:%s\n";
+
+ char *local_group_entry_template =
+ "dn: %s\n"
+ "objectclass:top\n"
+ "objectclass:groupofuniquenames\n"
+ "objectclass:ntGroup\n"
+ "objectclass:mailGroup\n"
+ "ntGroupDeleteGroup:true\n"
+ "cn:%s\n";
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_create_local_entry\n", 0, 0, 0 );
+
+ windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group);
+ local_entry_template = is_user ? local_user_entry_template : local_group_entry_template;
+ /* Create a new entry */
+ /* Give it its DN and username */
+ entry_string = slapi_ch_smprintf(local_entry_template,slapi_sdn_get_dn(local_sdn),username, username);
+ if (NULL == entry_string)
+ {
+ goto error;
+ }
+ local_entry = slapi_str2entry(entry_string, 0);
+ slapi_ch_free((void**)&entry_string);
+ if (NULL == local_entry)
+ {
+ goto error;
+ }
+ /* Map the appropriate attributes sourced from the remote entry */
+ for (rc = slapi_entry_first_attr(remote_entry, &attr); rc == 0;
+ rc = slapi_entry_next_attr(remote_entry, attr, &attr))
+ {
+ Slapi_Value *value = NULL;
+ char *type = NULL;
+ Slapi_ValueSet *vs = NULL;
+ int mapdn = 0;
+
+ slapi_attr_get_type( attr, &type );
+ slapi_attr_get_valueset(attr,&vs);
+
+ if ( is_straight_mapped_attr(type,is_user) )
+ {
+ /* copy over the attr values */
+ slapi_entry_add_valueset(local_entry,type,vs);
+ } else
+ {
+ char *new_type = NULL;
+
+ windows_map_attr_name(type , 0 /* from windows */, is_user, 1 /* create */, &new_type, &mapdn);
+ if (new_type)
+ {
+ if (mapdn)
+ {
+ Slapi_ValueSet *mapped_values = NULL;
+ map_dn_values(prp,vs,&mapped_values, 0 /* from windows */);
+ if (mapped_values)
+ {
+ slapi_entry_add_valueset(local_entry,new_type,mapped_values);
+ slapi_valueset_free(mapped_values);
+ mapped_values = NULL;
+ }
+ } else
+ {
+ slapi_entry_add_valueset(local_entry,new_type,vs);
+ }
+ slapi_ch_free((void**)&new_type);
+ }
+ }
+ if (vs)
+ {
+ slapi_valueset_free(vs);
+ vs = NULL;
+ }
+ }
+ /* Copy over the GUID */
+ guid_str = extract_guid_from_entry(remote_entry);
+ if (guid_str)
+ {
+ slapi_entry_add_string(local_entry,"ntUniqueId",guid_str);
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "extract_guid_from_entry entry %s failed to extract the guid\n", slapi_sdn_get_dn(local_sdn));
+ /* Fatal error : need the guid */
+ goto error;
+ }
+ /* Store it */
+ windows_dump_entry("Adding new local entry",local_entry);
+ pb = slapi_pblock_new();
+ slapi_add_entry_internal_set_pb(pb, local_entry, NULL,repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),0);
+ slapi_add_internal_pb(pb);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &retval);
+
+ if (retval) {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "add operation of entry %s returned: %d\n", slapi_sdn_get_dn(local_sdn), retval);
+ }
+error:
+ if (pb)
+ {
+ slapi_pblock_destroy(pb);
+ }
+ if (username)
+ {
+ slapi_ch_free((void**)&username);
+ }
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_create_local_entry\n", 0, 0, 0 );
+ return retval;
+}
+
+static int
+windows_update_local_entry(Private_Repl_Protocol *prp,Slapi_Entry *remote_entry,Slapi_Entry *local_entry)
+{
+ int retval = 0;
+ Slapi_Mods smods = {0};
+ Slapi_Attr *attr = NULL;
+ int do_modify = 0;
+ int is_user = 0;
+ int is_group = 0;
+ int rc = 0;
+ Slapi_PBlock *pb = NULL;
+ /* Iterate over the attributes on the remote entry, updating the local entry where appropriate */
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_update_local_entry\n", 0, 0, 0 );
+
+ windows_is_remote_entry_user_or_group(remote_entry,&is_user,&is_group);
+
+ slapi_mods_init (&smods, 0);
+ for (rc = slapi_entry_first_attr(remote_entry, &attr); rc == 0;
+ rc = slapi_entry_next_attr(remote_entry, attr, &attr))
+ {
+ int is_present_local = 0;
+ Slapi_Value *value = NULL;
+ char *type = NULL;
+ Slapi_ValueSet *vs = NULL;
+ char *local_type = NULL;
+ Slapi_Attr *local_attr = NULL;
+ int is_guid = 0;
+ int mapdn = 0;
+
+
+ slapi_attr_get_type( attr, &type );
+ slapi_attr_get_valueset(attr,&vs);
+
+ /* First determine what we will do with this attr */
+ /* If it's a GUID, we need to take special action */
+ if (0 == slapi_attr_type_cmp(type,"objectGuid",SLAPI_TYPE_CMP_SUBTYPE))
+ {
+ is_guid = 1;
+ local_type = slapi_ch_strdup("ntUniqueId");
+ } else
+ {
+ if ( is_straight_mapped_attr(type,is_user) ) {
+ local_type = slapi_ch_strdup(type);
+ } else {
+ windows_map_attr_name(type , 0 /* from windows */, is_user, 0 /* not create */, &local_type, &mapdn);
+ }
+ is_guid = 0;
+ }
+ if (NULL == local_type)
+ {
+ /* Means we do not map this attribute */
+ if (vs)
+ {
+ slapi_valueset_free(vs);
+ vs = NULL;
+ }
+ continue;
+ }
+ slapi_entry_attr_find(local_entry,local_type,&local_attr);
+ is_present_local = (NULL == local_attr) ? 0 : 1;
+ /* Is the attribute present on the local entry ? */
+ if (is_present_local && !is_guid)
+ {
+ int values_equal = attr_compare_equal(attr,local_attr);
+ /* If it is then we need to replace the local values with the remote values if they are different */
+ if (!values_equal)
+ {
+ if (mapdn)
+ {
+ Slapi_ValueSet *mapped_values = NULL;
+ map_dn_values(prp,vs,&mapped_values, 1 /* to windows */);
+ if (mapped_values)
+ {
+ slapi_mods_add_mod_values(&smods,LDAP_MOD_REPLACE,local_type,valueset_get_valuearray(mapped_values));
+ slapi_valueset_free(mapped_values);
+ mapped_values = NULL;
+ }
+ } else
+ {
+ slapi_mods_add_mod_values(&smods,LDAP_MOD_REPLACE,local_type,valueset_get_valuearray(vs));
+ }
+ do_modify = 1;
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "windows_update_local_entry: %s, %s : values are equal\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)), local_type);
+ }
+ } else
+ {
+ if (!is_present_local)
+ {
+ /* If it is currently absent, then we add the value from the remote entry */
+ if (is_guid)
+ {
+ /* Translate the guid value */
+ char *guid = extract_guid_from_entry(remote_entry);
+ if (guid)
+ {
+ slapi_mods_add_string(&smods,LDAP_MOD_ADD,local_type,guid);
+ slapi_ch_free((void**)&guid);
+ }
+ } else
+ {
+ slapi_mods_add_mod_values(&smods,LDAP_MOD_ADD,local_type,valueset_get_valuearray(vs));
+ }
+ do_modify = 1;
+ }
+ }
+ if (vs)
+ {
+ slapi_valueset_free(vs);
+ vs = NULL;
+ }
+ if (local_type)
+ {
+ slapi_ch_free((void**)&local_type);
+ local_type = NULL;
+ }
+ }
+ /* Now perform the modify if we need to */
+ if (do_modify)
+ {
+ int rc = 0;
+ pb = slapi_pblock_new();
+ if (pb)
+ {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "modifying entry: %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)));
+ slapi_modify_internal_set_pb (pb, slapi_entry_get_ndn(local_entry), slapi_mods_get_ldapmods_byref(&smods), NULL, NULL,
+ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
+ slapi_modify_internal_pb (pb);
+ slapi_pblock_get (pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ if (rc)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "windows_update_local_entry: failed to modify entry %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(local_entry)));
+ }
+ slapi_pblock_destroy(pb);
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "failed to make pb in windows_update_local_entry\n");
+ }
+
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,
+ "no mods generated for entry: %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const(remote_entry)));
+ }
+ slapi_mods_done(&smods);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_update_local_entry: %d\n", retval, 0, 0 );
+ return retval;
+}
+
+static int
+windows_process_total_add(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* remote_dn)
+{
+ int retval = 0;
+ LDAPMod **entryattrs = NULL;
+ Slapi_Entry *mapped_entry = NULL;
+ char *password = NULL;
+ const Slapi_DN* local_dn = NULL;
+ /* First map the entry */
+ local_dn = slapi_entry_get_sdn_const(e);
+ retval = windows_create_remote_entry(prp, e, remote_dn, &mapped_entry, &password);
+ /* Convert entry to mods */
+ if (0 == retval && mapped_entry)
+ {
+ (void)slapi_entry2mods (mapped_entry , NULL /* &entrydn : We don't need it */, &entryattrs);
+ slapi_entry_free(mapped_entry);
+ mapped_entry = NULL;
+ 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));
+ retval = CONN_LOCAL_ERROR;
+ }
+ else
+ {
+ windows_log_add_entry_remote(local_dn, remote_dn);
+ retval = windows_conn_send_add(prp->conn, slapi_sdn_get_dn(remote_dn), entryattrs, NULL, NULL /* returned controls */);
+ /* 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));
+ }
+ ldap_mods_free(entryattrs, 1);
+ entryattrs = NULL;
+ }
+ }
+ return retval;
+}
+
+static int
+windows_process_total_delete(Private_Repl_Protocol *prp,Slapi_Entry *e, Slapi_DN* remote_dn)
+{
+ int retval = 0;
+ if (delete_remote_entry_allowed(e))
+ {
+ retval = windows_conn_send_delete(prp->conn, slapi_sdn_get_dn(remote_dn), NULL, NULL /* returned controls */);
+ }
+ return retval;
+}
+
+/* Entry point for the total protocol */
+int windows_process_total_entry(Private_Repl_Protocol *prp,Slapi_Entry *e)
+{
+ int retval = 0;
+ int is_ours = 0;
+ int is_tombstone = 0;
+ Slapi_DN *remote_dn = NULL;
+ int missing_entry = 0;
+ const Slapi_DN *local_dn = slapi_entry_get_sdn_const(e);
+ /* First check if the entry is for us */
+ is_ours = is_subject_of_agreemeent_local(e, prp->agmt);
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
+ "%s: windows_process_total_entry: Looking dn=\"%s\" (%s)\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(slapi_entry_get_sdn_const(e)), is_ours ? "ours" : "not ours");
+ if (is_ours)
+ {
+ retval = map_entry_dn_outbound(e,&remote_dn,prp,&missing_entry);
+ if (retval || NULL == remote_dn)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "%s: windows_replay_update: failed map dn for total update dn=\"%s\"\n",
+ agmt_get_long_name(prp->agmt), slapi_sdn_get_dn(local_dn));
+ goto error;
+ }
+ /* Either the entry is a tombstone, or not a tombstone */
+ if (is_tombstone)
+ {
+ retval = windows_process_total_delete(prp,e,remote_dn);
+ } else
+ {
+ retval = windows_process_total_add(prp,e,remote_dn);
+ }
+ }
+ if (remote_dn)
+ {
+ slapi_sdn_free(&remote_dn);
+ }
+error:
+ return retval;
+}
+
+int
+windows_search_local_entry_by_uniqueid(Private_Repl_Protocol *prp, const char *uniqueid, char ** attrs, Slapi_Entry **ret_entry , void * component_identity)
+{
+ Slapi_Entry **entries = NULL;
+ Slapi_PBlock *int_search_pb = NULL;
+ int rc = 0;
+ char *filter_string = NULL;
+ const Slapi_DN *local_subtree = NULL;
+
+ *ret_entry = NULL;
+ local_subtree = windows_private_get_directory_subtree(prp->agmt);
+ filter_string = PR_smprintf("(&(|(objectclass=*)(objectclass=ldapsubentry)(objectclass=nsTombstone))(nsUniqueid=%s))",uniqueid);
+ 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,
+ attrs ,
+ 0 /* attrsonly */, NULL /* controls */,
+ NULL /* uniqueid */,
+ component_identity, 0 /* actions */ );
+ slapi_search_internal_pb ( int_search_pb );
+ slapi_pblock_get( int_search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc );
+ if ( LDAP_SUCCESS == rc ) {
+ slapi_pblock_get( int_search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
+ if ( NULL != entries && NULL != entries[ 0 ]) {
+ Slapi_Entry *temp_entry = NULL;
+ temp_entry = entries[ 0 ];
+ *ret_entry = slapi_entry_dup(temp_entry);
+ } else {
+ /* No entry there */
+ rc = LDAP_NO_SUCH_OBJECT;
+ }
+ }
+ slapi_free_search_results_internal(int_search_pb);
+ slapi_pblock_destroy(int_search_pb);
+ int_search_pb = NULL;
+ if (filter_string)
+ {
+ PR_smprintf_free(filter_string);
+ }
+ return rc;
+}
+
+static int
+windows_get_local_entry_by_uniqueid(Private_Repl_Protocol *prp,const char* uniqueid,Slapi_Entry **local_entry)
+{
+ int retval = ENTRY_NOTFOUND;
+ Slapi_Entry *new_entry = NULL;
+ windows_search_local_entry_by_uniqueid( prp, uniqueid, NULL, &new_entry,
+ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION));
+ if (new_entry)
+ {
+ *local_entry = new_entry;
+ retval = 0;
+ }
+ return retval;
+}
+
+static int
+windows_get_local_entry(const Slapi_DN* local_dn,Slapi_Entry **local_entry)
+{
+ int retval = ENTRY_NOTFOUND;
+ Slapi_Entry *new_entry = NULL;
+ slapi_search_internal_get_entry( (Slapi_DN*)local_dn, NULL, &new_entry,
+ repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION));
+ if (new_entry)
+ {
+ *local_entry = new_entry;
+ retval = 0;
+ }
+ return retval;
+}
+
+static int
+windows_process_dirsync_entry(Private_Repl_Protocol *prp,Slapi_Entry *e, int is_total)
+{
+ Slapi_DN* local_sdn = NULL;
+ int rc = 0;
+
+ /* deleted users are outside the 'correct container'.
+ They live in cn=deleted objects, windows_private_get_directory_subtree( prp->agmt) */
+
+ if (is_tombstone(e))
+ {
+ rc = map_tombstone_dn_inbound(e, &local_sdn, prp->agmt);
+ if ((0 == rc) && local_sdn)
+ {
+ /* Go ahead and delte the local peer */
+ rc = windows_delete_local_entry(local_sdn);
+ slapi_sdn_free(&local_sdn);
+ } else
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,"%s: windows_process_dirsync_entry: failed to map tombstone dn.\n",agmt_get_long_name(prp->agmt));
+ }
+ } else
+ {
+ /* Is this entry one we should be interested in ? */
+ if (is_subject_of_agreemeent_remote(e,prp->agmt))
+ {
+ /* First make its local DN */
+ rc = map_entry_dn_inbound(e, &local_sdn, prp->agmt);
+ if ((0 == rc) && local_sdn)
+ {
+ Slapi_Entry *local_entry = NULL;
+ /* Get the local entry if it exists */
+ rc = windows_get_local_entry(local_sdn,&local_entry);
+ if ((0 == rc) && local_entry)
+ {
+ /* Since the entry exists we should now make it match the entry we received from AD */
+ rc = windows_update_local_entry(prp, e, local_entry);
+ slapi_entry_free(local_entry);
+ if (rc) {
+ /* Something bad happened */
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"%s: windows_process_dirsync_entry: failed to update inbound entry.\n",agmt_get_long_name(prp->agmt));
+ }
+ } else
+ {
+ /* If it doesn't exist, try to make it */
+ windows_create_local_entry(prp,e,local_sdn);
+ }
+ slapi_sdn_free(&local_sdn);
+ } else
+ {
+ /* We should have been able to map the DN, so this is an error */
+ slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name,"%s: windows_process_dirsync_entry: failed to map inbound entry.\n",agmt_get_long_name(prp->agmt));
+ }
+ } /* subject of agreement */
+ } /* is tombstone */
+ return rc;
+}
+
+void
+windows_dirsync_inc_run(Private_Repl_Protocol *prp)
+ {
+
+ int rc = 0;
+ int msgid=0;
+ Slapi_PBlock *pb = NULL;
+ Slapi_Filter *filter_user = NULL;
+ Slapi_Filter *filter_user_deleted = NULL;
+ Slapi_Filter *filter_group = NULL;
+ Slapi_Filter *filter_group_deleted = NULL;
+ int done = 0;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_dirsync_inc_run\n", 0, 0, 0 );
+ while (!done) {
+
+ Slapi_Entry *e = NULL;
+ int filter_ret = 0;
+ PRBool create_users_from_dirsync = windows_private_create_users(prp->agmt);
+
+ rc = send_dirsync_search(prp->conn);
+ if (rc != CONN_OPERATION_SUCCESS)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
+ "failed to send dirsync search request: %d\n", rc);
+ goto error;
+ }
+
+ while ( (e = windows_conn_get_search_result(prp->conn) ) != NULL)
+ {
+ rc = windows_process_dirsync_entry(prp,e,0);
+ if (e)
+ {
+ slapi_entry_free(e);
+ }
+ } /* While entry != NULL */
+ if (!windows_private_dirsync_has_more(prp->agmt))
+ {
+ done = 1;
+ }
+ } /* While !done */
+error:
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_dirsync_inc_run\n", 0, 0, 0 );
+}
+
diff --git a/ldap/servers/plugins/replication/windows_replica.c b/ldap/servers/plugins/replication/windows_replica.c
deleted file mode 100644
index fc86cbdd..00000000
--- a/ldap/servers/plugins/replication/windows_replica.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-/** BEGIN COPYRIGHT BLOCK
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-/* repl5_replica.c */
-
-#include "slapi-plugin.h"
-#include "repl.h" /* ONREPL - this is bad */
-#include "repl5.h"
-#include "windowsrepl.h"
-#include "repl_shared.h"
-#include "csnpl.h"
-#include "cl5_api.h"
-
-/* from proto-slap.h */
-int g_get_shutdown();
-
-#define RUV_SAVE_INTERVAL (30 * 1000) /* 30 seconds */
-#define START_UPDATE_DELAY 2 /* 2 second */
-#define START_REAP_DELAY 3600 /* 1 hour */
-
-#define REPLICA_RDN "cn=windowsreplica"
-#define CHANGELOG_RDN "cn=legacy changelog"
-
-/*
- * A replica is a locally-held copy of a portion of the DIT.
- */
-struct replica {
- Slapi_DN *repl_root; /* top of the replicated area */
- char *repl_name; /* unique replica name */
- PRBool new_name; /* new name was generated - need to be saved */
- ReplicaUpdateDNList updatedn_list; /* list of dns with which a supplier should bind
- to update this replica */
- ReplicaType repl_type; /* is this replica read-only ? */
- PRBool legacy_consumer; /* if true, this replica is supplied by 4.0 consumer */
- char* legacy_purl; /* partial url of the legacy supplier */
- ReplicaId repl_rid; /* replicaID */
- Object *repl_ruv; /* replica update vector */
- PRBool repl_ruv_dirty; /* Dirty flag for ruv */
- CSNPL *min_csn_pl; /* Pending list for minimal CSN */
- void *csn_pl_reg_id; /* registration assignment for csn callbacks */
- unsigned long repl_state_flags; /* state flags */
- PRUint32 repl_flags; /* persistent, externally visible flags */
- PRLock *repl_lock; /* protects entire structure */
- Slapi_Eq_Context repl_eqcxt_rs; /* context to cancel event that saves ruv */
- Slapi_Eq_Context repl_eqcxt_tr; /* context to cancel event that reaps tombstones */
- Object *repl_csngen; /* CSN generator for this replica */
- PRBool repl_csn_assigned; /* Flag set when new csn is assigned. */
- PRUint32 repl_purge_delay; /* When purgeable, CSNs are held on to for this many extra seconds */
- PRBool tombstone_reap_stop; /* TRUE when the tombstone reaper should stop */
- PRBool tombstone_reap_active; /* TRUE when the tombstone reaper is running */
- long tombstone_reap_interval; /* Time in seconds between tombstone reaping */
- Slapi_ValueSet *repl_referral; /* A list of administrator provided referral URLs */
- PRBool state_update_inprogress; /* replica state is being updated */
- PRLock *agmt_lock; /* protects agreement creation, start and stop */
- char *locking_purl; /* supplier who has exclusive access */
-
-
- Object *consumer_repl_ruv; /* tracks location in changelog for changes to send to active directoroy */
-
-};
-
-
-typedef struct reap_callback_data
-{
- int rc;
- unsigned long num_entries;
- unsigned long num_purged_entries;
- CSN *purge_csn;
- PRBool *tombstone_reap_stop;
-} reap_callback_data;
-
-
-
-
-/* Forward declarations of helper functions*/
-static Slapi_Entry* _windows_replica_get_config_entry (const Slapi_DN *root);
-static int _windows_replica_check_validity (const Replica *r);
-static int _windows_replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext);
-static int __replica_update_entry (Replica *r, Slapi_Entry *e, char *errortext);
-static int __replica_configure_ruv (Replica *r, PRBool isLocked);
-static void _windows_replica_update_state (time_t when, void *arg);
-static char * _replica_get_config_dn (const Slapi_DN *root);
-static char * __replica_type_as_string (const Replica *r);
-static int replica_create_ruv_tombstone(Replica *r);
-static void assign_csn_callback(const CSN *csn, void *data);
-static void abort_csn_callback(const CSN *csn, void *data);
-static void eq_cb_reap_tombstones(time_t when, void *arg);
-static CSN *_replica_get_purge_csn_nolock (const Replica *r);
-static void replica_get_referrals_nolock (const Replica *r, char ***referrals);
-static void replica_clear_legacy_referrals (const Slapi_DN *repl_root_sdn, char **referrals, const char *state);
-static void replica_remove_legacy_attr (const Slapi_DN *repl_root_sdn, const char *attr);
-static int replica_log_ruv_elements_nolock (const Replica *r);
-static void replica_replace_ruv_tombstone(Replica *r);
-static void start_agreements_for_replica (Replica *r, PRBool start);
-void replica_consumer_set_ruv (Replica *r, RUV *ruv) ;
-
-/* PRBool */
-/* replica_is_state_flag_set(Replica *r, PRInt32 flag) */
-/* { */
-/* PR_ASSERT(r); */
-/* if (r) */
-/* return (r->repl_state_flags & flag); */
-/* else */
-/* return PR_FALSE; */
-/* } */
-
-/* Replica * */
-/* windows_replica_new(const Slapi_DN *root) */
-/* { */
-/* Replica *r = NULL; */
-/* Slapi_Entry *e = NULL; */
-/* char errorbuf[BUFSIZ]; */
-/* char ebuf[BUFSIZ]; */
-
-/* PR_ASSERT (root); */
-
-/* /\* check if there is a replica associated with the tree *\/ */
-/* e = _windows_replica_get_config_entry (root); */
-/* if (e) */
-/* { */
-/* errorbuf[0] = '\0'; */
-/* r = windows_replica_new_from_entry(e, errorbuf, */
-/* PR_FALSE /\* not a newly added entry *\/); */
-
-/* if (NULL == r) */
-/* { */
-/* slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "Unable to " */
-/* "configure replica %s: %s\n", */
-/* escape_string(slapi_sdn_get_dn(root), ebuf), */
-/* errorbuf); */
-/* } */
-
-/* slapi_entry_free (e); */
-/* } */
-
-/* return r; */
-/* } */
-
-/*
-int windows_replica_start_agreement
-(Replica *r, Repl_Agmt *ra)
-{
- int ret = 0;
-
- if (r == NULL) return -1;
-
- PR_Lock(r->agmt_lock);
-
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "windows_replica_start_agreement: state_flag =%d\n",
- !replica_is_state_flag_set(r, REPLICA_AGREEMENTS_DISABLED));
-
-
- if (!replica_is_state_flag_set(r, REPLICA_AGREEMENTS_DISABLED)) {
- ret = windows_agmt_start(ra);
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "windows_replica_start_agreement: rc=%d\n", ret);
- ret = 0;
- }
-
- PR_Unlock(r->agmt_lock);
-
- return ret;
-} */
-
-
-/*
- * A callback function registed as op->o_replica_attr_handler and
- * called by backend ops to get replica attributes.
- */
-int
-__replica_get_attr ( Slapi_PBlock *pb, const char* type, void *value )
-{
- int rc = -1;
-
- Object *replica_obj;
- replica_obj = replica_get_replica_for_op (pb);
- if (NULL != replica_obj)
- {
- Replica *replica = (Replica*) object_get_data (replica_obj);
- if ( NULL != replica )
- {
- if (strcasecmp (type, type_replicaTombstonePurgeInterval) == 0)
- {
- *((int*)value) = replica->tombstone_reap_interval;
- rc = 0;
- }
- else if (strcasecmp (type, type_replicaPurgeDelay) == 0)
- {
- *((int*)value) = replica->repl_purge_delay;
- rc = 0;
- }
- }
- object_release (replica_obj);
- }
-
- return rc;
-}
-
-
-static Slapi_Entry*
-_windows_replica_get_config_entry (const Slapi_DN *root)
-{
- int rc = 0;
- char *dn = NULL;
- Slapi_Entry **entries;
- Slapi_Entry *e = NULL;
- Slapi_PBlock *pb = NULL;
-
- dn = _replica_get_config_dn (root);
- pb = slapi_pblock_new ();
-
- slapi_search_internal_set_pb (pb, dn, LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, NULL,
- NULL, repl_get_plugin_identity (PLUGIN_WINDOWS_REPLICATION), 0);
- slapi_search_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc == 0)
- {
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- e = slapi_entry_dup (entries [0]);
- }
-
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy (pb);
- slapi_ch_free_string(&dn);
-
- return e;
-}
-
-
-static char*
-_replica_get_config_dn (const Slapi_DN *root)
-{
- char *dn;
- const char *mp_base = slapi_get_mapping_tree_config_root ();
- int len;
-
- PR_ASSERT (root);
-
- len = strlen (REPLICA_RDN) + strlen (slapi_sdn_get_dn (root)) +
- strlen (mp_base) + 8; /* 8 = , + cn= + \" + \" + , + \0 */
-
- dn = (char*)slapi_ch_malloc (len);
- sprintf (dn, "%s,cn=\"%s\",%s", REPLICA_RDN, slapi_sdn_get_dn (root), mp_base);
-
- return dn;
-}
-
-Replica *
-windows_replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation)
-{
- int rc = 0;
- Replica *r;
- RUV *ruv;
- RUV *consumer_ruv;
- char *repl_name = NULL;
-
- if (e == NULL)
- {
- if (NULL != errortext)
- {
- sprintf (errortext, "NULL entry");
- }
- return NULL;
- }
-
- r = (Replica *)slapi_ch_calloc(1, sizeof(Replica));
-
- if ((r->repl_lock = PR_NewLock()) == NULL)
- {
- if (NULL != errortext)
- {
- sprintf (errortext, "failed to create replica lock");
- }
- rc = -1;
- goto done;
- }
-
- if ((r->agmt_lock = PR_NewLock()) == NULL)
- {
- if (NULL != errortext)
- {
- sprintf (errortext, "failed to create replica lock");
- }
- rc = -1;
- goto done;
- }
-
- /* read parameters from the replica config entry */
- rc = _windows_replica_init_from_config (r, e, errortext);
- if (rc != 0)
- {
- goto done;
- }
-
- /* configure ruv */
- rc = __replica_configure_ruv (r, PR_FALSE);
- if (rc != 0)
- {
- goto done;
- }
-
- /* If smallest csn exists in RUV for our local replica, it's ok to begin iteration */
- ruv = (RUV*) object_get_data (r->repl_ruv); //XXX
- PR_ASSERT (ruv);
-
- consumer_ruv = ruv_dup(ruv);
- replica_consumer_set_ruv(r, consumer_ruv);
-
- if (is_add_operation)
- {
- /*
- * This is called by an ldap add operation.
- * Update the entry to contain information generated
- * during replica initialization
- */
- rc = __replica_update_entry (r, e, errortext);
- }
- else
- {
- /*
- * Entry is already in dse.ldif - update it on the disk
- * (done by the update state event scheduled below)
- */
- }
- if (rc != 0)
- goto done;
-
- /* ONREPL - the state update can occur before the entry is added to the DIT.
- In that case the updated would fail but nothing bad would happen. The next
- scheduled update would save the state */
- repl_name = slapi_ch_strdup (r->repl_name);
- r->repl_eqcxt_rs = slapi_eq_repeat(_windows_replica_update_state, repl_name,
- current_time () + START_UPDATE_DELAY, RUV_SAVE_INTERVAL);
-
- if (r->tombstone_reap_interval > 0)
- {
- /*
- * Reap Tombstone should be started some time after the plugin started.
- * This will allow the server to fully start before consuming resources.
- */
- repl_name = slapi_ch_strdup (r->repl_name);
- // XXX r->repl_eqcxt_tr = slapi_eq_repeat(eq_cb_reap_tombstones, repl_name, current_time() + START_REAP_DELAY, 1000 * r->tombstone_reap_interval);
- }
-
- if (r->legacy_consumer)
- {
- char ebuf[BUFSIZ];
-
- legacy_consumer_init_referrals (r);
- slapi_log_error(SLAPI_LOG_REPL, windows_repl_plugin_name, "replica_new_from_entry: "
- "replica for %s was configured as legacy consumer\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf));
- }
-
-done:
- if (rc != 0 && r)
- {
- replica_destroy ((void**)&r);
- }
-
- return r;
-
-
-
-}
-
-static int
-_windows_replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext)
-{
- int rc;
- Slapi_Attr *attr;
- char *val;
- CSNGen *gen;
- char buf [BUFSIZ];
- char *errormsg = errortext? errortext : buf;
- Slapi_Attr *a = NULL;
- char dnescape[BUFSIZ]; /* for escape_string */
-
- PR_ASSERT (r && e);
-
- /* get replica root */
- val = slapi_entry_attr_get_charptr (e, attr_replicaRoot);
- if (val == NULL)
- {
- sprintf (errormsg, "failed to retrieve %s attribute from (%s)\n",
- attr_replicaRoot,
- escape_string((char*)slapi_entry_get_dn ((Slapi_Entry*)e), dnescape));
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "_replica_init_from_config: %s\n",
- errormsg);
-
- return -1;
- }
-
- r->repl_root = slapi_sdn_new_dn_passin (val);
-
- /* get replica type */
- val = slapi_entry_attr_get_charptr (e, attr_replicaType);
- if (val)
- {
- r->repl_type = atoi(val);
- slapi_ch_free ((void**)&val);
- }
- else
- {
- r->repl_type = REPLICA_TYPE_READONLY;
- }
-
- /* get legacy consumer flag */
- val = slapi_entry_attr_get_charptr (e, type_replicaLegacyConsumer);
- if (val)
- {
- if (strcasecmp (val, "on") == 0 || strcasecmp (val, "yes") == 0 ||
- strcasecmp (val, "true") == 0 || strcasecmp (val, "1") == 0)
- {
- r->legacy_consumer = PR_TRUE;
- }
- else
- {
- r->legacy_consumer = PR_FALSE;
- }
-
- slapi_ch_free ((void**)&val);
- }
- else
- {
- r->legacy_consumer = PR_FALSE;
- }
-
- /* get replica flags */
- r->repl_flags = slapi_entry_attr_get_ulong(e, attr_flags);
-
- /* get replicaid */
- /* the replica id is ignored for read only replicas and is set to the
- special value READ_ONLY_REPLICA_ID */
- if (r->repl_type == REPLICA_TYPE_READONLY)
- {
- r->repl_rid = READ_ONLY_REPLICA_ID;
- slapi_entry_attr_set_uint(e, attr_replicaId, (unsigned int)READ_ONLY_REPLICA_ID);
- }
- /* a replica id is required for updatable and primary replicas */
- else if (r->repl_type == REPLICA_TYPE_UPDATABLE ||
- r->repl_type == REPLICA_TYPE_PRIMARY)
- {
- if ((val = slapi_entry_attr_get_charptr (e, attr_replicaId)))
- {
- int temprid = atoi (val);
- slapi_ch_free ((void**)&val);
- if (temprid <= 0 || temprid >= READ_ONLY_REPLICA_ID)
- {
-/* sprintf (errormsg, */
-/* "attribute %s must have a value greater than 0 " */
-/* "and less than %d: entry %s", */
-/* attr_replicaId, READ_ONLY_REPLICA_ID, */
-/* escape_string((char*)slapi_entry_get_dn ((Slapi_Entry*)e), */
-/* dnescape)); */
-/* slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, */
-/* "_replica_init_from_config: %s\n", */
-/* errormsg); */
-/* return -1; */
- }
- else
- {
- r->repl_rid = (ReplicaId)temprid;
- }
- }
- else
- {
- sprintf (errormsg, "failed to retrieve required %s attribute from %s",
- attr_replicaId,
- escape_string((char*)slapi_entry_get_dn ((Slapi_Entry*)e),
- dnescape));
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "_replica_init_from_config: %s\n",
- errormsg);
- return -1;
- }
- }
-
- attr = NULL;
- rc = slapi_entry_attr_find(e, attr_state, &attr);
- gen = csngen_new (r->repl_rid, attr);
- if (gen == NULL)
- {
- sprintf (errormsg, "failed to create csn generator for replica (%s)",
- escape_string((char*)slapi_entry_get_dn ((Slapi_Entry*)e),
- dnescape));
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "_replica_init_from_config: %s\n",
- errormsg);
- return -1;
- }
- r->repl_csngen = object_new((void*)gen, (FNFree)csngen_free);
-
- /* Hook generator so we can maintain min/max CSN info */
- r->csn_pl_reg_id = csngen_register_callbacks(gen, assign_csn_callback, r, abort_csn_callback, r);
-
- /* get replication bind dn */
- r->updatedn_list = replica_updatedn_list_new(e);
-
- /* get replica name */
- val = slapi_entry_attr_get_charptr (e, attr_replicaName);
- if (val) {
- r->repl_name = val;
- }
- else
- {
- rc = slapi_uniqueIDGenerateString (&r->repl_name);
- if (rc != UID_SUCCESS)
- {
- sprintf (errormsg, "failed to assign replica name for replica (%s); "
- "uuid generator error - %d ",
- escape_string((char*)slapi_entry_get_dn ((Slapi_Entry*)e), dnescape),
- rc);
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "_replica_init_from_config: %s\n",
- errormsg);
- return -1;
- }
- else
- r->new_name = PR_TRUE;
- }
-
- /* get the list of referrals */
- slapi_entry_attr_find( e, attr_replicaReferral, &attr );
- if(attr!=NULL)
- {
- slapi_attr_get_valueset(attr, &r->repl_referral);
- }
-
- /*
- * Set the purge offset (default 7 days). This is the extra
- * time we allow purgeable CSNs to stick around, in case a
- * replica regresses. Could also be useful when LCUP happens,
- * since we don't know about LCUP replicas, and they can just
- * turn up whenever they want to.
- */
- if (slapi_entry_attr_find(e, type_replicaPurgeDelay, &a) == -1)
- {
- /* No purge delay provided, so use default */
- r->repl_purge_delay = 60 * 60 * 24 * 7; /* One week, in seconds */
- }
- else
- {
- r->repl_purge_delay = slapi_entry_attr_get_uint(e, type_replicaPurgeDelay);
- }
-
- if (slapi_entry_attr_find(e, type_replicaTombstonePurgeInterval, &a) == -1)
- {
- /* No reap interval provided, so use default */
- r->tombstone_reap_interval = 3600 * 24; /* One day */
- }
- else
- {
- r->tombstone_reap_interval = slapi_entry_attr_get_int(e, type_replicaTombstonePurgeInterval);
- }
-
- r->tombstone_reap_stop = r->tombstone_reap_active = PR_FALSE;
-
- return (_windows_replica_check_validity (r));
-}
-
-
-static int
-_windows_replica_check_validity (const Replica *r)
-{
- PR_ASSERT (r);
-
- if (r->repl_root == NULL || r->repl_type == 0 ||
- r->repl_rid > MAX_REPLICA_ID || r->repl_name == NULL)
- {
- return -1;
- }
- else
- {
- return 0;
- }
-}
-
-
-/* NOTE - this is the only non-api function that performs locking because
- it is called by the event queue */
-static void
-_windows_replica_update_state (time_t when, void *arg)
-{
- int rc;
- const char *replica_name = (const char *)arg;
- Object *replica_object = NULL;
- Replica *r;
- Slapi_Mod smod;
- LDAPMod *mods[3];
- Slapi_PBlock *pb = NULL;
- char *dn = NULL;
-
- if (NULL == replica_name)
- return;
-
- /*
- * replica_get_by_name() will acquire the replica object
- * and that could prevent the replica from being destroyed
- * until the object_release is called.
- */
- replica_object = replica_get_by_name(replica_name);
- if (NULL == replica_object)
- {
- return;
- }
-
- /* We have a reference, so replica won't vanish on us. */
- r = (Replica *)object_get_data(replica_object);
- if (NULL == r)
- {
- goto done;
- }
-
- PR_Lock(r->repl_lock);
-
- /* replica state is currently being updated
- or no CSN was assigned - bail out */
- if (r->state_update_inprogress)
- {
- PR_Unlock(r->repl_lock);
- goto done;
- }
-
- /* This might be a consumer */
- if (!r->repl_csn_assigned)
- {
- /* EY: the consumer needs to flush ruv to disk. */
- PR_Unlock(r->repl_lock);
- replica_write_ruv(r);
- goto done;
- }
-
- /* ONREPL update csn generator state of an updatable replica only */
- /* ONREPL state always changes because we update time every second and
- we write state to the disk less frequently */
- rc = csngen_get_state ((CSNGen*)object_get_data (r->repl_csngen), &smod);
- if (rc != 0)
- {
- PR_Unlock(r->repl_lock);
- goto done;
- }
-
- r->state_update_inprogress = PR_TRUE;
- r->repl_csn_assigned = PR_FALSE;
-
- dn = _replica_get_config_dn (r->repl_root);
- pb = slapi_pblock_new();
- mods[0] = (LDAPMod*)slapi_mod_get_ldapmod_byref(&smod);
-
- /* we don't want to held lock during operations since it causes lock contention
- and sometimes deadlock. So releasing lock here */
-
- PR_Unlock(r->repl_lock);
-
- /* replica repl_name and new_name attributes do not get changed once
- the replica is configured - so it is ok that they are outside replica lock */
-
- /* write replica name if it has not been written before */
- if (r->new_name)
- {
- struct berval *vals[2];
- struct berval val;
- LDAPMod mod;
-
- mods[1] = &mod;
-
- mod.mod_op = LDAP_MOD_REPLACE;
- mod.mod_type = (char*)attr_replicaName;
- mod.mod_bvalues = vals;
- vals [0] = &val;
- vals [1] = NULL;
- val.bv_val = r->repl_name;
- val.bv_len = strlen (val.bv_val);
- mods[2] = NULL;
- }
- else
- {
- mods[1] = NULL;
- }
-
- slapi_modify_internal_set_pb (pb, dn, mods, NULL, NULL,
- repl_get_plugin_identity (PLUGIN_WINDOWS_REPLICATION), 0);
- slapi_modify_internal_pb (pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc != LDAP_SUCCESS)
- {
- char ebuf[BUFSIZ];
-
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "_replica_update_state: "
- "failed to update state of csn generator for replica %s: LDAP "
- "error - %d\n", escape_string(slapi_sdn_get_dn(r->repl_root),ebuf), rc);
- }
- else
- {
- r->new_name = PR_FALSE;
- }
-
- /* update RUV - performs its own locking */
- replica_write_ruv (r);
-
- /* since this is the only place this value is changed and we are
- guaranteed that only one thread enters the function, its ok
- to change it outside replica lock */
- r->state_update_inprogress = PR_FALSE;
-
- slapi_ch_free ((void**)&dn);
- slapi_pblock_destroy (pb);
- slapi_mod_done (&smod);
-
-done:
- if (replica_object)
- object_release (replica_object);
-}
-
-
-/* this function is called during server startup for each replica
- to check whether the replica's data was reloaded offline and
- whether replica's changelog needs to be reinitialized */
-
-/* the function does not use replica lock but all functions it calls are
- thread safe. Locking replica lock while calling changelog functions
- causes a deadlock because changelog calls replica functions that
- that lock the same lock */
-int windows_replica_check_for_data_reload (Replica *r, void *arg)
-{
- int rc = 0;
- RUV *upper_bound_ruv = NULL;
- RUV *r_ruv = NULL;
- Object *r_obj, *ruv_obj;
- int cl_cover_be, be_cover_cl;
-
- PR_ASSERT (r);
-
- /* check that we have a changelog and if this replica logs changes */
- if (cl5GetState () == CL5_STATE_OPEN && r->repl_flags & REPLICA_LOG_CHANGES)
- {
- /* Compare new ruv to the purge ruv. If the new contains csns which
- are smaller than those in purge ruv, we need to remove old and
- create new changelog file for this replica. This is because we
- will not have sufficient changes to incrementally update a consumer
- to the current state of the supplier. */
-
- rc = cl5GetUpperBoundRUV (r, &upper_bound_ruv);
- if (rc != CL5_SUCCESS && rc != CL5_NOTFOUND)
- {
- return -1;
- }
-
- if (upper_bound_ruv)
- {
- ruv_obj = replica_get_ruv (r);
- r_ruv = object_get_data (ruv_obj);
- PR_ASSERT (r_ruv);
-
- /* Compare new ruv to the changelog's upper bound ruv. We could only keep
- the existing changelog if its upper bound is the same as replica's RUV.
- This is because if changelog has changes not in RUV, they will be
- eventually sent to the consumer's which will cause a state mismatch
- (because the supplier does not actually contain the changes in its data store.
- If, on the other hand, the changelog is not as up to date as the supplier,
- it is not really useful since out of sync consumer's can't be brought
- up to date using this changelog and hence will need to be reinitialized */
-
- /*
- * Actually we can ignore the scenario that the changelog's upper
- * bound ruv covers data store's ruv for two reasons: (1) a change
- * is always written to the changelog after it is committed to the
- * data store; (2) a change will be ignored if the server has seen
- * it before - this happens frequently at the beginning of replication
- * sessions.
- */
-
- be_cover_cl = ruv_covers_ruv (r_ruv, upper_bound_ruv);
- cl_cover_be = ruv_covers_ruv (upper_bound_ruv, r_ruv);
- if (!cl_cover_be)
- {
- /* the data was reloaded and we can no longer use existing changelog */
- char ebuf[BUFSIZ];
-
- /* create a temporary replica object to conform to the interface */
- r_obj = object_new (r, NULL);
-
- /* We can't use existing changelog - remove existing file */
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "replica_check_for_data_reload: "
- "Warning: data for replica %s was reloaded and it no longer matches the data "
- "in the changelog (replica data %s changelog). Recreating the changelog file. This could affect replication "
- "with replica's consumers in which case the consumers should be reinitialized.\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf),
- ((!be_cover_cl && !cl_cover_be) ? "<>" : (!be_cover_cl ? "<" : ">")) );
-
- rc = cl5DeleteDBSync (r_obj);
-
- object_release (r_obj);
-
- if (rc == CL5_SUCCESS)
- {
- /* log changes to mark starting point for replication */
- rc = replica_log_ruv_elements (r);
- }
- }
-
- object_release (ruv_obj);
- }
- else /* we have no changes currently logged for this replica */
- {
- /* log changes to mark starting point for replication */
- rc = replica_log_ruv_elements (r);
- }
- }
-
- if (rc == 0)
- {
- /* reset mapping tree referrals based on new local RUV */
- // consumer5_set_mapping_tree_state_for_replica(r, NULL);
- }
-
- if (upper_bound_ruv)
- ruv_destroy (&upper_bound_ruv);
-
- return rc;
-}
-
-/* This function updates the entry to contain information generated
- during replica initialization.
- Returns 0 if successful and -1 otherwise */
-static int
-__replica_update_entry (Replica *r, Slapi_Entry *e, char *errortext)
-{
- int rc;
- Slapi_Mod smod;
- Slapi_Value *val;
-
- PR_ASSERT (r);
-
- /* add attribute that stores state of csn generator */
- rc = csngen_get_state ((CSNGen*)object_get_data (r->repl_csngen), &smod);
- if (rc != CSN_SUCCESS)
- {
- sprintf (errortext, "failed to get csn generator's state; csn error - %d", rc);
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_update_entry: %s\n", errortext);
- return -1;
- }
-
- val = slapi_value_new_berval(slapi_mod_get_first_value(&smod));
-
- rc = slapi_entry_add_value (e, slapi_mod_get_type (&smod), val);
-
- slapi_value_free(&val);
- slapi_mod_done (&smod);
-
- if (rc != 0)
- {
- sprintf (errortext, "failed to update replica entry");
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_update_entry: %s\n", errortext);
- return -1;
- }
-
- /* add attribute that stores replica name */
- rc = slapi_entry_add_string (e, attr_replicaName, r->repl_name);
- if (rc != 0)
- {
- sprintf (errortext, "failed to update replica entry");
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_update_entry: %s\n", errortext);
- return -1;
- }
- else
- r->new_name = PR_FALSE;
-
- return 0;
-}
-
-
-/* This function retrieves RUV from the root of the replicated tree.
- * The attribute can be missing if
- * (1) this replica is the first supplier and replica generation has not been assigned
- * or
- * (2) this is a consumer that has not been yet initialized
- * In either case, replica_set_ruv should be used to further initialize the replica.
- * Returns 0 on success, -1 on failure. If 0 is returned, the RUV is present in the replica.
- */
-static int
-__replica_configure_ruv (Replica *r, PRBool isLocked)
-{
- Slapi_PBlock *pb = NULL;
- char *attrs[2];
- int rc;
- int return_value = -1;
- Slapi_Entry **entries = NULL;
- Slapi_Attr *attr;
- RUV *ruv = NULL;
- CSN *csn = NULL;
- ReplicaId rid = 0;
- char ebuf[BUFSIZ];
-
- /* read ruv state from the ruv tombstone entry */
- pb = slapi_pblock_new();
- attrs[0] = (char*)type_ruvElement;
- attrs[1] = NULL;
- slapi_search_internal_set_pb(
- pb,
- slapi_sdn_get_dn(r->repl_root),
- LDAP_SCOPE_BASE,
- "objectclass=*",
- attrs,
- 0, /* attrsonly */
- NULL, /* controls */
- RUV_STORAGE_ENTRY_UNIQUEID,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
- OP_FLAG_REPLICATED); /* flags */
- slapi_search_internal_pb (pb);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc == LDAP_SUCCESS)
- {
- /* get RUV attributes and construct the RUV */
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
- if (NULL == entries || NULL == entries[0])
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_configure_ruv: replica ruv tombstone entry for "
- "replica %s not found\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf));
- goto done;
- }
-
- rc = slapi_entry_attr_find(entries[0], type_ruvElement, &attr);
- if (rc != 0) /* ruv attribute is missing - this not allowed */
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_configure_ruv: replica ruv tombstone entry for "
- "replica %s does not contain %s\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf), type_ruvElement);
- goto done;
- }
-
- /* Check in the tombstone we have retrieved if the local purl is
- already present:
- rid == 0: the local purl is not present
- rid != 0: the local purl is present ==> nothing to do
- */
- ruv_init_from_slapi_attr_and_check_purl (attr, &ruv, &rid);
- if (ruv)
- {
- char *generation = NULL;
- generation = ruv_get_replica_generation(ruv);
- if (NULL != generation)
- {
- r->repl_ruv = object_new((void*)ruv, (FNFree)ruv_destroy);
-
- /* Is the local purl in the ruv? (the port or the host could have
- changed)
- */
- /* A consumer only doesn't have its purl in its ruv */
- if (r->repl_type == REPLICA_TYPE_UPDATABLE)
- {
- int need_update = 0;
- if (rid == 0)
- {
- /* We can not have more than 1 ruv with the same rid
- so we replace it */
- const char *purl = NULL;
-
- purl = multimaster_get_local_purl();
- ruv_delete_replica(ruv, r->repl_rid);
- ruv_add_index_replica(ruv, r->repl_rid, purl, 1);
- need_update = 1; /* ruv changed, so write tombstone */
- }
- else /* bug 540844: make sure the local supplier rid is first in the ruv */
- {
- /* make sure local supplier is first in list */
- ReplicaId first_rid = 0;
- char *first_purl = NULL;
- ruv_get_first_id_and_purl(ruv, &first_rid, &first_purl);
- /* if the local supplier is not first in the list . . . */
- if (rid != first_rid)
- {
- /* . . . move the local supplier to the beginning of the list */
- ruv_move_local_supplier_to_first(ruv, rid);
- need_update = 1; /* must update tombstone also */
- }
- }
-
- /* Update also the directory entry */
- if (need_update) {
- /* richm 20010821 bug 556498
- replica_replace_ruv_tombstone acquires the repl_lock, so release
- the lock then reacquire it if locked */
- if (isLocked) PR_Unlock(r->repl_lock);
- replica_replace_ruv_tombstone(r);
- if (isLocked) PR_Lock(r->repl_lock);
- }
- }
-
- slapi_ch_free((void **)&generation);
- return_value = 0;
- }
- else
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "RUV for replica %s is missing replica generation\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf));
- goto done;
- }
- }
- else
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "Unable to convert %s attribute in entry %s to a replica update vector.\n",
- type_ruvElement, escape_string(slapi_sdn_get_dn(r->repl_root),ebuf));
- goto done;
- }
-
- }
- else /* search failed */
- {
- if (LDAP_NO_SUCH_OBJECT == rc)
- {
- /* The entry doesn't exist: create it */
- rc = replica_create_ruv_tombstone(r);
- if (LDAP_SUCCESS != rc)
- {
- /*
- * XXXggood - the following error appears on startup if we try
- * to initialize replica RUVs before the backend instance is up.
- * It's alarming to see this error, and we should suppress it
- * (or avoid trying to configure it) if the backend instance is
- * not yet online.
- */
- /*
- * XXXrichm - you can also get this error when the backend is in
- * read only mode c.f. bug 539782
- */
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_configure_ruv: failed to create replica ruv tombstone "
- "entry (%s); LDAP error - %d\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf), rc);
- goto done;
- }
- else
- {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "_replica_configure_ruv: No ruv tombstone found for replica %s. "
- "Created a new one\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf));
- return_value = 0;
- }
- }
- else
- {
- /* see if the suffix is disabled */
- char *state = slapi_mtn_get_state(r->repl_root);
- if (state && !strcasecmp(state, "disabled"))
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_configure_ruv: replication disabled for "
- "entry (%s); LDAP error - %d\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf), rc);
- slapi_ch_free_string(&state);
- goto done;
- }
- else if (!r->repl_ruv) /* other error */
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
- "_replica_configure_ruv: replication broken for "
- "entry (%s); LDAP error - %d\n",
- escape_string(slapi_sdn_get_dn(r->repl_root),ebuf), rc);
- slapi_ch_free_string(&state);
- goto done;
- }
- else /* some error but continue anyway? */
- {
- slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
- "_replica_configure_ruv: Error %d reading tombstone for replica %s.\n",
- rc, escape_string(slapi_sdn_get_dn(r->repl_root),ebuf));
- return_value = 0;
- }
- slapi_ch_free_string(&state);
- }
- }
-
- if (NULL != r->min_csn_pl)
- {
- csnplFree (&r->min_csn_pl);
- }
-
- /* create pending list for min csn if necessary */
- if (ruv_get_smallest_csn_for_replica ((RUV*)object_get_data (r->repl_ruv),
- r->repl_rid, &csn) == RUV_SUCCESS)
- {
- csn_free (&csn);
- r->min_csn_pl = NULL;
- }
- else
- {
- /*
- * The local replica has not generated any of its own CSNs yet.
- * We need to watch CSNs being generated and note the first
- * locally-generated CSN that's committed. Once that event occurs,
- * the RUV is suitable for iteration over locally generated
- * changes.
- */
- r->min_csn_pl = csnplNew();
- }
-
-done:
- if (NULL != pb)
- {
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy (pb);
- }
- if (return_value != 0)
- {
- if (ruv)
- ruv_destroy (&ruv);
- }
-
- return return_value;
-}
-
-/* Update the tombstone entry to reflect the content of the ruv */
-static void
-replica_replace_ruv_tombstone(Replica *r)
-{
- Slapi_PBlock *pb = NULL;
- char *dn;
- int rc;
-
- Slapi_Mod smod;
- Slapi_Mod smod_last_modified;
- LDAPMod *mods [3];
-
- PR_ASSERT(NULL != r && NULL != r->repl_root);
-
- PR_Lock(r->repl_lock);
-
- PR_ASSERT (r->repl_ruv);
- ruv_to_smod ((RUV*)object_get_data(r->repl_ruv), &smod);
- ruv_last_modified_to_smod ((RUV*)object_get_data(r->repl_ruv), &smod_last_modified);
-
- dn = _replica_get_config_dn (r->repl_root);
- mods[0] = (LDAPMod*)slapi_mod_get_ldapmod_byref(&smod);
- mods[1] = (LDAPMod*)slapi_mod_get_ldapmod_byref(&smod_last_modified);
-
- PR_Unlock (r->repl_lock);
-
- mods [2] = NULL;
- pb = slapi_pblock_new();
-
- slapi_modify_internal_set_pb(
- pb,
- (char*)slapi_sdn_get_dn (r->repl_root), /* only used to select be */
- mods,
- NULL, /* controls */
- RUV_STORAGE_ENTRY_UNIQUEID,
- repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
- OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP);
-
- slapi_modify_internal_pb (pb);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
-
- if (rc != LDAP_SUCCESS)
- {
- if ((rc != LDAP_NO_SUCH_OBJECT) || !replica_is_state_flag_set(r, REPLICA_IN_USE))
- {
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_replace_ruv_tombstone: "
- "failed to update replication update vector for replica %s: LDAP "
- "error - %d\n", (char*)slapi_sdn_get_dn (r->repl_root), rc);
- }
- }
-
- slapi_ch_free ((void**)&dn);
- slapi_pblock_destroy (pb);
- slapi_mod_done (&smod);
- slapi_mod_done (&smod_last_modified);
-}
-
-
-/*
- * Returns refcounted object that contains RUV. The caller should release the
- * object once it is no longer used. To release, call object_release
- */
-Object *
-replica_consumer_get_ruv (const Replica *r)
-{
- Object *ruv = NULL;
-
- PR_ASSERT(r);
- // PR_ASSERT (r->repl_ruv);
-
- object_acquire (r->consumer_repl_ruv);
- ruv = r->consumer_repl_ruv;
-
- return ruv;
-}
-
-void
-replica_consumer_set_ruv (Replica *r, RUV *ruv)
-{
- PR_ASSERT(r);
- PR_ASSERT(ruv);
-
- if(NULL != r->consumer_repl_ruv)
- {
- object_release(r->consumer_repl_ruv);
- }
-
- r->consumer_repl_ruv = object_new((void*)ruv, (FNFree)ruv_destroy);
-}
diff --git a/ldap/servers/plugins/replication/windows_tot_protocol.c b/ldap/servers/plugins/replication/windows_tot_protocol.c
index d6da5a7c..f81a2bf8 100644
--- a/ldap/servers/plugins/replication/windows_tot_protocol.c
+++ b/ldap/servers/plugins/replication/windows_tot_protocol.c
@@ -12,11 +12,12 @@
*/
-#include "windowsrepl.h"
-#include "windows_prot_private.h"
+
#include "repl.h"
#include "repl5.h"
-#include "repl5_prot_private.h"
+#include "windowsrepl.h"
+#include "windows_prot_private.h"
+#include "slap.h"
/* Private data structures */
typedef struct windows_tot_private
@@ -65,6 +66,8 @@ windows_tot_run(Private_Repl_Protocol *prp)
CSN *remote_schema_csn = NULL;
PRBool cookie_has_more = PR_TRUE;
RUV *ruv = NULL;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_tot_run\n", 0, 0, 0 );
PR_ASSERT(NULL != prp);
@@ -80,7 +83,7 @@ windows_tot_run(Private_Repl_Protocol *prp)
/* acquire remote replica */
agmt_set_last_init_start(prp->agmt, current_time());
- rc = windows_acquire_replica (prp, &ruv);
+ rc = windows_acquire_replica (prp, &ruv, 0 /* don't check RUV for total protocol */);
/* We never retry total protocol, even in case a transient error.
This is because if somebody already updated the replica we don't
want to do it again */
@@ -108,16 +111,17 @@ windows_tot_run(Private_Repl_Protocol *prp)
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "Beginning total update of replica "
"\"%s\".\n", agmt_get_long_name(prp->agmt));
- windows_private_null_dirsync_control(prp->agmt);
+ windows_private_null_dirsync_cookie(prp->agmt);
/* get everything */
windows_dirsync_inc_run(prp);
cookie_has_more = windows_private_dirsync_has_more(prp->agmt);
+ windows_private_save_dirsync_cookie(prp->agmt);
/* send everything */
- dn = slapi_sdn_get_dn( windows_private_get_directory_replarea(prp->agmt));
+ dn = slapi_sdn_get_dn( windows_private_get_directory_subtree(prp->agmt));
pb = slapi_pblock_new ();
slapi_search_internal_set_pb (pb, dn, /* XXX modify the searchfilter and scope? */
@@ -155,6 +159,7 @@ windows_tot_run(Private_Repl_Protocol *prp)
done:
prp->stopped = 1;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_tot_run\n", 0, 0, 0 );
}
static int
@@ -164,6 +169,8 @@ windows_tot_stop(Private_Repl_Protocol *prp)
int seconds = 600;
PRIntervalTime start, maxwait, now;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_tot_stop\n", 0, 0, 0 );
+
prp->terminate = 1;
maxwait = PR_SecondsToInterval(seconds);
start = PR_IntervalNow();
@@ -188,6 +195,8 @@ windows_tot_stop(Private_Repl_Protocol *prp)
return_value = 0;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_tot_stop\n", 0, 0, 0 );
+
return return_value;
}
@@ -197,6 +206,8 @@ static int
windows_tot_status(Private_Repl_Protocol *prp)
{
int return_value = 0;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_tot_status\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_tot_status\n", 0, 0, 0 );
return return_value;
}
@@ -205,6 +216,8 @@ windows_tot_status(Private_Repl_Protocol *prp)
static void
windows_tot_noop(Private_Repl_Protocol *prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_tot_noop\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_tot_noop\n", 0, 0, 0 );
/* noop */
}
@@ -214,6 +227,9 @@ Windows_Tot_Protocol_new(Repl_Protocol *rp)
{
windows_tot_private *rip = NULL;
Private_Repl_Protocol *prp = (Private_Repl_Protocol *)slapi_ch_malloc(sizeof(Private_Repl_Protocol));
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> Windows_Tot_Protocol_new\n", 0, 0, 0 );
+
prp->delete = windows_tot_delete;
prp->run = windows_tot_run;
prp->stop = windows_tot_stop;
@@ -241,22 +257,28 @@ Windows_Tot_Protocol_new(Repl_Protocol *rp)
rip->rp = rp;
prp->private = (void *)rip;
prp->replica_acquired = PR_FALSE;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= Windows_Tot_Protocol_new\n", 0, 0, 0 );
return prp;
loser:
windows_tot_delete(&prp);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= Windows_Tot_Protocol_new - loser\n", 0, 0, 0 );
return NULL;
}
static void
windows_tot_delete(Private_Repl_Protocol **prp)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_tot_delete\n", 0, 0, 0 );
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_tot_delete\n", 0, 0, 0 );
}
static
void get_result (int rc, void *cb_data)
{
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> get_result\n", 0, 0, 0 );
PR_ASSERT (cb_data);
((callback_data*)cb_data)->rc = rc;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= get_result\n", 0, 0, 0 );
}
static
@@ -265,11 +287,12 @@ int send_entry (Slapi_Entry *e, void *cb_data)
int rc;
Private_Repl_Protocol *prp;
- // struct berval *bv;
unsigned long *num_entriesp;
time_t *sleep_on_busyp;
time_t *last_busyp;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> send_entry\n", 0, 0, 0 );
+
PR_ASSERT (cb_data);
prp = ((callback_data*)cb_data)->prp;
@@ -283,40 +306,23 @@ int send_entry (Slapi_Entry *e, void *cb_data)
conn_disconnect(prp->conn);
prp->stopped = 1;
((callback_data*)cb_data)->rc = -1;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= send_entry\n", 0, 0, 0 );
return -1;
}
- /* skip ruv tombstone - need to do this because it might be
- more up to date then the data we are sending to the client.
- RUV is sent separately via the protocol */
- if (is_ruv_tombstone_entry (e))
+ /* skip ruv tombstone - not relvant to Active Directory */
+ if (is_ruv_tombstone_entry (e)) {
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= send_entry\n", 0, 0, 0 );
return 0;
+ }
- do {
/* push the entry to the consumer */
- rc = add_or_modify_user(e);
+ rc = windows_process_total_entry(prp,e);
- if (rc == CONN_BUSY) {
- time_t now = current_time ();
- if ((now - *last_busyp) < (*sleep_on_busyp + 10)) {
- *sleep_on_busyp +=5;
- }
- else {
- *sleep_on_busyp = 5;
- }
- *last_busyp = now;
-
- slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name,
- "Replica \"%s\" is busy. Waiting %ds while"
- " it finishes processing its current import queue\n",
- agmt_get_long_name(prp->agmt), *sleep_on_busyp);
- DS_Sleep(PR_SecondsToInterval(*sleep_on_busyp));
- }
- }
- while (rc == CONN_BUSY);
-
(*num_entriesp)++;
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= send_entry\n", 0, 0, 0 );
+
if (CONN_OPERATION_SUCCESS == rc) {
return 0;
} else {
diff --git a/ldap/servers/plugins/replication/windows_total.c b/ldap/servers/plugins/replication/windows_total.c
index 6af9d3f9..0c2435c2 100644
--- a/ldap/servers/plugins/replication/windows_total.c
+++ b/ldap/servers/plugins/replication/windows_total.c
@@ -5,42 +5,9 @@
* END COPYRIGHT BLOCK **/
-/*
- repl5_total.c - code that implements a total replica update.
-
- The requestValue of the NSDS50ReplicationEntry looks like this:
-
- requestValue ::= SEQUENCE {
- uniqueid OCTET STRING,
- dn LDAPDN,
- annotatedAttributes AnnotatedAttributeList
- }
-
- AnnotatedAttributeList ::= SET OF SEQUENCE {
- attributeType AttributeDescription,
- attributeDeletionCSN OCTET STRING OPTIONAL,
- attributeDeleted BOOLEAN DEFAULT FALSE,
- annotatedValues SET OF AnnotatedValue
- }
-
- AnnotatedValue ::= SEQUENCE {
- value AttributeValue,
- valueDeleted BOOLEAN DEFAULT FALSE,
- valueCSNSet SEQUENCE OF ValueCSN,
- }
-
- ValueCSN ::= SEQUENCE {
- CSNType ENUMERATED {
- valuePresenceCSN (1),
- valueDeletionCSN (2),
- valueDistinguishedCSN (3)
- }
- CSN OCTET STRING,
- }
-*/
#include "repl5.h"
-#include "windowsrepl.h"
+#include "slap.h"
#define CSN_TYPE_VALUE_UPDATED_ON_WIRE 1
#define CSN_TYPE_VALUE_DELETED_ON_WIRE 2
@@ -72,6 +39,8 @@ my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
int rc = -1;
int csn_type_as_ber = -1;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> my_ber_printf_csn\n", 0, 0, 0 );
+
switch (t)
{
case CSN_TYPE_VALUE_UPDATED:
@@ -88,6 +57,7 @@ my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
default:
slapi_log_error(SLAPI_LOG_FATAL, windows_repl_plugin_name, "my_ber_printf_csn: unknown "
"csn type %d encountered.\n", (int)t);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_printf_csn\n", 0, 0, 0 );
return -1;
}
@@ -106,6 +76,8 @@ my_ber_printf_csn(BerElement *ber, const CSN *csn, const CSNType t)
BER_DEBUG("{e(csn type)s(csn)}");
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_printf_csn\n", 0, 0, 0 );
+
return rc;
}
@@ -123,6 +95,8 @@ my_ber_printf_value(BerElement *ber, const char *type, const Slapi_Value *value,
CSN *csn;
CSNType t;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> my_ber_printf_value\n", 0, 0, 0 );
+
bval = slapi_value_get_berval(value);
BER_DEBUG("{o(value)");
if (ber_printf(ber, "{o", bval->bv_val, bval->bv_len) == -1) /* Start sequence */
@@ -183,6 +157,7 @@ my_ber_printf_value(BerElement *ber, const char *type, const Slapi_Value *value,
rc = 0;
done:
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_printf_value\n", 0, 0, 0 );
return rc;
}
@@ -195,6 +170,8 @@ my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted)
char *type;
int i;
const CSN *csn;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> my_ber_printf_attr\n", 0, 0, 0 );
/* First, send the type */
slapi_attr_get_type(attr, &type);
@@ -272,8 +249,10 @@ my_ber_printf_attr (BerElement *ber, Slapi_Attr *attr, PRBool deleted)
goto loser;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_printf_attr\n", 0, 0, 0 );
return 0;
loser:
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_printf_attr - loser\n", 0, 0, 0 );
return -1;
}
@@ -292,6 +271,8 @@ my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
CSNType csntype;
char *lasti;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> my_ber_scanf_value\n", 0, 0, 0 );
+
PR_ASSERT(ber && value && deleted);
*value = NULL;
@@ -377,6 +358,7 @@ my_ber_scanf_value(BerElement *ber, Slapi_Value **value, PRBool *deleted)
if (attrval)
ber_bvfree(attrval);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_scanf_value\n", 0, 0, 0 );
return 0;
loser:
@@ -389,7 +371,7 @@ loser:
{
slapi_value_free (value);
}
-
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_scanf_value - loser\n", 0, 0, 0 );
return -1;
}
@@ -406,6 +388,8 @@ my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
int rc;
Slapi_Value *value;
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> my_ber_scanf_attr\n", 0, 0, 0 );
+
PR_ASSERT (ber && attr && deleted);
/* allocate the attribute */
@@ -495,6 +479,7 @@ my_ber_scanf_attr (BerElement *ber, Slapi_Attr **attr, PRBool *deleted)
goto loser;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_scanf_attr\n", 0, 0, 0 );
return 0;
loser:
if (*attr)
@@ -502,6 +487,7 @@ loser:
if (value)
slapi_value_free (&value);
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= my_ber_scanf_attr - loser\n", 0, 0, 0 );
return -1;
}
@@ -525,6 +511,8 @@ decode_total_update_extop(Slapi_PBlock *pb, Slapi_Entry **ep)
unsigned long tag;
int rc;
PRBool deleted;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> decode_total_update_extop\n", 0, 0, 0 );
PR_ASSERT(NULL != pb);
PR_ASSERT(NULL != ep);
@@ -645,6 +633,7 @@ free_and_return:
ber_free(tmp_bere, 1);
tmp_bere = NULL;
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= decode_total_update_extop\n", 0, 0, 0 );
return rc;
}
@@ -659,6 +648,8 @@ ___multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
Slapi_Entry *e = NULL;
Slapi_Connection *conn = NULL;
int connid, opid;
+
+ LDAPDebug( LDAP_DEBUG_TRACE, "=> ___multimaster_extop_NSDS50ReplicationEntry\n", 0, 0, 0 );
connid = 0;
slapi_pblock_get(pb, SLAPI_CONN_ID, &connid);
@@ -723,5 +714,7 @@ ___multimaster_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb)
}
}
+ LDAPDebug( LDAP_DEBUG_TRACE, "<= ___multimaster_extop_NSDS50ReplicationEntry\n", 0, 0, 0 );
+
return rc;
}
diff --git a/ldap/servers/plugins/replication/windowsrepl.h b/ldap/servers/plugins/replication/windowsrepl.h
index 88ad1d41..8379dc6c 100644
--- a/ldap/servers/plugins/replication/windowsrepl.h
+++ b/ldap/servers/plugins/replication/windowsrepl.h
@@ -4,247 +4,28 @@
* All rights reserved.
* END COPYRIGHT BLOCK **/
-/* repl5.h - 5.0 replication header */
-#include "repl.h"
-#include "repl5.h"
-
-#ifndef _WINDOWSREPL5_H_
-#define _WINDOWSREPL5_H_
-
-#include <limits.h>
-#include <time.h>
-#include <stdio.h>
-
-#undef REPL_PLUGIN_NAME
-#define REPL_PLUGIN_NAME "WindowsSyncPlugin"
-#define WINDOWS_REPL_PLUGIN_NAME REPL_PLUGIN_NAME
-
-char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);
-#include <string.h>
-#ifndef _WIN32
-#include <sys/param.h>
-#endif /* _WIN32 */
-
-#include "portable.h" /* GGOODREPL - is this cheating? */
-#include "repl_shared.h"
-#include "llist.h"
-#include "repl5_ruv.h"
-#include "cl4.h"
-
-
-/* Attribute names for replication agreement attributes */
-extern const char *type_nsdsWindowsReplicaCookie;
-extern char *windows_repl_plugin_name;
-
-/* windows plugin points */
-int windows_preop_bind (Slapi_PBlock *pb);
-int windows_preop_add (Slapi_PBlock *pb);
-int windows_preop_delete (Slapi_PBlock *pb);
-int windows_preop_modify (Slapi_PBlock *pb);
-int windows_preop_modrdn (Slapi_PBlock *pb);
-int windows_preop_search (Slapi_PBlock *pb);
-int windows_preop_compare (Slapi_PBlock *pb);
-int windows_bepreop_add (Slapi_PBlock *pb);
-int windows_bepreop_delete (Slapi_PBlock *pb);
-int windows_bepreop_modify (Slapi_PBlock *pb);
-int windows_bepreop_modrdn (Slapi_PBlock *pb);
-int windows_bepostop_modrdn (Slapi_PBlock *pb);
-int windows_bepostop_delete (Slapi_PBlock *pb);
-int windows_postop_bind (Slapi_PBlock *pb);
-int windows_postop_add (Slapi_PBlock *pb);
-int windows_postop_delete (Slapi_PBlock *pb);
-int windows_postop_modify (Slapi_PBlock *pb);
-int windows_postop_modrdn (Slapi_PBlock *pb);
-
-/* In repl5_init.c */
-char* get_thread_private_agmtname ();
-void set_thread_private_agmtname (const char *agmtname);
-void* get_thread_private_cache ();
-void set_thread_private_cache (void *buf);
-char* get_repl_session_id (Slapi_PBlock *pb, char *id, CSN **opcsn);
-
-/* In repl_extop.c */
-int windows_extop_StartNSDS50ReplicationRequest(Slapi_PBlock *pb);
-int windows_extop_EndNSDS50ReplicationRequest(Slapi_PBlock *pb);
-int extop_noop(Slapi_PBlock *pb);
-struct berval *NSDS50StartReplicationRequest_new(const char *protocol_oid,
- const char *repl_root, char **extra_referrals, CSN *csn);
-struct berval *NSDS50EndReplicationRequest_new(char *repl_root);
-int decode_repl_ext_response(struct berval *data, int *response_code,
- struct berval ***ruv_bervals);
-
-/* extension construct/destructor */
-void* windows_operation_extension_constructor (void *object, void *parent);
-void windows_operation_extension_destructor (void* ext,void *object, void *parent);
-void* windows_consumer_operation_extension_constructor (void *object, void *parent);
-void windows_consumer_operation_extension_destructor (void* ext,void *object, void *parent);
-void windows_mtnode_extension_destructor (void* ext, void *object, void *parent);
-void *windows_mtnode_extension_constructor (void *object, void *parent);
-
-
-
-
-
-typedef struct windows_operation_extension
-{
- int prevent_recursive_call;
- struct slapi_operation_parameters *operation_parameters;
- char *repl_gen;
-} windows_operation_extension;
-
-/* windows_ext.c */
-void windows_repl_sup_init_ext ();
-void windows_repl_con_init_ext ();
-int windows_repl_sup_register_ext (ext_type type); // never used?
-int windows_repl_con_register_ext (ext_type type); // never used
-void* windows_repl_sup_get_ext (ext_type type, void *object);
-void* windows_repl_con_get_ext (ext_type type, void *object);
-
-
-
-/* In repl5_total.c */
-int windows_extop_NSDS50ReplicationEntry(Slapi_PBlock *pb);
-
-/* In repl_controls.c */
-int create_NSDS50ReplUpdateInfoControl(const char *uuid,
- const char *superior_uuid, const CSN *csn,
- LDAPMod **modify_mods, LDAPControl **ctrlp);
-void destroy_NSDS50ReplUpdateInfoControl(LDAPControl **ctrlp);
-int decode_NSDS50ReplUpdateInfoControl(LDAPControl **controlsp,
- char **uuid, char **newsuperior_uuid, CSN **csn, LDAPMod ***modrdn_mods);
-
-/* In repl5_replsupplier.c */
-/* typedef struct repl_supplier Repl_Supplier; */
-Repl_Supplier *replsupplier_init(Slapi_Entry *e);
-void replsupplier_configure(Repl_Supplier *rs, Slapi_PBlock *pb);
-void replsupplier_start(Repl_Supplier *rs);
-void replsupplier_stop(Repl_Supplier *rs);
-void replsupplier_destroy(Repl_Supplier **rs);
-void replsupplier_notify(Repl_Supplier *rs, PRUint32 eventmask);
-PRUint32 replsupplier_get_status(Repl_Supplier *rs);
-
-/* In repl5_plugins.c */
-int windows_set_local_purl();
-const char *windows_get_local_purl();
-PRBool windows_started();
-
-/* In repl5_schedule.c */
-/* typedef struct schedule Schedule; */
-/* typedef void (*window_state_change_callback)(void *arg, PRBool opened); */
-Schedule *schedule_new(window_state_change_callback callback_fn, void *callback_arg, const char *session_id);
-void schedule_destroy(Schedule *s);
-int schedule_set(Schedule *sch, Slapi_Attr *attr);
-char **schedule_get(Schedule *sch);
-int schedule_in_window_now(Schedule *sch);
-PRTime schedule_next(Schedule *sch);
-int schedule_notify(Schedule *sch, Slapi_PBlock *pb);
-void schedule_set_priority_attributes(Schedule *sch, char **prio_attrs, int override_schedule);
-void schedule_set_startup_delay(Schedule *sch, size_t startup_delay);
-void schedule_set_maximum_backlog(Schedule *sch, size_t max_backlog);
-void schedule_notify_session(Schedule *sch, PRTime session_end_time, unsigned int flags);
-#define REPLICATION_SESSION_SUCCESS 0
-
-/* In repl5_bos.c */
-/* typedef struct repl_bos Repl_Bos; */
-
-/* In repl5_agmt.c */
-/* typedef struct repl5agmt Repl_Agmt; */
-/* #define TRANSPORT_FLAG_SSL 1 */
-/* #define TRANSPORT_FLAG_TLS 2 */
-/* #define BINDMETHOD_SIMPLE_AUTH 1 */
-/* #define BINDMETHOD_SSL_CLIENTAUTH 2 */
-Repl_Agmt *windows_agmt_new_from_entry(Slapi_Entry *e);
-/* Repl_Agmt *agmt_new_from_pblock(Slapi_PBlock *pb); */
-/* void agmt_delete(void **ra); */
-/* const Slapi_DN *agmt_get_dn_byref(const Repl_Agmt *ra); */
-/* int agmt_get_auto_initialize(const Repl_Agmt *ra); */
-/* long agmt_get_timeout(const Repl_Agmt *ra); */
-/* long agmt_get_busywaittime(const Repl_Agmt *ra); */
-/* long agmt_get_pausetime(const Repl_Agmt *ra); */
-int windows_agmt_start(Repl_Agmt *ra);
-int windows_agmt_stop(Repl_Agmt *ra);
-/* int agmt_replicate_now(Repl_Agmt *ra); */
-/* char *agmt_get_hostname(const Repl_Agmt *ra); */
-/* int agmt_get_port(const Repl_Agmt *ra); */
-/* PRUint32 agmt_get_transport_flags(const Repl_Agmt *ra); */
-/* char *agmt_get_binddn(const Repl_Agmt *ra); */
-/* struct berval *agmt_get_credentials(const Repl_Agmt *ra); */
-/* int agmt_get_bindmethod(const Repl_Agmt *ra); */
-Slapi_DN *windows_agmt_get_replarea(const Repl_Agmt *ra);
-/* int agmt_is_fractional(const Repl_Agmt *ra); */
-/* int agmt_is_fractional_attr(const Repl_Agmt *ra, const char *attrname); */
-/* int agmt_is_50_mm_protocol(const Repl_Agmt *ra); */
-/* int agmt_matches_name(const Repl_Agmt *ra, const Slapi_DN *name); */
-/* int agmt_replarea_matches(const Repl_Agmt *ra, const Slapi_DN *name); */
-int windows_agmt_schedule_in_window_now(const Repl_Agmt *ra);
-int windows_agmt_set_schedule_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
-/* int agmt_set_timeout_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); */
-/* int agmt_set_busywaittime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); */
-/* int agmt_set_pausetime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); */
-int windows_agmt_set_credentials_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
-/* int agmt_set_binddn_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); */
-/* int agmt_set_bind_method_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); */
-/* int agmt_set_transportinfo_from_entry( Repl_Agmt *ra, const Slapi_Entry *e ); */
-const char *windows_agmt_get_long_name(const Repl_Agmt *ra);
-/* int agmt_initialize_replica(const Repl_Agmt *agmt); */
-/* void agmt_replica_init_done (const Repl_Agmt *agmt); */
-/* void agmt_notify_change(Repl_Agmt *ra, Slapi_PBlock *pb); */
-/* Object* agmt_get_consumer_ruv (Repl_Agmt *ra); */
-/* ReplicaId agmt_get_consumer_rid ( Repl_Agmt *ra, void *conn ); */
-/* int agmt_set_consumer_ruv (Repl_Agmt *ra, RUV *ruv); */
-void windows_agmt_update_consumer_ruv (Repl_Agmt *ra);
-/* CSN* agmt_get_consumer_schema_csn (Repl_Agmt *ra); */
-/* void agmt_set_consumer_schema_csn (Repl_Agmt *ra, CSN *csn); */
-/* void agmt_set_last_update_in_progress (Repl_Agmt *ra, PRBool in_progress); */
-/* void agmt_set_last_update_start (Repl_Agmt *ra, time_t start_time); */
-/* void agmt_set_last_update_end (Repl_Agmt *ra, time_t end_time); */
-/* void agmt_set_last_update_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *msg); */
-/* void agmt_set_update_in_progress (Repl_Agmt *ra, PRBool in_progress); */
-/* void agmt_set_last_init_start (Repl_Agmt *ra, time_t start_time); */
-/* void agmt_set_last_init_end (Repl_Agmt *ra, time_t end_time); */
-/* void agmt_set_last_init_status (Repl_Agmt *ra, int ldaprc, int replrc, const char *msg); */
-/* void agmt_inc_last_update_changecount (Repl_Agmt *ra, ReplicaId rid, int skipped); */
-/* void agmt_get_changecount_string (Repl_Agmt *ra, char *buf, int bufsize); */
-
-/* typedef struct replica Replica; */
-
-/* In repl5_agmtlist.c */
-int windows_agmtlist_config_init();
-void windows_agmtlist_shutdown();
-void windows_agmtlist_notify_all(Slapi_PBlock *pb);
-Object* windows_agmtlist_get_first_agreement_for_replica(Replica *r);
-Object* windows_agmtlist_get_next_agreement_for_replica(Replica *r, Object *prev);
-
-
-/* In repl5_backoff.c */
-/* typedef struct backoff_timer Backoff_Timer; */
-#define BACKOFF_FIXED 1
-#define BACKOFF_EXPONENTIAL 2
-#define BACKOFF_RANDOM 3
-Backoff_Timer *backoff_new(int timer_type, int initial_interval, int max_interval);
-time_t backoff_reset(Backoff_Timer *bt, slapi_eq_fn_t callback, void *callback_data);
-time_t backoff_step(Backoff_Timer *bt);
-int backoff_expired(Backoff_Timer *bt, int margin);
-void backoff_delete(Backoff_Timer **btp);
-
-/* In repl5_connection.c */
-/* typedef struct repl_connection Repl_Connection; */
-/* typedef enum */
-/* { */
-/* CONN_OPERATION_SUCCESS, */
-/* CONN_OPERATION_FAILED, */
-/* CONN_NOT_CONNECTED, */
-/* CONN_SUPPORTS_DS5_REPL, */
-/* CONN_DOES_NOT_SUPPORT_DS5_REPL, */
-/* CONN_SCHEMA_UPDATED, */
-/* CONN_SCHEMA_NO_UPDATE_NEEDED, */
-/* CONN_LOCAL_ERROR, */
-/* CONN_BUSY, */
-/* CONN_SSL_NOT_ENABLED, */
-/* CONN_TIMEOUT */
-/* } ConnResult; */
-
-Repl_Connection *windows_conn_new(Repl_Agmt *agmt);
+/* windows_private.c */
+typedef struct windowsprivate Dirsync_Private;
+Dirsync_Private* windows_private_new();
+void windows_private_set_windows_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn );
+const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra);
+void windows_private_set_directory_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn );
+const Slapi_DN* windows_private_get_directory_subtree (const Repl_Agmt *ra);
+LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra);
+ConnResult send_dirsync_search(Repl_Connection *conn);
+ConnResult windows_search_entry(Repl_Connection *conn, char* searchbase, char *filter, Slapi_Entry **entry);
+Slapi_Entry *windows_conn_get_search_result(Repl_Connection *conn );
+void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **controls );
+PRBool windows_private_dirsync_has_more(const Repl_Agmt *ra);
+void windows_private_null_dirsync_cookie(const Repl_Agmt *ra);
+int windows_private_save_dirsync_cookie(const Repl_Agmt *ra);
+int windows_private_load_dirsync_cookie(const Repl_Agmt *ra);
+void windows_private_set_create_users(const Repl_Agmt *ra, PRBool value);
+PRBool windows_private_create_users(const Repl_Agmt *ra);
+const char *windows_private_get_windows_domain(const Repl_Agmt *ra);
+static void windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain);
+
+/* in windows_connection.c */
ConnResult windows_conn_connect(Repl_Connection *conn);
void windows_conn_disconnect(Repl_Connection *conn);
void windows_conn_delete(Repl_Connection *conn);
@@ -272,113 +53,3 @@ ConnResult windows_conn_push_schema(Repl_Connection *conn, CSN **remotecsn);
void windows_conn_set_timeout(Repl_Connection *conn, long timeout);
void windows_conn_set_agmt_changed(Repl_Connection *conn);
-
-
-/* In repl5_protocol.c */
-typedef struct windows_repl_protocol Windows_Repl_Protocol;
-Repl_Protocol *protocol_new(Repl_Agmt *agmt, int protocol_state);
-void protocol_start(Repl_Protocol *rp);
-
-Repl_Agmt *protocol_get_agreement(Repl_Protocol *rp);
-/* initiate total protocol */
-void protocol_initialize_replica(Repl_Protocol *rp);
-/* stop protocol session in progress */
-void protocol_stop(Repl_Protocol *rp);
-void protocol_free(Repl_Protocol **rpp);
-void protocol_delete(Repl_Protocol **rpp);
-PRBool protocol_set_active_protocol (Repl_Protocol *rp, PRBool total);
-void protocol_clear_active_protocol (Repl_Protocol *rp);
-Repl_Connection *protocol_get_connection(Repl_Protocol *rp);
-void protocol_resume(Repl_Protocol *rp, int wakeup_action);
-void protocol_notify_update(Repl_Protocol *rp);
-void protocol_notify_agmt_changed(Repl_Protocol *rp, char * agmt_name);
-void protocol_notify_window_opened (Repl_Protocol *rp);
-void protocol_notify_window_closed (Repl_Protocol *rp);
-Object *protocol_get_replica_object(Repl_Protocol *rp);
-void protocol_replicate_now(Repl_Protocol *rp);
-
-/* In repl5_replica.c */
-/* typedef enum */
-/* { */
-/* REPLICA_TYPE_UNKNOWN, */
-/* REPLICA_TYPE_PRIMARY, */
-/* REPLICA_TYPE_READONLY, */
-/* REPLICA_TYPE_UPDATABLE, */
-/* REPLICA_TYPE_END */
-/* } ReplicaType; */
-
-/* #define RUV_STORAGE_ENTRY_UNIQUEID "ffffffff-ffffffff-ffffffff-ffffffff" */
-/* #define START_ITERATION_ENTRY_UNIQUEID "00000000-00000000-00000000-00000000" */
-/* #define START_ITERATION_ENTRY_DN "cn=start iteration" */
-
-/* typedef int (*FNEnumReplica) (Replica *r, void *arg); */
-
-/* this function should be called to construct the replica object
- from the data already in the DIT */
- Replica *windows_replica_new(const Slapi_DN *root);
-
-#define REPLICA_IN_USE 1 /* The replica is busy */
-#define REPLICA_INCREMENTAL_IN_PROGRESS 2 /* Set only between start and stop inc */
-#define REPLICA_TOTAL_IN_PROGRESS 4 /* Set only between start and stop total */
-#define REPLICA_AGREEMENTS_DISABLED 8 /* Replica is offline */
-PRBool replica_is_state_flag_set(Replica *r, PRInt32 flag);
-void replica_set_state_flag (Replica *r, PRUint32 flag, PRBool clear);
-void replica_enable_replication (Replica *r);
-void replica_disable_replication (Replica *r, Object *r_obj);
-int windows_replica_start_agreement(Replica *r, Repl_Agmt *ra);
-
-CSN* replica_generate_next_csn ( Slapi_PBlock *pb, const CSN *basecsn );
-int replica_get_attr ( Slapi_PBlock *pb, const char *type, void *value );
-
-/* mapping tree extensions manipulation */
-void windows_mtnode_extension_init ();
-void windows_mtnode_extension_destroy ();
-void windows_mtnode_construct_replicas ();
-
-void windows_be_state_change (void *handle, char *be_name, int old_be_state, int new_be_state);
-
-/* In repl5_replica_config.c */
-int windows_replica_config_init();
-void windows_replica_config_destroy ();
-
-/* replutil.c */
-LDAPControl* create_managedsait_control ();
-LDAPControl* create_backend_control(Slapi_DN *sdn);
-void repl_set_mtn_state_and_referrals(const Slapi_DN *sdn, const char *mtn_state,
- const RUV *ruv, char **ruv_referrals,
- char **other_referrals);
-void repl_set_repl_plugin_path(const char *path);
-
-/* repl5_updatedn_list.c */
-/* typedef void *ReplicaUpdateDNList; */
-/* typedef int (*FNEnumDN)(Slapi_DN *dn, void *arg); */
-ReplicaUpdateDNList replica_updatedn_list_new(const Slapi_Entry *entry);
-void replica_updatedn_list_free(ReplicaUpdateDNList list);
-void replica_updatedn_list_replace(ReplicaUpdateDNList list, const Slapi_ValueSet *vs);
-void replica_updatedn_list_delete(ReplicaUpdateDNList list, const Slapi_ValueSet *vs);
-void replica_updatedn_list_add(ReplicaUpdateDNList list, const Slapi_ValueSet *vs);
-PRBool replica_updatedn_list_ismember(ReplicaUpdateDNList list, const Slapi_DN *dn);
-char *replica_updatedn_list_to_string(ReplicaUpdateDNList list, const char *delimiter);
-void replica_updatedn_list_enumerate(ReplicaUpdateDNList list, FNEnumDN fn, void *arg);
-
-
-/* windows_private.c */
-PRBool windows_private_dirsync_has_more(const Repl_Agmt *ra);
-
-/* windows_protocol.c */
-int add_or_modify_user(Slapi_Entry *e);
-
-
-void repl5_set_debug_timeout(const char *val);
-
-typedef struct windows_mtnode_extension
-{
- Object *replica;
-} windows_mtnode_extension;
-
-
-
-
-
-#endif /* _WINDOWSREPL5_H_ */
-