#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:
- {
- int cleanup_attrs = 0;
-
- if ( op->ora_e->e_attrs == NULL ) {
- char textbuf[ SLAP_TEXT_BUFLEN ];
- size_t textlen = sizeof( textbuf );
-
-#if 0
- /* FIXME: op->o_bd is still set to the BackendDB
- * structure of the database that tried to handle
- * the operation and actually returned a referral
- * ... */
- assert( SLAP_DBFLAGS( op->o_bd ) & SLAP_DBFLAG_GLOBAL_OVERLAY );
-#endif
-
- /* global overlay: create entry */
- /* NOTE: this is a hack to use the chain overlay
- * as global. I expect to be able to remove this
- * soon by using slap_mods2entry() earlier in
- * do_add(), adding the operational attrs later
- * if required. */
- rs->sr_err = slap_mods2entry( op->ora_modlist,
- &op->ora_e, 0, 1,
- &rs->sr_text, textbuf, textlen );
- if ( rs->sr_err != LDAP_SUCCESS ) {
- send_ldap_result( op, rs );
- rc = 1;
- break;
- }
- }
rc = ldap_chain_op( op, rs, lback->bi_op_add, ref );
- if ( cleanup_attrs ) {
- attrs_free( op->ora_e->e_attrs );
- op->ora_e->e_attrs = NULL;
- }
break;
- }
case LDAP_REQ_DELETE:
rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref );
break;
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;
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
if ( rc != LDAP_SUCCESS || sc2.sc_private == LDAP_CH_ERR ) {
- if ( rs->sr_err == LDAP_CANNOT_CHAIN ) {
+ if ( rs->sr_err == LDAP_X_CANNOT_CHAIN ) {
goto cannot_chain;
}
case LDAP_CHAINING_REQUIRED:
cannot_chain:;
op->o_callback = NULL;
- send_ldap_error( op, rs, LDAP_CANNOT_CHAIN, "operation cannot be completed without chaining" );
+ send_ldap_error( op, rs, LDAP_X_CANNOT_CHAIN,
+ "operation cannot be completed without chaining" );
break;
default:
op->o_ndn = ndn;
rs->sr_ref = ref;
+ ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
+
return rc;
}
PC_CHAINING = 1
};
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
static ConfigDriver chain_cf_gen;
-static ConfigLDAPadd chain_ldadd;
static ConfigCfAdd chain_cfadd;
+#endif
+static ConfigLDAPadd chain_ldadd;
static ConfigTable chaincfg[] = {
#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
return LDAP_SUCCESS;
}
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
+
static int
chain_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca )
{
return 0;
}
-#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
static slap_verbmasks chaining_mode[] = {
{ BER_BVC("referralsRequired"), LDAP_REFERRALS_REQUIRED },
{ BER_BVC("referralsPreferred"), LDAP_REFERRALS_PREFERRED },
{ BER_BVC("chainingPreferred"), LDAP_CHAINING_PREFERRED },
{ BER_BVNULL, 0 }
};
-#endif
static int
chain_cf_gen( ConfigArgs *c )
{
slap_overinst *on = (slap_overinst *)c->bi;
+#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR
ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private;
+#endif
int rc = 0;
return rc;
}
+#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */
+
static int
ldap_chain_db_config(
BackendDB *be,
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;