"FIND_PRESENT",
csn ? csn->bv_val : "" );
+again:
fop = *op;
fop.o_sync_mode &= SLAP_CONTROL_MASK; /* turn off sync_mode */
/* We want pure entries, not referrals */
fop.ors_filter = &cf;
fop.ors_filterstr.bv_val = buf;
-again:
switch( mode ) {
case FIND_MAXCSN:
cf.f_choice = LDAP_FILTER_GE;
Entry *e = NULL;
Attribute *a;
int rc, gonext;
- struct berval newdn;
- int freefdn = 0;
BackendDB *b0 = op->o_bd, db;
- fc.fdn = &op->o_req_ndn;
- /* compute new DN */
- if ( op->o_tag == LDAP_REQ_MODRDN && !saveit ) {
- ber_dupbv_x( &newdn, &op->orr_nnewDN, op->o_tmpmemctx );
- fc.fdn = &newdn;
- freefdn = 1;
- }
+ fc.fdn = saveit ? &op->o_req_ndn : &opc->sndn;
if ( !saveit && op->o_tag == LDAP_REQ_DELETE ) {
/* Delete succeeded, there is no entry */
} else if ( op->o_tag != LDAP_REQ_ADD ) {
}
if ( saveit || op->o_tag == LDAP_REQ_ADD ) {
- ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
- ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
+ if ( op->o_tag == LDAP_REQ_MODRDN ) {
+ ber_dupbv_x( &opc->sdn, &op->orr_newDN, op->o_tmpmemctx );
+ ber_dupbv_x( &opc->sndn, &op->orr_nnewDN, op->o_tmpmemctx );
+ } else {
+ ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
+ ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
+ }
opc->sreference = is_entry_referral( e );
a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID );
if ( a )
Debug( LDAP_DEBUG_SYNC, "%s syncprov_matchops: "
"%srecording uuid for dn=%s on opc=%p\n",
op->o_log_prefix, a ? "" : "not ", opc->sdn.bv_val, opc );
- } else if ( op->o_tag == LDAP_REQ_MODRDN && !saveit ) {
- op->o_tmpfree( opc->sndn.bv_val, op->o_tmpmemctx );
- op->o_tmpfree( opc->sdn.bv_val, op->o_tmpmemctx );
- ber_dupbv_x( &opc->sdn, &e->e_name, op->o_tmpmemctx );
- ber_dupbv_x( &opc->sndn, &e->e_nname, op->o_tmpmemctx );
}
ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
else if ( opc->se )
entry_free( opc->se );
}
- if ( freefdn ) {
- op->o_tmpfree( fc.fdn->bv_val, op->o_tmpmemctx );
- }
op->o_bd = b0;
}
{
searchstate *ss = op->o_callback->sc_private;
slap_overinst *on = ss->ss_on;
+ syncops *so = ss->ss_so;
syncprov_info_t *si = (syncprov_info_t *)on->on_bi.bi_private;
sync_control *srs = op->o_controls[slap_cids.sc_LDAPsync];
sid = slap_parse_csn_sid( &a->a_nvals[0] );
/* If not a persistent search */
- if ( !ss->ss_so ) {
+ if ( !so ) {
/* Make sure entry is less than the snapshot'd contextCSN */
for ( i=0; i<ss->ss_numcsns; i++ ) {
if ( sid == ss->ss_sids[i] && ber_bvcmp( &a->a_nvals[0],
/* Is this a regular refresh?
* Note: refresh never gets here if there were no changes
*/
- if ( !ss->ss_so ) {
+ if ( !so ) {
rs->sr_ctrls = op->o_tmpalloc( sizeof(LDAPControl *)*2,
op->o_tmpmemctx );
rs->sr_ctrls[1] = NULL;
op->o_tmpfree( cookie.bv_val, op->o_tmpmemctx );
} else {
/* It's RefreshAndPersist, transition to Persist phase */
+ rs->sr_err = SLAPD_NO_REPLY;
syncprov_sendinfo( op, rs, ( ss->ss_flags & SS_PRESENT ) ?
LDAP_TAG_SYNC_REFRESH_PRESENT : LDAP_TAG_SYNC_REFRESH_DELETE,
( ss->ss_flags & SS_CHANGED ) ? &cookie : NULL,
return SLAPD_ABANDON;
} else {
- ldap_pvt_thread_mutex_lock( &ss->ss_so->s_mutex );
+ ldap_pvt_thread_mutex_lock( &so->s_mutex );
/* Turn off the refreshing flag */
- ss->ss_so->s_flags ^= PS_IS_REFRESHING;
+ so->s_flags ^= PS_IS_REFRESHING;
Debug( LDAP_DEBUG_SYNC, "%s syncprov_search_response: "
"detaching op\n", op->o_log_prefix );
- syncprov_detach_op( op, ss->ss_so, on );
+ syncprov_detach_op( op, so, on );
ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
/* If there are queued responses, fire them off */
- if ( ss->ss_so->s_res )
- syncprov_qstart( ss->ss_so );
- ldap_pvt_thread_mutex_unlock( &ss->ss_so->s_mutex );
- return SLAPD_NO_REPLY;
+ if ( so->s_res )
+ syncprov_qstart( so );
+ ldap_pvt_thread_mutex_unlock( &so->s_mutex );
+ return rs->sr_err;
}
}
}
return SLAP_CB_CONTINUE;
}
+static int
+syncprov_search_cb( Operation *op, SlapReply *rs )
+{
+ /*
+ * Prevent the glue overlay from processing subordinates when it is
+ * configured (explicitly or implicitly) below the syncprov overlay.
+ */
+ if ( rs->sr_type == REP_RESULT )
+ op->o_no_subordinate_glue = 1;
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+syncprov_search_cleanup( Operation *op, SlapReply *rs )
+{
+ if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_INTERMEDIATE ||
+ rs->sr_err == SLAPD_ABANDON || op->o_abandon ) {
+ searchstate *ss = op->o_callback->sc_private;
+ if ( ss && ss->ss_numcsns ) {
+ ber_bvarray_free_x( ss->ss_ctxcsn, op->o_tmpmemctx );
+ op->o_tmpfree( ss->ss_sids, op->o_tmpmemctx );
+ }
+ slap_freeself_cb( op, rs );
+ }
+ return SLAP_CB_CONTINUE;
+}
+
static int
syncprov_op_search( Operation *op, SlapReply *rs )
{
int minsid, maxsid;
int dirty = 0;
+ if ( op->o_sync > SLAP_CONTROL_IGNORED ) {
+ cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx );
+ cb->sc_response = syncprov_search_cb;
+ cb->sc_cleanup = syncprov_search_cleanup;
+ cb->sc_next = op->o_callback;
+ op->o_callback = cb;
+ }
+
if ( !(op->o_sync_mode & SLAP_SYNC_REFRESH) ) return SLAP_CB_CONTINUE;
if ( op->ors_deref & LDAP_DEREF_SEARCHING ) {
}
rs->sr_ctrls = NULL;
send_ldap_result( op, rs );
+ if ( numcsns ) {
+ ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
+ op->o_tmpfree( sids, op->o_tmpmemctx );
+ }
return rs->sr_err;
}
}
rs->sr_err = LDAP_SUCCESS;
send_ldap_result( op, rs );
rs->sr_ctrls = NULL;
+ if ( numcsns ) {
+ ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
+ op->o_tmpfree( sids, op->o_tmpmemctx );
+ }
return rs->sr_err;
}
Debug( LDAP_DEBUG_SYNC, "%s syncprov_op_search: "
/* No, so a reload is required */
/* the 2.2 consumer doesn't send this hint */
if ( si->si_usehint && srs->sr_rhint == 0 ) {
- if ( ctxcsn )
- ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
- if ( sids )
- op->o_tmpfree( sids, op->o_tmpmemctx );
rs->sr_err = LDAP_SYNC_REFRESH_REQUIRED;
rs->sr_text = "sync cookie is stale";
goto bailout;
} else {
gotstate = 1;
/* If changed and doing Present lookup, send Present UUIDs */
- if ( syncprov_findcsn( op, FIND_PRESENT, 0 ) != LDAP_SUCCESS ) {
- if ( ctxcsn )
- ber_bvarray_free_x( ctxcsn, op->o_tmpmemctx );
- if ( sids )
- op->o_tmpfree( sids, op->o_tmpmemctx );
+ if ( syncprov_findcsn( op, FIND_PRESENT, 0 ) != LDAP_SUCCESS )
goto bailout;
- }
}
} else {
/* The consumer knows nothing, we know nothing. OK. */
ss->ss_numcsns = numcsns;
ss->ss_sids = sids;
cb->sc_response = syncprov_search_response;
+ cb->sc_cleanup = syncprov_search_cleanup;
cb->sc_private = ss;
cb->sc_next = op->o_callback;
op->o_callback = cb;
--- /dev/null
+#! /bin/sh
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+if test $BACKLDAP = ldapno; then
+ echo "LDAP backend not available, test skipped"
+ exit 0
+fi
+
+if test $RWM = rwmno; then
+ echo "rwm (rewrite/remap) overlay not available, test skipped"
+ exit 0
+fi
+
+if test $SYNCPROV = syncprovno; then
+ echo "Syncrepl provider overlay not available, test skipped"
+ exit 0
+fi
+
+RMTSUFFIX="dc=remote,$BASEDN"
+RMTROOTDN="cn=Manager,$RMTSUFFIX"
+
+RMTDIR=$TESTDIR/remote
+PR1DIR=$TESTDIR/provider1
+PR2DIR=$TESTDIR/provider2
+RMTCONF=$RMTDIR/slapd.d
+PR1CONF=$PR1DIR/slapd.d
+PR2CONF=$PR2DIR/slapd.d
+
+ENTRIES=$TESTDIR/entries.ldif
+SYNC1OUT=$TESTDIR/syncrepl1.out
+SYNC2OUT=$TESTDIR/syncrepl2.out
+
+mkdir -p $RMTDIR $RMTCONF $RMTDIR/db
+mkdir -p $PR1DIR $PR1CONF $PR1DIR/db
+mkdir -p $PR2DIR $PR2CONF $PR2DIR/db
+
+cd $TESTDIR
+
+KILLPIDS=
+
+$SLAPPASSWD -g -n > $CONFIGPWF
+
+cat <<EOF > $CONFLDIF
+dn: cn=config
+objectClass: olcGlobal
+cn: config
+
+dn: olcDatabase={0}config,cn=config
+objectClass: olcDatabaseConfig
+olcDatabase: {0}config
+olcRootPW:< file://$CONFIGPWF
+
+dn: cn=schema,cn=config
+objectClass: olcSchemaConfig
+cn: schema
+
+include: file://$ABS_SCHEMADIR/core.ldif
+include: file://$ABS_SCHEMADIR/cosine.ldif
+include: file://$ABS_SCHEMADIR/nis.ldif
+include: file://$ABS_SCHEMADIR/inetorgperson.ldif
+
+dn: cn=module,cn=config
+objectClass: olcModuleList
+cn: module
+olcModulePath: $TESTWD/../servers/slapd/overlays
+EOF
+
+[ "$BACKENDTYPE" = mod ] && echo "olcModuleLoad: $TESTWD/../servers/slapd/back-$BACKEND/back_$BACKEND.la" >> $CONFLDIF
+
+echo "Initializing remote configurations..."
+cat $CONFLDIF - <<EOF | $SLAPADD -F $RMTCONF -n 0
+
+dn: olcDatabase={1}$BACKEND,cn=config
+objectClass: olcDatabaseConfig
+${nullExclude}objectClass: olc${BACKEND}Config
+olcDatabase: {1}$BACKEND
+${nullExclude}olcDbDirectory: $RMTDIR/db
+olcSuffix: $RMTSUFFIX
+olcRootDN: $RMTROOTDN
+olcRootPW: $PASSWD
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "slapadd failed ($RC)!"
+ exit $RC
+fi
+
+[ "$BACKLDAP" = ldapmod ] && echo "olcModuleLoad: $TESTWD/../servers/slapd/back-ldap/back_ldap.la" >> $CONFLDIF
+[ "$RWM" = rwmmod ] && echo "olcModuleLoad: rwm.la" >> $CONFLDIF
+[ "$SYNCPROV" = syncprovmod ] && echo "olcModuleLoad: syncprov.la" >> $CONFLDIF
+cat <<EOF >> $CONFLDIF
+
+dn: olcDatabase={1}ldap,cn=config
+objectClass: olcDatabaseConfig
+objectClass: olcLDAPConfig
+olcDatabase: {1}ldap
+olcSuffix: ou=remote,ou=users,$BASEDN
+olcSubordinate: TRUE
+olcDbURI: $URI1
+olcDbIDAssertBind: bindmethod=simple
+ binddn="$RMTROOTDN"
+ credentials=$PASSWD
+ mode=none
+olcDbIDAssertAuthzFrom: dn.exact:$MANAGERDN
+olcRootDN: $MANAGERDN
+
+dn: olcOverlay={0}rwm,olcDatabase={1}ldap,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcRwmConfig
+olcOverlay: {0}rwm
+olcRwmRewrite: rwm-suffixmassage "ou=users,$RMTSUFFIX"
+EOF
+
+echo "Initializing provider1 configurations..."
+cat $CONFLDIF - <<EOF | $SLAPADD -F $PR1CONF -n 0
+
+dn: olcDatabase={2}$BACKEND,cn=config
+objectClass: olcDatabaseConfig
+${nullExclude}objectClass: olc${BACKEND}Config
+olcDatabase: {2}$BACKEND
+${nullExclude}olcDbDirectory: $PR1DIR/db
+olcSuffix: $BASEDN
+olcRootDN: $MANAGERDN
+olcRootPW: $PASSWD
+
+dn: olcOverlay={0}syncprov,olcDatabase={2}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcSyncProvConfig
+olcOverlay: {0}syncprov
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "slapadd failed ($RC)!"
+ exit $RC
+fi
+
+echo "Initializing provider2 configurations..."
+cat $CONFLDIF - <<EOF | $SLAPADD -F $PR2CONF -n 0
+
+dn: olcDatabase={2}$BACKEND,cn=config
+objectClass: olcDatabaseConfig
+${nullExclude}objectClass: olc${BACKEND}Config
+olcDatabase: {2}$BACKEND
+${nullExclude}olcDbDirectory: $PR2DIR/db
+olcSuffix: $BASEDN
+olcRootDN: $MANAGERDN
+olcRootPW: $PASSWD
+
+dn: olcOverlay={0}glue,olcDatabase={2}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcConfig
+olcOverlay: {0}glue
+
+dn: olcOverlay={1}syncprov,olcDatabase={2}$BACKEND,cn=config
+objectClass: olcOverlayConfig
+objectClass: olcSyncProvConfig
+olcOverlay: {1}syncprov
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "slapadd failed ($RC)!"
+ exit $RC
+fi
+
+echo "Starting remote slapd on TCP/IP port $PORT1..."
+cd $RMTDIR
+$SLAPD -F slapd.d -h $URI1 -d $LVL > $LOG1 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+ echo PID $PID
+ read foo
+fi
+KILLPIDS="$KILLPIDS $PID"
+cd $TESTWD
+sleep 1
+echo "Using ldapsearch to check that remote slapd is running..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "" -H $URI1 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+done
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Starting provider1 slapd on TCP/IP port $PORT2..."
+cd $PR1DIR
+$SLAPD -F slapd.d -h $URI2 -d $LVL > $LOG2 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+ echo PID $PID
+ read foo
+fi
+KILLPIDS="$KILLPIDS $PID"
+cd $TESTWD
+sleep 1
+echo "Using ldapsearch to check that provider1 slapd is running..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "" -H $URI2 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+done
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Starting provider2 slapd on TCP/IP port $PORT3..."
+cd $PR2DIR
+$SLAPD -F slapd.d -h $URI3 -d $LVL > $LOG3 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+ echo PID $PID
+ read foo
+fi
+KILLPIDS="$KILLPIDS $PID"
+cd $TESTWD
+sleep 1
+echo "Using ldapsearch to check that provider2 slapd is running..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "" -H $URI3 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+done
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Populating remote database entries..."
+$LDAPADD -D "$RMTROOTDN" -H $URI1 -w $PASSWD <<EOF >> $TESTOUT 2>&1
+dn: $RMTSUFFIX
+objectClass: dcObject
+objectClass: organization
+dc: `echo $RMTSUFFIX | sed 's/^dc=\([^,]*\),.*/\1/'`
+o: Example, Inc
+
+dn: ou=users,$RMTSUFFIX
+objectClass: organizationalUnit
+ou: users
+
+dn: cn=remote_user,ou=users,$RMTSUFFIX
+objectClass: person
+cn: remote_user
+sn: remote_user
+userPassword: $PASSWD
+EOF
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapadd failed to populate remote database entries ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+cat <<EOF > $ENTRIES
+dn: $BASEDN
+objectClass: dcObject
+objectClass: organization
+dc: example
+o: Example, Inc
+
+dn: ou=users,$BASEDN
+objectClass: organizationalUnit
+ou: users
+
+dn: ou=local,ou=users,$BASEDN
+objectClass: organizationalUnit
+ou: local
+
+dn: cn=local_user,ou=local,ou=users,$BASEDN
+objectClass: person
+cn: local_user
+sn: local_user
+userPassword: $PASSWD
+EOF
+
+echo "Populating provider1 database entries..."
+$LDAPADD -D "$MANAGERDN" -H $URI2 -w $PASSWD < $ENTRIES >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapadd failed to populate provider1 database entries ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Populating provider2 database entries..."
+$LDAPADD -D "$MANAGERDN" -H $URI3 -w $PASSWD < $ENTRIES >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapadd failed to populate provider2 database entries ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Starting refreshAndPersist search on provider1..."
+$LDAPRSEARCH -D $MANAGERDN -H $URI2 -w $PASSWD -MM -E sync=rp -b $BASEDN '*' + 2>&1 > $SYNC1OUT &
+PID=$!
+RC=32
+for i in 0 1 2 3 4 5; do
+ echo "Waiting for refreshDone message..."
+ sleep $SLEEP0
+ if grep '^# refresh done, switching to persist stage' $SYNC1OUT; then
+ awk '/^result:/{print; exit $2}' $SYNC1OUT
+ RC=$?
+ break
+ fi
+done
+if test $RC != 0 ; then
+ echo "refresh failed ($RC)!"
+ kill $PID
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Using ldapmodify to modify local entry on provider1..."
+$LDAPMODIFY -D $MANAGERDN -H $URI2 -w $PASSWD <<EOF >> $TESTOUT 2>&1
+dn: cn=local_user,ou=local,ou=users,$BASEDN
+changeType: modify
+replace: description
+description: Syncrepl local_user
+EOF
+RC=32
+for i in 0 1 2 3 4 5; do
+ echo "Waiting for syncrepl to receive changes..."
+ sleep $SLEEP0
+ if grep -q '^description: Syncrepl local_user' $SYNC1OUT; then
+ RC=0
+ break
+ fi
+done
+kill $PID
+if test $RC != 0 ; then
+ echo "syncrepl failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Check that remote entries are NOT replicated..."
+if grep 'ou=remote,' $SYNC1OUT; then
+ echo "remote entries were unexpectedly replicated!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+echo "Starting refreshAndPersist search on provider2..."
+$LDAPRSEARCH -D $MANAGERDN -H $URI3 -w $PASSWD -MM -E sync=rp -b $BASEDN '*' + 2>&1 > $SYNC2OUT &
+PID=$!
+RC=32
+for i in 0 1 2 3 4 5; do
+ echo "Waiting for refreshDone message..."
+ sleep $SLEEP0
+ if grep '^# refresh done, switching to persist stage' $SYNC2OUT; then
+ awk '/^result:/{print; exit $2}' $SYNC2OUT
+ RC=$?
+ break
+ fi
+done
+if test $RC != 0 ; then
+ echo "refresh failed ($RC)!"
+ kill $PID
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Using ldapmodify to modify local entry on privider2..."
+$LDAPMODIFY -D $MANAGERDN -H $URI3 -w $PASSWD <<EOF >> $TESTOUT 2>&1
+dn: cn=local_user,ou=local,ou=users,$BASEDN
+changeType: modify
+replace: description
+description: Syncrepl local_user
+EOF
+RC=32
+for i in 0 1 2 3 4 5; do
+ echo "Waiting for syncrepl to receive changes..."
+ sleep $SLEEP0
+ if grep -q '^description: Syncrepl local_user' $SYNC2OUT; then
+ RC=0
+ break
+ fi
+done
+if test $RC != 0 ; then
+ echo "syncrepl failed ($RC)!"
+ kill $PID
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Using ldapmodify to modify remote entry on privider2..."
+$LDAPMODIFY -D $MANAGERDN -H $URI3 -w $PASSWD <<EOF >> $TESTOUT 2>&1
+dn: cn=remote_user,ou=remote,ou=users,$BASEDN
+changeType: modify
+replace: description
+description: Syncrepl remote_user
+EOF
+RC=32
+for i in 0 1 2 3 4 5; do
+ echo "Waiting for syncrepl to receive changes..."
+ sleep $SLEEP0
+ if grep -q '^description: Syncrepl remote_user' $SYNC2OUT; then
+ RC=0
+ break
+ fi
+done
+kill $PID
+if test $RC != 0 ; then
+ echo "syncrepl failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+echo ">>>>> Test succeeded"
+exit 0