summaryrefslogtreecommitdiffstats
path: root/ldap/servers/plugins/replication/legacy_consumer.c
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /ldap/servers/plugins/replication/legacy_consumer.c
downloadds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.gz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.tar.xz
ds-b2093e3016027d6b5cf06b3f91f30769bfc099e2.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'ldap/servers/plugins/replication/legacy_consumer.c')
-rw-r--r--ldap/servers/plugins/replication/legacy_consumer.c707
1 files changed, 707 insertions, 0 deletions
diff --git a/ldap/servers/plugins/replication/legacy_consumer.c b/ldap/servers/plugins/replication/legacy_consumer.c
new file mode 100644
index 00000000..8bf45ee1
--- /dev/null
+++ b/ldap/servers/plugins/replication/legacy_consumer.c
@@ -0,0 +1,707 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+/*
+ * repl_legacy_consumer.c - support for legacy replication (consumer-side)
+ *
+ * Support for legacy replication involves correctly dealing with
+ * the addition and removal of attribute types "copiedFrom" and
+ * "copyingFrom". The behavior is:
+ * 1) If a copiedFrom appears in an entry, and that entry is the root
+ * of a replicated area, then put the backend into "refer on update"
+ * mode and install a referral corresponding to the URL contained
+ * in the copiedFrom attribute. This referral overrides the mode
+ * of the replica, e.g. if it was previously an updateable replica,
+ * it now becomes read-only except for the updatedn.
+ * 2) If a copiedFrom disappears from an entry, or the entry containing
+ * the copiedFrom is removed, restore the backend to the state
+ * determined by the DS 5.0 replica configuration.
+ * 3) If a "copyingFrom" referral appears in an entry, and that entry
+ * is the root of a replicated area, then put the backend into
+ * "refer all operations" mode and install a referral corresponding
+ * to the URL contained in the copyingFrom attribute. This referral
+ * overrides the mode of the replica, e.g if it was previously an
+ * updateable replica, it now becomes read-only and refers all
+ * operations except for the updatedn.
+ * 4) If a copyingFrom disappears from an entry, or the entry containing
+ * the copyingFrom is removed, restore the backend to the state
+ * determined by the DS 5.0 replica configuration.
+ */
+
+
+#include "repl5.h"
+#include "repl.h"
+
+/* Forward Declarations */
+static int legacy_consumer_config_add (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
+static int legacy_consumer_config_modify (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
+static int legacy_consumer_config_delete (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
+
+static int legacy_consumer_extract_config(Slapi_Entry* entry, char *returntext);
+static int legacy_consumer_read_config ();
+static void legacy_consumer_encode_pw (Slapi_Entry *e);
+static void set_legacy_purl (Slapi_PBlock *pb, const char *purl);
+static int get_legacy_referral (Slapi_Entry *e, char **referral, char **state);
+
+#define LEGACY_CONSUMER_CONFIG_DN "cn=legacy consumer," REPL_CONFIG_TOP
+#define LEGACY_CONSUMER_FILTER "(objectclass=*)"
+
+/* Configuration parameters local to this module */
+static Slapi_DN *legacy_consumer_replicationdn = NULL;
+static char *legacy_consumer_replicationpw = NULL;
+/* Lock which protects the above config parameters */
+PRRWLock *legacy_consumer_config_lock = NULL;
+
+static PRBool
+target_is_a_replica_root(Slapi_PBlock *pb, const Slapi_DN **root)
+{
+ char *dn;
+ Slapi_DN *sdn;
+ PRBool return_value;
+ Object *repl_obj;
+
+ slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
+ sdn = slapi_sdn_new_dn_byref(dn);
+ repl_obj = replica_get_replica_from_dn(sdn);
+ if (NULL != repl_obj)
+ {
+ Replica *r = object_get_data(repl_obj);
+ *root = replica_get_root(r);
+ return_value = PR_TRUE;
+ object_release(repl_obj);
+ }
+ else
+ {
+ *root = NULL;
+ return_value = PR_FALSE;
+ }
+ slapi_sdn_free(&sdn);
+ return return_value;
+}
+
+
+
+static int
+parse_cfstring(const char *cfstring, char **referral, char **generation, char **lastreplayed)
+{
+ int return_value = -1;
+ char *ref, *gen, *lastplayed;
+
+ if (cfstring != NULL)
+ {
+ char *tmp;
+ char *cfcopy = slapi_ch_strdup(cfstring);
+ ref = cfcopy;
+ tmp = strchr(cfcopy, ' ');
+ if (NULL != tmp)
+ {
+ *tmp++ = '\0';
+ while ('\0' != *tmp && ' ' == *tmp) tmp++;
+ gen = tmp;
+ tmp = strchr(gen, ' ');
+ if (NULL != tmp)
+ {
+ *tmp++ = '\0';
+ while ('\0' != *tmp && ' ' == *tmp) tmp++;
+ lastplayed = tmp;
+ return_value = 0;
+ }
+ }
+
+ if (return_value == 0)
+ {
+ if (referral)
+ *referral = slapi_ch_strdup(ref);
+ if (generation)
+ *generation = slapi_ch_strdup(gen);
+ if (lastreplayed)
+ *lastreplayed = slapi_ch_strdup(lastplayed);
+ }
+ slapi_ch_free((void **)&cfcopy);
+ }
+ return return_value;
+}
+
+
+
+/*
+ * This is called from the consumer post-op plugin point.
+ * It's called if:
+ * 1) The operation is an add or modify operation, and a
+ * copiedfrom/copyingfrom was found in the entry/mods, or
+ * 2) the operation is a delete operation, or
+ * 3) the operation is a moddn operation.
+ */
+
+void
+process_legacy_cf(Slapi_PBlock *pb)
+{
+ consumer_operation_extension *opext;
+ Slapi_Operation *op;
+ char *referral_array[2] = {0};
+ char *referral;
+ char *state;
+ int rc;
+ const Slapi_DN *replica_root_sdn = NULL;
+ Slapi_Entry *e;
+
+ slapi_pblock_get(pb, SLAPI_OPERATION, &op);
+ opext = (consumer_operation_extension*) repl_con_get_ext (REPL_CON_EXT_OP, op);
+
+ if (opext->has_cf)
+ {
+ PR_ASSERT (operation_get_type (op) == SLAPI_OPERATION_ADD ||
+ operation_get_type (op) == SLAPI_OPERATION_MODIFY);
+
+ if ((PR_FALSE == target_is_a_replica_root(pb, &replica_root_sdn)) ||
+ (NULL == replica_root_sdn)){
+ return;
+ }
+
+ slapi_pblock_get (pb, SLAPI_ENTRY_POST_OP, &e);
+ PR_ASSERT (e);
+
+ if (NULL == e)
+ return;
+
+ rc = get_legacy_referral (e, &referral, &state);
+ if (rc == 0)
+ {
+ referral_array[0] = referral;
+ referral_array[1] = NULL;
+ repl_set_mtn_state_and_referrals(replica_root_sdn, state, NULL, NULL,
+ referral_array);
+ /* set partial url in the replica_object */
+ set_legacy_purl (pb, referral);
+
+ slapi_ch_free((void **)&referral);
+ }
+
+ }
+}
+
+void legacy_consumer_be_state_change (void *handle, char *be_name,
+ int old_be_state, int new_be_state)
+{
+ Object *r_obj;
+ Replica *r;
+
+ /* we only interested when a backend is coming online */
+ if (new_be_state == SLAPI_BE_STATE_ON)
+ {
+ r_obj = replica_get_for_backend (be_name);
+ if (r_obj)
+ {
+ r = (Replica*)object_get_data (r_obj);
+ PR_ASSERT (r);
+
+ if (replica_is_legacy_consumer (r))
+ legacy_consumer_init_referrals (r);
+
+ object_release (r_obj);
+ }
+ }
+}
+
+
+static int
+dont_allow_that(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg)
+{
+ *returncode = LDAP_UNWILLING_TO_PERFORM;
+ return SLAPI_DSE_CALLBACK_ERROR;
+}
+
+int
+legacy_consumer_config_init()
+{
+ /* The FE DSE *must* be initialised before we get here */
+ int rc;
+
+ if ((legacy_consumer_config_lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "legacy_consumer_config_lock")) == NULL) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "Failed to create legacy_consumer config read-write lock\n");
+ exit(1);
+ }
+
+ rc = legacy_consumer_read_config ();
+ if (rc != LDAP_SUCCESS)
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
+ "Failed to initialize legacy replication configuration\n");
+ return 1;
+ }
+
+ slapi_config_register_callback(SLAPI_OPERATION_ADD,DSE_FLAG_PREOP,LEGACY_CONSUMER_CONFIG_DN,LDAP_SCOPE_SUBTREE,LEGACY_CONSUMER_FILTER,legacy_consumer_config_add,NULL);
+ slapi_config_register_callback(SLAPI_OPERATION_MODIFY,DSE_FLAG_PREOP,LEGACY_CONSUMER_CONFIG_DN,LDAP_SCOPE_SUBTREE,LEGACY_CONSUMER_FILTER,legacy_consumer_config_modify,NULL);
+ slapi_config_register_callback(SLAPI_OPERATION_MODRDN,DSE_FLAG_PREOP,LEGACY_CONSUMER_CONFIG_DN,LDAP_SCOPE_SUBTREE,LEGACY_CONSUMER_FILTER,dont_allow_that,NULL);
+ slapi_config_register_callback(SLAPI_OPERATION_DELETE,DSE_FLAG_PREOP,LEGACY_CONSUMER_CONFIG_DN,LDAP_SCOPE_SUBTREE,LEGACY_CONSUMER_FILTER,legacy_consumer_config_delete,NULL);
+
+ return 0;
+}
+
+static int
+legacy_consumer_config_add (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
+{
+ int rc;
+
+ rc = legacy_consumer_extract_config(e, returntext);
+ if (rc != LDAP_SUCCESS)
+ {
+ *returncode = rc;
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Failed to configure legacy replication\n");
+ return SLAPI_DSE_CALLBACK_ERROR;
+ }
+ /* make sure that the password is encoded */
+ legacy_consumer_encode_pw(e);
+
+ slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "legacy_consumer_config_add: "
+ "successfully configured legacy consumer credentials\n");
+
+ return SLAPI_DSE_CALLBACK_OK;
+}
+
+#define config_copy_strval( s ) s ? slapi_ch_strdup (s) : NULL;
+
+static int
+legacy_consumer_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg)
+{
+ int rc= 0;
+ LDAPMod **mods;
+ int not_allowed = 0;
+ int i;
+
+ if (returntext)
+ {
+ returntext[0] = '\0';
+ }
+ *returncode = LDAP_SUCCESS;
+
+
+ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
+ PR_RWLock_Wlock (legacy_consumer_config_lock);
+
+ for (i = 0; (mods[i] && (!not_allowed)); i++)
+ {
+ if (mods[i]->mod_op & LDAP_MOD_DELETE)
+ {
+ /* We don't support deleting an attribute from cn=config */
+ }
+ else
+ {
+ int j;
+ for (j = 0; ((mods[i]->mod_values[j]) && (LDAP_SUCCESS == rc)); j++)
+ {
+ char *config_attr, *config_attr_value;
+ int mod_type;
+ config_attr = (char *) mods[i]->mod_type;
+ config_attr_value = (char *) mods[i]->mod_bvalues[j]->bv_val;
+ /* replace existing value */
+ mod_type = mods[i]->mod_op & ~LDAP_MOD_BVALUES;
+ if ( strcasecmp (config_attr, CONFIG_LEGACY_REPLICATIONDN_ATTRIBUTE ) == 0 )
+ {
+ if (legacy_consumer_replicationdn)
+ slapi_sdn_free (&legacy_consumer_replicationdn);
+
+ if (mod_type == LDAP_MOD_REPLACE)
+ {
+ if (config_attr_value)
+ legacy_consumer_replicationdn = slapi_sdn_new_dn_byval (config_attr_value);
+ }
+ else if (mod_type == LDAP_MOD_DELETE)
+ {
+ legacy_consumer_replicationdn = NULL;
+ }
+ else if (mod_type == LDAP_MOD_ADD)
+ {
+ if (legacy_consumer_replicationdn != NULL)
+ {
+ not_allowed = 1;
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
+ "Multiple replicationdns not permitted." );
+ }
+ else
+ {
+ if (config_attr_value)
+ legacy_consumer_replicationdn = slapi_sdn_new_dn_byval (config_attr_value);
+ }
+ }
+ }
+ else if ( strcasecmp ( config_attr, CONFIG_LEGACY_REPLICATIONPW_ATTRIBUTE ) == 0 )
+ {
+ if (mod_type == LDAP_MOD_REPLACE)
+ {
+ legacy_consumer_replicationpw = config_copy_strval(config_attr_value);
+ }
+ else if (mod_type == LDAP_MOD_DELETE)
+ {
+ legacy_consumer_replicationpw = NULL;
+ }
+ else if (mod_type == LDAP_MOD_ADD)
+ {
+ if (legacy_consumer_replicationpw != NULL)
+ {
+ not_allowed = 1;
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
+ "Multiple replicationpws not permitted." );
+ }
+ else
+ {
+ legacy_consumer_replicationpw = config_copy_strval(config_attr_value);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ PR_RWLock_Unlock (legacy_consumer_config_lock);
+
+
+ if (not_allowed)
+ {
+ slapi_log_error( SLAPI_LOG_FATAL, repl_plugin_name,
+ "Failed to modify legacy replication configuration\n" );
+ *returncode= LDAP_CONSTRAINT_VIOLATION;
+ return SLAPI_DSE_CALLBACK_ERROR;
+ }
+
+ /* make sure that the password is encoded */
+ legacy_consumer_encode_pw (e);
+
+ return SLAPI_DSE_CALLBACK_OK;
+}
+
+static int
+legacy_consumer_config_delete (Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg)
+{
+
+ PR_RWLock_Wlock (legacy_consumer_config_lock);
+ if (legacy_consumer_replicationdn)
+ slapi_sdn_free (&legacy_consumer_replicationdn);
+ if (legacy_consumer_replicationpw)
+ slapi_ch_free ((void**)&legacy_consumer_replicationpw);
+
+ legacy_consumer_replicationdn = NULL;
+ legacy_consumer_replicationpw = NULL;
+ PR_RWLock_Unlock (legacy_consumer_config_lock);
+
+ *returncode = LDAP_SUCCESS;
+ return SLAPI_DSE_CALLBACK_OK;
+}
+
+/*
+ * Given the changelog configuration entry, extract the configuration directives.
+ */
+static int
+legacy_consumer_extract_config(Slapi_Entry* entry, char *returntext)
+{
+ int rc = LDAP_SUCCESS; /* OK */
+ char *arg;
+
+ PR_RWLock_Wlock (legacy_consumer_config_lock);
+
+ arg= slapi_entry_attr_get_charptr(entry,CONFIG_LEGACY_REPLICATIONDN_ATTRIBUTE);
+ if (arg)
+ legacy_consumer_replicationdn = slapi_sdn_new_dn_passin (arg);
+
+ arg= slapi_entry_attr_get_charptr(entry,CONFIG_LEGACY_REPLICATIONPW_ATTRIBUTE);
+ legacy_consumer_replicationpw = arg;
+
+ PR_RWLock_Unlock (legacy_consumer_config_lock);
+
+ return rc;
+}
+
+
+
+
+static int
+legacy_consumer_read_config ()
+{
+ int rc = LDAP_SUCCESS;
+ int scope= LDAP_SCOPE_BASE;
+ Slapi_PBlock *pb;
+
+ pb = slapi_pblock_new ();
+ slapi_search_internal_set_pb (pb, LEGACY_CONSUMER_CONFIG_DN, scope,
+ "(objectclass=*)", NULL /*attrs*/, 0 /* attrs only */,
+ NULL /* controls */, NULL /* uniqueid */,
+ repl_get_plugin_identity(PLUGIN_LEGACY_REPLICATION), 0 /* actions */);
+ slapi_search_internal_pb (pb);
+ slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_RESULT, &rc );
+ if ( LDAP_SUCCESS == rc )
+ {
+ Slapi_Entry **entries = NULL;
+ slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
+ if ( NULL != entries && NULL != entries[0])
+ {
+ /* Extract the config info from the changelog entry */
+ rc = legacy_consumer_extract_config(entries[0], NULL);
+ }
+ }
+ else
+ {
+ rc = LDAP_SUCCESS;
+ }
+ slapi_free_search_results_internal(pb);
+ slapi_pblock_destroy(pb);
+
+ return rc;
+}
+
+
+int
+legacy_consumer_is_replicationdn(char *dn)
+{
+ int return_value = 0; /* Assume not */
+
+ if (NULL != dn && '\0' != dn[0])
+ {
+ if (NULL != legacy_consumer_replicationdn)
+ {
+ Slapi_DN *sdn = slapi_sdn_new_dn_byref (dn);
+
+ if (slapi_sdn_compare (legacy_consumer_replicationdn, sdn) == 0) {
+ return_value = 1;
+ }
+
+ slapi_sdn_free (&sdn);
+ }
+ }
+ return return_value;
+}
+
+
+int
+legacy_consumer_is_replicationpw(struct berval *pwval)
+{
+ int return_value = 0; /* Assume not */
+
+ if (NULL != pwval && NULL != pwval->bv_val)
+ {
+ if (NULL != legacy_consumer_replicationpw &&
+ '\0' != legacy_consumer_replicationpw[0]) {
+ struct berval *pwvals[2];
+ struct berval config_pw;
+
+ config_pw.bv_val = legacy_consumer_replicationpw;
+ config_pw.bv_len = strlen(legacy_consumer_replicationpw);
+ pwvals[0] = &config_pw;
+ pwvals[1] = NULL;
+
+ return_value = slapi_pw_find(pwvals, pwval) == 0;
+ }
+ }
+ return return_value;
+}
+
+static void
+legacy_consumer_free_config ()
+{
+ if (NULL != legacy_consumer_replicationdn) {
+ slapi_sdn_free(&legacy_consumer_replicationdn);
+ }
+ if (NULL != legacy_consumer_replicationpw) {
+ slapi_ch_free((void **) &legacy_consumer_replicationpw);
+ }
+}
+
+
+
+static void
+legacy_consumer_encode_pw (Slapi_Entry *e)
+{
+ char *updatepw = slapi_entry_attr_get_charptr(e,
+ CONFIG_LEGACY_REPLICATIONPW_ATTRIBUTE);
+ int is_encoded;
+ char *encoded_value = NULL;
+
+ if (updatepw != NULL)
+ {
+ is_encoded = slapi_is_encoded (updatepw);
+
+ if (!is_encoded)
+ {
+ encoded_value = slapi_encode (updatepw, "SHA");
+ }
+
+ if (encoded_value)
+ {
+ slapi_entry_attr_set_charptr(e,
+ CONFIG_LEGACY_REPLICATIONPW_ATTRIBUTE, encoded_value);
+ }
+ }
+}
+
+static void
+set_legacy_purl (Slapi_PBlock *pb, const char *purl)
+{
+ Object *r_obj;
+ Replica *r;
+
+ r_obj = replica_get_replica_for_op (pb);
+ PR_ASSERT (r_obj);
+ r = (Replica*)object_get_data (r_obj);
+ PR_ASSERT (r && replica_is_legacy_consumer(r));
+
+ replica_set_legacy_purl (r, purl);
+
+ object_release (r_obj);
+}
+
+/* this function get referrals from an entry.
+ Returns 0 if successful
+ 1 if no referrals are present
+ -1 in case of error
+ */
+static int
+get_legacy_referral (Slapi_Entry *e, char **referral, char **state)
+{
+ char* pat = "ldap://%s";
+ const char *val = NULL;
+ char *hostport;
+ int rc = 1;
+ Slapi_Attr *attr;
+ const Slapi_Value *sval;
+
+ PR_ASSERT (e && referral && state);
+
+ /* Find any copiedFrom/copyingFrom attributes -
+ copyingFrom has priority */
+ if (slapi_entry_attr_find(e, type_copyingFrom, &attr) == 0)
+ {
+ slapi_attr_first_value(attr, (Slapi_Value **)&sval);
+ val = slapi_value_get_string(sval);
+ *state = STATE_REFERRAL;
+ }
+ else if (slapi_entry_attr_find(e, type_copiedFrom, &attr) == 0)
+ {
+ slapi_attr_first_value(attr, (Slapi_Value **)&sval);
+ val = slapi_value_get_string(sval);
+ *state = STATE_UPDATE_REFERRAL;
+ }
+
+ if (val)
+ {
+ rc = parse_cfstring(val, &hostport, NULL, NULL);
+ if (rc != 0)
+ {
+ const char *target_dn = slapi_entry_get_dn_const(e);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Warning: a copiedFrom "
+ "or copyingFrom attribute was added to or removed from an "
+ "entry that is not the root of a replicated area. It is possible "
+ "that a legacy replication supplier is incorrectly configured "
+ "to supply updates to the subtree rooted at %s\n",
+ target_dn == NULL ? "null" : target_dn);
+ }
+ else
+ {
+ *referral = slapi_ch_malloc (strlen (pat) + strlen (hostport));
+
+ sprintf (*referral, pat, hostport);
+
+ slapi_ch_free ((void**)&hostport);
+ }
+ }
+ else
+ {
+ rc = 1; /* no copiedFrom or copyingFrom int the entry */
+ }
+
+ return rc;
+}
+
+/* this function is called during server startup or when replica's data
+ is reloaded. It sets up referrals in the mapping tree based on the
+ copiedFrom and copyingFrom attributes. It also sets up partial url in
+ the replica object used to update RUV.
+ Returns 0 if successful and -1 otherwise
+
+ */
+int
+legacy_consumer_init_referrals (Replica *r)
+{
+ Slapi_PBlock *pb;
+ const Slapi_DN *root_sdn;
+ const char *root_dn;
+ char *attrs[] = {"copiedFrom", "copyingFrom"};
+ int rc;
+ Slapi_Entry **entries = NULL;
+ char *referral = NULL;
+ char *referral_array[2];
+ char *state = NULL;
+
+ PR_ASSERT (r);
+
+ pb = slapi_pblock_new ();
+ PR_ASSERT (pb);
+
+ root_sdn = replica_get_root(r);
+ PR_ASSERT (root_sdn);
+
+ root_dn = slapi_sdn_get_ndn(root_sdn);
+ PR_ASSERT (root_dn);
+
+ slapi_search_internal_set_pb (pb, root_dn, LDAP_SCOPE_BASE, "objectclass=*",attrs,
+ 0 /* attrsonly */, NULL /* controls */,
+ NULL /* uniqueid */,
+ repl_get_plugin_identity (PLUGIN_LEGACY_REPLICATION),
+ 0 /* flags */);
+
+ slapi_search_internal_pb (pb);
+
+ slapi_pblock_get (pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ if (rc != LDAP_SUCCESS)
+ {
+ if (rc == LDAP_REFERRAL)
+ {
+ /* We are in referral mode, probably because ORC failed */
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "legacy_consumer_init_referrals "
+ "data for replica %s is in referral mode due to failed "
+ "initialization. Replica need to be reinitialized\n",
+ root_dn);
+ rc = 0;
+ }
+ else
+ {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "legacy_consumer_init_referrals "
+ "failed to obtain root entry for replica %s; LDAP error - %d\n",
+ root_dn, rc);
+ rc = -1;
+ }
+
+ goto done;
+ }
+
+ slapi_pblock_get (pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+
+ PR_ASSERT (entries && entries[0]);
+
+ rc = get_legacy_referral (entries[0], &referral, &state);
+ if (rc == 0)
+ {
+ referral_array[0] = referral;
+ referral_array[1] = NULL;
+ repl_set_mtn_state_and_referrals(root_sdn, state, NULL, NULL, referral_array);
+
+ /* set purtial url in the replica_object */
+ replica_set_legacy_purl (r, referral);
+
+ slapi_ch_free((void **)&referral);
+ }
+ else if (rc == 1) /* no referrals - treat as success */
+ {
+ rc = 0;
+ }
+
+ slapi_free_search_results_internal (pb);
+
+done:
+
+ slapi_pblock_destroy (pb);
+ return rc;
+}
+