#define LDAP_CHAIN_F_NONE 0x00U
#define LDAP_CHAIN_F_CHAINING 0x01U
+ ldap_pvt_thread_mutex_t lc_mutex;
+
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
LDAPControl lc_chaining_ctrl;
char lc_chaining_ctrlflag;
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private;
- struct ldapinfo li, *lip = lc->lc_li;
+
+ struct ldapinfo *lip = lc->lc_li;
+ char *save_url = NULL;
+ SlapReply rs2 = { 0 };
/* NOTE: returned if ref is empty... */
int rc = LDAP_OTHER;
if ( lip->url != NULL ) {
op->o_bd->be_private = lip;
- rc = ( *op_f )( op, rs );
+ rc = ( *op_f )( op, &rs2 );
+ rs->sr_err = rs2.sr_err;
goto done;
}
- li = *lip;
- op->o_bd->be_private = &li;
+ save_url = lip->url;
+ lip->url = NULL;
+ op->o_bd->be_private = lip;
/* if we parse the URI then by no means
* we can cache stuff or reuse connections,
save_dn = srv->lud_dn;
srv->lud_dn = "";
srv->lud_scope = LDAP_SCOPE_DEFAULT;
- li.url = ldap_url_desc2str( srv );
+ lip->url = ldap_url_desc2str( srv );
srv->lud_dn = save_dn;
ldap_free_urldesc( srv );
- if ( li.url == NULL ) {
+ if ( lip->url == NULL ) {
/* try next */
rc = LDAP_OTHER;
continue;
}
- rc = ( *op_f )( op, rs );
+ rc = ( *op_f )( op, &rs2 );
+ rs->sr_err = rs2.sr_err;
- ldap_memfree( li.url );
- li.url = NULL;
+ ldap_memfree( lip->url );
+ lip->url = NULL;
if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
break;
}
}
+ lip->url = save_url;
+
done:;
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
(void)chaining_control_remove( op, &ctrls );
struct berval ndn = op->o_ndn;
ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private;
- struct ldapinfo li, *lip = lc->lc_li;
+ struct ldapinfo *lip = lc->lc_li;
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
int sr_err = rs->sr_err;
}
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+ ldap_pvt_thread_mutex_lock( &lc->lc_mutex );
+
/*
* TODO: add checks on who/when chain operations; e.g.:
* a) what identities are authorized
}
break;
case LDAP_REQ_ADD:
- /* slap_mods2entry () should be called in do_add() */
- assert( op->ora_e->e_attrs != NULL );
rc = ldap_chain_op( op, rs, lback->bi_op_add, ref );
break;
case LDAP_REQ_DELETE:
struct berval *curr = ref,
odn = op->o_req_dn,
ondn = op->o_req_ndn;
+ char *save_url = NULL;
+ SlapReply rs2 = { 0 };
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
LDAPControl **ctrls = NULL;
sc2.sc_response = ldap_chain_cb_search_response;
- li = *lip;
- li.url = NULL;
- op->o_bd->be_private = &li;
+ save_url = lip->url;
+ lip->url = NULL;
+ op->o_bd->be_private = lip;
/* if we parse the URI then by no means
* we can cache stuff or reuse connections,
save_dn = srv->lud_dn;
srv->lud_dn = "";
srv->lud_scope = LDAP_SCOPE_DEFAULT;
- li.url = ldap_url_desc2str( srv );
- if ( li.url != NULL ) {
+ lip->url = ldap_url_desc2str( srv );
+ if ( lip->url != NULL ) {
ber_str2bv_x( save_dn, 0, 1, &op->o_req_dn,
op->o_tmpmemctx );
ber_dupbv_x( &op->o_req_ndn, &op->o_req_dn,
srv->lud_dn = save_dn;
ldap_free_urldesc( srv );
- if ( li.url == NULL ) {
+ if ( lip->url == NULL ) {
/* try next */
rs->sr_err = LDAP_OTHER;
continue;
/* FIXME: should we also copy filter and scope?
* according to RFC3296, no */
- rc = lback->bi_op_search( op, rs );
+ rc = lback->bi_op_search( op, &rs2 );
+ rs->sr_err = rs2.sr_err;
- ldap_memfree( li.url );
- li.url = NULL;
+ ldap_memfree( lip->url );
+ lip->url = NULL;
op->o_tmpfree( op->o_req_dn.bv_val,
op->o_tmpmemctx );
(void)chaining_control_remove( op, &ctrls );
#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+ lip->url = save_url;
+
op->o_req_dn = odn;
op->o_req_ndn = ondn;
rs->sr_type = REP_SEARCHREF;
op->o_ndn = ndn;
rs->sr_ref = ref;
+ ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
+
return rc;
}
lc = ch_malloc( sizeof( ldap_chain_t ) );
memset( lc, 0, sizeof( ldap_chain_t ) );
+ ldap_pvt_thread_mutex_init( &lc->lc_mutex );
+
bd.be_private = NULL;
rc = lback->bi_db_init( &bd );
lc->lc_li = (struct ldapinfo *)bd.be_private;
be->be_private = (void *)lc->lc_li;
rc = lback->bi_db_destroy( be );
- lc->lc_li = be->be_private;
+ ldap_pvt_thread_mutex_destroy( &lc->lc_mutex );
ch_free( lc );
on->on_bi.bi_private = NULL;
be->be_private = private;