time_t                  li_timeout[ SLAP_OP_LAST ];
 } ldapinfo_t;
 
+#define        LDAP_ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)
+
 typedef enum ldap_back_send_t {
        LDAP_BACK_DONTSEND              = 0x00,
        LDAP_BACK_SENDOK                = 0x01,
 
        char            **refs = NULL;
        LDAPControl     **ctrls = NULL;
 
-#define        ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)
-
        rs->sr_text = NULL;
        rs->sr_matched = NULL;
        rs->sr_ref = NULL;
        /* if the error recorded in the reply corresponds
         * to a successful state, get the error from the
         * remote server response */
-       if ( ERR_OK( rs->sr_err ) ) {
+       if ( LDAP_ERR_OK( rs->sr_err ) ) {
                int             rc;
                struct timeval  tv;
                LDAPMessage     *res = NULL;
        /* if the error in the reply structure is not
         * LDAP_SUCCESS, try to map it from client 
         * to server error */
-       if ( !ERR_OK( rs->sr_err ) ) {
+       if ( !LDAP_ERR_OK( rs->sr_err ) ) {
                rs->sr_err = slap_map_api2result( rs );
 
                /* internal ops ( op->o_conn == NULL ) 
                }
 
        } else if ( op->o_conn &&
-               ( ( ( sendok & LDAP_BACK_SENDOK ) && ERR_OK( rs->sr_err ) )
-                       || ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )
+               ( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) )
+                       || ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) )
        {
                send_ldap_result( op, rs );
        }
                rs->sr_ctrls = NULL;
        }
 
-       return( ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
+       return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
 }
 
 /* return true if bound, false if failed */
 
        struct berval   mdn = BER_BVNULL, mapped;
        dncookie        dc;
        int             msgid;
-       int             do_retry = 1;
+       ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
 
        Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
        rs->sr_err = ldap_add_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
                              attrs, ctrls, NULL, &msgid );
        rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-               mt->mt_timeout[ SLAP_OP_ADD ], LDAP_BACK_SENDRESULT );
-       if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-               do_retry = 0;
+               mt->mt_timeout[ SLAP_OP_ADD ], ( LDAP_BACK_SENDRESULT | retrying ) );
+       if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+               retrying &= ~LDAP_BACK_RETRYING;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
 
                metatarget_t            *mt = mi->mi_targets[ candidate ];
                metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
 
-#define        ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)
-
-               if ( ERR_OK( rs->sr_err ) ) {
+               if ( LDAP_ERR_OK( rs->sr_err ) ) {
                        int             rc;
                        struct timeval  tv;
                        LDAPMessage     *res = NULL;
                /* if the error in the reply structure is not
                 * LDAP_SUCCESS, try to map it from client 
                 * to server error */
-               if ( !ERR_OK( rs->sr_err ) ) {
+               if ( !LDAP_ERR_OK( rs->sr_err ) ) {
                        rs->sr_err = slap_map_api2result( rs );
 
                        /* internal ops ( op->o_conn == NULL ) 
                rs->sr_matched = matched;
        }
 
-       if ( op->o_conn &&
-               ( ( sendok & LDAP_BACK_SENDOK ) 
-                       || ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )
+       if ( rs->sr_err == LDAP_UNAVAILABLE ) {
+               if ( !( sendok & LDAP_BACK_RETRYING ) ) {
+                       if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
+                               if ( rs->sr_text == NULL ) rs->sr_text = "Proxy operation retry failed";
+                               send_ldap_result( op, rs );
+                       }
+               }
+
+       } else if ( op->o_conn &&
+               ( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) )
+                       || ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) )
        {
                send_ldap_result( op, rs );
        }
        rs->sr_ref = save_ref;
        rs->sr_ctrls = save_ctrls;
 
-       return( ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
+       return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
 }
 
 /*
 
        struct berval   mapped_attr = op->orc_ava->aa_desc->ad_cname;
        struct berval   mapped_value = op->orc_ava->aa_value;
        int             msgid;
-       int             do_retry = 1;
+       ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
                        ctrls, NULL, &msgid );
 
        rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-               mt->mt_timeout[ SLAP_OP_COMPARE ], LDAP_BACK_SENDRESULT );
-       if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-               do_retry = 0;
+               mt->mt_timeout[ SLAP_OP_COMPARE ], ( LDAP_BACK_SENDRESULT | retrying ) );
+       if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+               retrying &= ~LDAP_BACK_RETRYING;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
 
        struct berval   mdn = BER_BVNULL;
        dncookie        dc;
        int             msgid;
-       int             do_retry = 1;
+       ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
        rs->sr_err = ldap_delete_ext( mc->mc_conns[ candidate ].msc_ld,
                        mdn.bv_val, ctrls, NULL, &msgid );
        rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-               mt->mt_timeout[ SLAP_OP_DELETE ], LDAP_BACK_SENDRESULT );
-       if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-               do_retry = 0;
+               mt->mt_timeout[ SLAP_OP_DELETE ], ( LDAP_BACK_SENDRESULT | retrying ) );
+       if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+               retrying &= ~LDAP_BACK_RETRYING;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
 
        struct berval   mapped;
        dncookie        dc;
        int             msgid;
-       int             do_retry = 1;
+       ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
 
        mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
        rs->sr_err = ldap_modify_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
                        modv, ctrls, NULL, &msgid );
        rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-               mt->mt_timeout[ SLAP_OP_MODIFY ], LDAP_BACK_SENDRESULT );
-       if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-               do_retry = 0;
+               mt->mt_timeout[ SLAP_OP_MODIFY ], ( LDAP_BACK_SENDRESULT | retrying ) );
+       if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+               retrying &= ~LDAP_BACK_RETRYING;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
 
                        mnewSuperior = BER_BVNULL;
        dncookie        dc;
        int             msgid;
-       int             do_retry = 1;
+       ldap_back_send_t        retrying = LDAP_BACK_RETRYING;
        LDAPControl     **ctrls = NULL;
        struct berval   newrdn = BER_BVNULL;
 
                        mnewSuperior.bv_val, op->orr_deleteoldrdn,
                        ctrls, NULL, &msgid );
        rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-               mt->mt_timeout[ SLAP_OP_MODRDN ], LDAP_BACK_SENDRESULT );
-       if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-               do_retry = 0;
+               mt->mt_timeout[ SLAP_OP_MODRDN ], ( LDAP_BACK_SENDRESULT | retrying ) );
+       if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+               retrying &= ~LDAP_BACK_RETRYING;
                if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        /* if the identity changed, there might be need to re-authz */
                        (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );