mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
rework compare
fix several minor issues with using dangling pointers and uninitialized data fix caching of privileged connections fix issues with unresponsive target failures during search
This commit is contained in:
parent
fd0176e49c
commit
efb04832bd
@ -494,11 +494,6 @@ meta_clear_one_candidate(
|
||||
metaconn_t *mc,
|
||||
int candidate );
|
||||
|
||||
extern int
|
||||
meta_clear_candidates(
|
||||
Operation *op,
|
||||
metaconn_t *mc );
|
||||
|
||||
/*
|
||||
* Dn cache stuff (experimental)
|
||||
*/
|
||||
|
@ -253,6 +253,7 @@ retry_lock:;
|
||||
|
||||
ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
|
||||
if ( isroot ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( mc );
|
||||
mc->mc_conn = LDAP_BACK_PCONN_SET( op );
|
||||
}
|
||||
lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
|
||||
@ -262,9 +263,8 @@ retry_lock:;
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
if ( lerr == -1 ) {
|
||||
meta_clear_candidates( op, mc );
|
||||
|
||||
/* we can do this because mc_refcnt == 1 */
|
||||
assert( mc->mc_refcnt == 1 );
|
||||
mc->mc_refcnt = 0;
|
||||
meta_back_conn_free( mc );
|
||||
mc = NULL;
|
||||
@ -396,10 +396,10 @@ retry:;
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
|
||||
assert( LDAP_BACK_CONN_BINDING( msc ) );
|
||||
|
||||
#if 0
|
||||
#ifdef DEBUG_205
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_back_bind_op_result ldap_unbind_ext[%d] ld=%p\n",
|
||||
op->o_log_prefix, candidate, (void *)msc->msc_ld );
|
||||
#endif
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
|
||||
msc->msc_ld = NULL;
|
||||
@ -575,7 +575,7 @@ meta_back_single_dobind(
|
||||
!op->o_do_not_cache &&
|
||||
( BER_BVISNULL( &msc->msc_bound_ndn ) ||
|
||||
BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
|
||||
( LDAP_BACK_CONN_ISPRIV( msc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) ||
|
||||
( LDAP_BACK_CONN_ISPRIV( mc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) ||
|
||||
( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
|
||||
{
|
||||
(void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok );
|
||||
|
@ -189,10 +189,14 @@ meta_clear_one_candidate(
|
||||
|
||||
if ( msc->msc_ld ) {
|
||||
|
||||
#if 0
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p\n",
|
||||
op ? op->o_log_prefix : "", candidate, (void *)mc );
|
||||
#endif
|
||||
#ifdef DEBUG_205
|
||||
char buf[ BUFSIZ ];
|
||||
|
||||
snprintf( buf, sizeof( buf ), "meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p ld=%p",
|
||||
candidate, (void *)mc, (void *)msc->msc_ld );
|
||||
Debug( LDAP_DEBUG_ANY, "### %s %s\n",
|
||||
op ? op->o_log_prefix : "", buf, 0 );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
|
||||
msc->msc_ld = NULL;
|
||||
@ -212,20 +216,3 @@ meta_clear_one_candidate(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* meta_clear_candidates
|
||||
*
|
||||
* clears all candidates
|
||||
*/
|
||||
int
|
||||
meta_clear_candidates( Operation *op, metaconn_t *mc )
|
||||
{
|
||||
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
|
||||
int c;
|
||||
|
||||
for ( c = 0; c < mi->mi_ntargets; c++ ) {
|
||||
meta_clear_one_candidate( op, mc, c );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -34,319 +34,122 @@
|
||||
int
|
||||
meta_back_compare( Operation *op, SlapReply *rs )
|
||||
{
|
||||
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
|
||||
metaconn_t *mc = NULL;
|
||||
char *match = NULL,
|
||||
*err = NULL;
|
||||
struct berval mmatch = BER_BVNULL;
|
||||
int ncandidates = 0,
|
||||
last = 0,
|
||||
i,
|
||||
count = 0,
|
||||
rc,
|
||||
cres = LDAP_SUCCESS,
|
||||
rres = LDAP_SUCCESS,
|
||||
*msgid;
|
||||
dncookie dc;
|
||||
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
|
||||
metatarget_t *mt;
|
||||
metaconn_t *mc;
|
||||
int rc = 0;
|
||||
int candidate = -1;
|
||||
struct berval mdn = BER_BVNULL;
|
||||
dncookie dc;
|
||||
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;
|
||||
LDAPControl **ctrls = NULL;
|
||||
|
||||
SlapReply *candidates = meta_back_candidates_get( op );
|
||||
|
||||
mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_SENDERR );
|
||||
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
|
||||
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
msgid = ch_calloc( sizeof( int ), mi->mi_ntargets );
|
||||
if ( msgid == NULL ) {
|
||||
send_ldap_error( op, rs, LDAP_OTHER, NULL );
|
||||
rc = LDAP_OTHER;
|
||||
goto done;
|
||||
}
|
||||
|
||||
assert( mc->mc_conns[ candidate ].msc_ld != NULL );
|
||||
|
||||
/*
|
||||
* start an asynchronous compare for each candidate target
|
||||
* Rewrite the modify dn, if needed
|
||||
*/
|
||||
mt = mi->mi_targets[ candidate ];
|
||||
dc.target = mt;
|
||||
dc.conn = op->o_conn;
|
||||
dc.rs = rs;
|
||||
dc.ctx = "compareDN";
|
||||
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
struct berval mdn = BER_BVNULL;
|
||||
struct berval mapped_attr = op->orc_ava->aa_desc->ad_cname;
|
||||
struct berval mapped_value = op->orc_ava->aa_value;
|
||||
metatarget_t *mt = mi->mi_targets[ i ];
|
||||
LDAPControl **ctrls = NULL;
|
||||
switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rc = 1;
|
||||
goto cleanup;
|
||||
|
||||
if ( ! META_IS_CANDIDATE( &candidates[ i ] ) ) {
|
||||
msgid[ i ] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrite the compare dn, if needed
|
||||
*/
|
||||
dc.target = mt;
|
||||
|
||||
switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rc = 1;
|
||||
goto finish;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* if attr is objectClass, try to remap the value
|
||||
*/
|
||||
if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
|
||||
ldap_back_map( &mt->mt_rwmap.rwm_oc,
|
||||
&op->orc_ava->aa_value,
|
||||
&mapped_value, BACKLDAP_MAP );
|
||||
|
||||
if ( BER_BVISNULL( &mapped_value ) || mapped_value.bv_val[0] == '\0' ) {
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* else try to remap the attribute
|
||||
*/
|
||||
} else {
|
||||
ldap_back_map( &mt->mt_rwmap.rwm_at,
|
||||
&op->orc_ava->aa_desc->ad_cname,
|
||||
&mapped_attr, BACKLDAP_MAP );
|
||||
if ( BER_BVISNULL( &mapped_attr ) || mapped_attr.bv_val[0] == '\0' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||
{
|
||||
dc.ctx = "compareAttrDN";
|
||||
|
||||
switch ( ldap_back_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
|
||||
{
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rc = 1;
|
||||
goto finish;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctrls = op->o_ctrls;
|
||||
if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ i ].msc_bound_ndn,
|
||||
mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* the compare op is spawned across the targets and the first
|
||||
* that returns determines the result; a constraint on unicity
|
||||
* of the result ought to be enforced
|
||||
*/
|
||||
rc = ldap_compare_ext( mc->mc_conns[ i ].msc_ld, mdn.bv_val,
|
||||
mapped_attr.bv_val, &mapped_value,
|
||||
ctrls, NULL, &msgid[ i ] );
|
||||
|
||||
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
|
||||
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( mdn.bv_val );
|
||||
BER_BVZERO( &mdn );
|
||||
}
|
||||
|
||||
if ( mapped_attr.bv_val != op->orc_ava->aa_desc->ad_cname.bv_val ) {
|
||||
free( mapped_attr.bv_val );
|
||||
BER_BVZERO( &mapped_attr );
|
||||
}
|
||||
|
||||
if ( mapped_value.bv_val != op->orc_ava->aa_value.bv_val ) {
|
||||
free( mapped_value.bv_val );
|
||||
BER_BVZERO( &mapped_value );
|
||||
}
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
/* FIXME: what should we do with the error? */
|
||||
continue;
|
||||
}
|
||||
|
||||
++ncandidates;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* wait for replies
|
||||
* if attr is objectClass, try to remap the value
|
||||
*/
|
||||
for ( rc = 0, count = 0; ncandidates > 0; ) {
|
||||
if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
|
||||
ldap_back_map( &mt->mt_rwmap.rwm_oc,
|
||||
&op->orc_ava->aa_value,
|
||||
&mapped_value, BACKLDAP_MAP );
|
||||
|
||||
/*
|
||||
* FIXME: should we check for abandon?
|
||||
*/
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
metasingleconn_t *msc = &mc->mc_conns[ i ];
|
||||
int lrc;
|
||||
LDAPMessage *res = NULL;
|
||||
struct timeval tv;
|
||||
if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
LDAP_BACK_TV_SET( &tv );
|
||||
/*
|
||||
* else try to remap the attribute
|
||||
*/
|
||||
} else {
|
||||
ldap_back_map( &mt->mt_rwmap.rwm_at,
|
||||
&op->orc_ava->aa_desc->ad_cname,
|
||||
&mapped_attr, BACKLDAP_MAP );
|
||||
if ( BER_BVISNULL( &mapped_attr ) || BER_BVISEMPTY( &mapped_attr ) ) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ( msgid[ i ] == -1 ) {
|
||||
continue;
|
||||
}
|
||||
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
|
||||
{
|
||||
dc.ctx = "compareAttrDN";
|
||||
|
||||
lrc = ldap_result( msc->msc_ld, msgid[ i ],
|
||||
LDAP_MSG_ALL, &tv, &res );
|
||||
|
||||
switch ( lrc ) {
|
||||
case 0:
|
||||
assert( res == NULL );
|
||||
continue;
|
||||
|
||||
case -1:
|
||||
/* we do not retry in this case;
|
||||
* only for unique operations... */
|
||||
ldap_get_option( msc->msc_ld,
|
||||
LDAP_OPT_RESULT_CODE, &rs->sr_err );
|
||||
rres = slap_map_api2result( rs );
|
||||
rres = rc;
|
||||
rc = -1;
|
||||
goto finish;
|
||||
switch ( ldap_back_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
|
||||
{
|
||||
case LDAP_UNWILLING_TO_PERFORM:
|
||||
rc = 1;
|
||||
goto cleanup;
|
||||
|
||||
default:
|
||||
/* only touch when activity actually took place... */
|
||||
/* NOTE: no mutex because there's only a loose requirement
|
||||
* to bump it up... */
|
||||
if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) {
|
||||
msc->msc_time = op->o_time;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( lrc == LDAP_RES_COMPARE ) {
|
||||
if ( count > 0 ) {
|
||||
rres = LDAP_OTHER;
|
||||
rc = -1;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* FIXME: matched? referrals? response controls? */
|
||||
rc = ldap_parse_result( msc->msc_ld, res,
|
||||
&rs->sr_err,
|
||||
NULL, NULL, NULL, NULL, 1 );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
rres = rc;
|
||||
rc = -1;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
switch ( rs->sr_err ) {
|
||||
case LDAP_COMPARE_TRUE:
|
||||
case LDAP_COMPARE_FALSE:
|
||||
|
||||
/*
|
||||
* true or false, got it;
|
||||
* sending to cache ...
|
||||
*/
|
||||
if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {
|
||||
( void )meta_dncache_update_entry( &mi->mi_cache, &op->o_req_ndn, i );
|
||||
}
|
||||
|
||||
count++;
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
rres = slap_map_api2result( rs );
|
||||
|
||||
if ( err != NULL ) {
|
||||
free( err );
|
||||
}
|
||||
ldap_get_option( msc->msc_ld,
|
||||
LDAP_OPT_DIAGNOSTIC_MESSAGE, &err );
|
||||
|
||||
if ( match != NULL ) {
|
||||
free( match );
|
||||
}
|
||||
ldap_get_option( msc->msc_ld,
|
||||
LDAP_OPT_MATCHED_DN, &match );
|
||||
|
||||
last = i;
|
||||
break;
|
||||
}
|
||||
msgid[ i ] = -1;
|
||||
--ncandidates;
|
||||
|
||||
} else {
|
||||
msgid[ i ] = -1;
|
||||
--ncandidates;
|
||||
if ( res ) {
|
||||
ldap_msgfree( res );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finish:;
|
||||
retry:;
|
||||
ctrls = op->o_ctrls;
|
||||
rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
|
||||
mt->mt_version, &mt->mt_idassert, op, rs, &ctrls );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
send_ldap_result( op, rs );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrite the matched portion of the search base, if required
|
||||
*
|
||||
* FIXME: only the last one gets caught!
|
||||
*/
|
||||
if ( count == 1 ) {
|
||||
if ( match != NULL ) {
|
||||
free( match );
|
||||
match = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* the result of the compare is assigned to the res code
|
||||
* that will be returned
|
||||
*/
|
||||
rres = cres;
|
||||
|
||||
/*
|
||||
* At least one compare failed with matched portion,
|
||||
* and none was successful
|
||||
*/
|
||||
} else if ( match != NULL && match[ 0 ] != '\0' ) {
|
||||
struct berval matched, pmatched;
|
||||
rs->sr_err = ldap_compare_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
|
||||
mapped_attr.bv_val, &mapped_value,
|
||||
ctrls, NULL, &msgid );
|
||||
|
||||
ber_str2bv( match, 0, 0, &matched );
|
||||
|
||||
dc.ctx = "matchedDN";
|
||||
ldap_back_dn_massage( &dc, &matched, &mmatch );
|
||||
if ( dnPretty( NULL, &mmatch, &pmatched, NULL ) == LDAP_SUCCESS ) {
|
||||
if ( mmatch.bv_val != match ) {
|
||||
free( mmatch.bv_val );
|
||||
}
|
||||
mmatch = pmatched;
|
||||
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;
|
||||
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
|
||||
/* if the identity changed, there might be need to re-authz */
|
||||
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
if ( rres != LDAP_SUCCESS ) {
|
||||
rs->sr_err = rres;
|
||||
}
|
||||
rs->sr_matched = mmatch.bv_val;
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_matched = NULL;
|
||||
cleanup:;
|
||||
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
|
||||
|
||||
if ( match != NULL ) {
|
||||
if ( mmatch.bv_val != match ) {
|
||||
free( mmatch.bv_val );
|
||||
}
|
||||
free( match );
|
||||
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
|
||||
free( mdn.bv_val );
|
||||
}
|
||||
|
||||
if ( msgid ) {
|
||||
free( msgid );
|
||||
if ( op->orc_ava->aa_value.bv_val != mapped_value.bv_val ) {
|
||||
free( mapped_value.bv_val );
|
||||
}
|
||||
|
||||
done:;
|
||||
meta_back_release_conn( op, mc );
|
||||
if ( mc ) {
|
||||
meta_back_release_conn( op, mc );
|
||||
}
|
||||
|
||||
return rc;
|
||||
return rs->sr_err;
|
||||
}
|
||||
|
||||
|
@ -156,11 +156,12 @@ ravl_print( Avlnode *root, int depth )
|
||||
}
|
||||
|
||||
mc = (metaconn_t *)root->avl_data;
|
||||
fprintf( stderr, "mc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
|
||||
fprintf( stderr, "mc=%p local=\"%s\" conn=%p %s refcnt=%d%s\n",
|
||||
(void *)mc,
|
||||
mc->mc_local_ndn.bv_val ? mc->mc_local_ndn.bv_val : "",
|
||||
(void *)mc->mc_conn,
|
||||
avl_bf2str( root->avl_bf ), mc->mc_refcnt );
|
||||
avl_bf2str( root->avl_bf ), mc->mc_refcnt,
|
||||
LDAP_BACK_CONN_TAINTED( mc ) ? " tainted" : "" );
|
||||
|
||||
ravl_print( root->avl_left, depth + 1 );
|
||||
}
|
||||
@ -424,10 +425,10 @@ retry:;
|
||||
|| ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( mi ) ) )
|
||||
{
|
||||
|
||||
#if 0
|
||||
#ifdef DEBUG_205
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_back_init_one_conn(TLS) ldap_unbind_ext[%d] ld=%p\n",
|
||||
op->o_log_prefix, candidate, (void *)msc->msc_ld );
|
||||
#endif
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
|
||||
msc->msc_ld = NULL;
|
||||
@ -464,8 +465,6 @@ retry:;
|
||||
ber_bvreplace( &msc->msc_bound_ndn, &slap_empty_bv );
|
||||
}
|
||||
|
||||
LDAP_BACK_CONN_ISPRIV_SET( msc );
|
||||
|
||||
} else {
|
||||
if ( !BER_BVISNULL( &msc->msc_cred ) ) {
|
||||
memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
|
||||
@ -492,10 +491,10 @@ retry:;
|
||||
&msc->msc_bound_ndn ) )
|
||||
{
|
||||
|
||||
#if 0
|
||||
#ifdef DEBUG_205
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_back_init_one_conn(rewrite) ldap_unbind_ext[%d] ld=%p\n",
|
||||
op->o_log_prefix, candidate, (void *)msc->msc_ld );
|
||||
#endif
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
|
||||
msc->msc_ld = NULL;
|
||||
@ -872,7 +871,7 @@ meta_back_getconn(
|
||||
META_DNTYPE_ENTRY,
|
||||
META_DNTYPE_PARENT,
|
||||
META_DNTYPE_NEWPARENT
|
||||
} dn_type = META_DNTYPE_ENTRY;
|
||||
} dn_type = META_DNTYPE_ENTRY;
|
||||
struct berval ndn = op->o_req_ndn,
|
||||
pndn;
|
||||
|
||||
@ -923,7 +922,8 @@ retry_lock:;
|
||||
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
|
||||
}
|
||||
|
||||
/* Don't reuse connections while they're still binding */
|
||||
/* Don't reuse connections while they're still binding
|
||||
* NOTE: only makes sense for binds */
|
||||
if ( LDAP_BACK_CONN_BINDING( mc ) ) {
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
ldap_pvt_thread_yield();
|
||||
@ -959,12 +959,12 @@ retry_lock:;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_REQ_COMPARE:
|
||||
case LDAP_REQ_DELETE:
|
||||
case LDAP_REQ_MODIFY:
|
||||
/* just a unique candidate */
|
||||
break;
|
||||
|
||||
case LDAP_REQ_COMPARE:
|
||||
case LDAP_REQ_SEARCH:
|
||||
/* allow multiple candidates for the searchBase */
|
||||
op_type = META_OP_ALLOW_MULTIPLE;
|
||||
@ -990,6 +990,13 @@ retry_lock:;
|
||||
if ( sendok & LDAP_BACK_BINDING ) {
|
||||
LDAP_BACK_CONN_BINDING_SET( mc );
|
||||
}
|
||||
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( mc );
|
||||
}
|
||||
|
||||
} else if ( 0 ) {
|
||||
/* TODO: if any of the connections is binding,
|
||||
* release mc and create a new one */
|
||||
}
|
||||
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
@ -1121,12 +1128,11 @@ retry_lock2:;
|
||||
(caddr_t)&mc_curr, meta_back_conndn_cmp );
|
||||
if ( mc != NULL ) {
|
||||
/* Don't reuse connections while they're still binding */
|
||||
if ( LDAP_BACK_CONN_BINDING( mc ) ) {
|
||||
if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
ldap_pvt_thread_yield();
|
||||
goto retry_lock2;
|
||||
}
|
||||
|
||||
mc->mc_refcnt++;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
@ -1142,6 +1148,9 @@ retry_lock2:;
|
||||
if ( sendok & LDAP_BACK_BINDING ) {
|
||||
LDAP_BACK_CONN_BINDING_SET( mc );
|
||||
}
|
||||
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( mc );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1197,8 +1206,8 @@ retry_lock2:;
|
||||
mc->mc_conn = mc_curr.mc_conn;
|
||||
ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
|
||||
new_conn = 1;
|
||||
if ( sendok & LDAP_BACK_BINDING ) {
|
||||
LDAP_BACK_CONN_BINDING_SET( mc );
|
||||
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( mc );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1404,7 +1413,6 @@ meta_back_release_conn_lock(
|
||||
}
|
||||
assert( mc->mc_refcnt > 0 );
|
||||
mc->mc_refcnt--;
|
||||
LDAP_BACK_CONN_BINDING_CLEAR( mc );
|
||||
/* NOTE: the connection is removed if either it is tainted
|
||||
* or if it is shared and no one else is using it. This needs
|
||||
* to occur because for intrinsic reasons cached connections
|
||||
@ -1428,8 +1436,14 @@ meta_back_release_conn_lock(
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
if ( mc->mc_refcnt == 0 ) {
|
||||
meta_back_conn_free( mc );
|
||||
mc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mc != NULL ) {
|
||||
LDAP_BACK_CONN_BINDING_CLEAR( mc );
|
||||
}
|
||||
|
||||
if ( dolock ) {
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
}
|
||||
|
@ -170,7 +170,6 @@ meta_back_conn_free(
|
||||
{
|
||||
metaconn_t *mc = v_mc;
|
||||
int ntargets;
|
||||
Operation op;
|
||||
|
||||
assert( mc != NULL );
|
||||
assert( mc->mc_refcnt == 0 );
|
||||
|
@ -85,7 +85,8 @@ meta_search_dobind_init(
|
||||
|
||||
meta_search_candidate_t retcode;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n", op->o_log_prefix, candidate, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n",
|
||||
op->o_log_prefix, candidate, 0 );
|
||||
|
||||
/*
|
||||
* all the targets are already bound as pseudoroot
|
||||
@ -98,17 +99,55 @@ meta_search_dobind_init(
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
|
||||
if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
|
||||
/* already bound (or anonymous) */
|
||||
|
||||
#ifdef DEBUG_205
|
||||
char buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
|
||||
int bound = 0;
|
||||
|
||||
if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
|
||||
bound = 1;
|
||||
}
|
||||
|
||||
snprintf( buf, sizeof( buf ), " mc=%p lc=%p%s DN=\"%s\"",
|
||||
(void *)mc, (void *)msc->msc_ld,
|
||||
bound ? " bound" : " anonymous",
|
||||
bound == 0 ? "" : msc->msc_bound_ndn.bv_val );
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
|
||||
op->o_log_prefix, candidate, buf );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
|
||||
} else if ( LDAP_BACK_CONN_BINDING( msc ) ) {
|
||||
/* another thread is binding the target for this conn; wait */
|
||||
|
||||
#ifdef DEBUG_205
|
||||
char buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
|
||||
|
||||
snprintf( buf, sizeof( buf ), " mc=%p lc=%p needbind",
|
||||
(void *)mc, (void *)msc->msc_ld );
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
|
||||
op->o_log_prefix, candidate, buf );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;
|
||||
retcode = META_SEARCH_NEED_BIND;
|
||||
|
||||
} else {
|
||||
/* we'll need to bind the target for this conn */
|
||||
|
||||
#ifdef DEBUG_205
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
|
||||
snprintf( buf, sizeof( buf ), " mc=%p ld=%p binding",
|
||||
(void *)mc, (void *)msc->msc_ld );
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
|
||||
op->o_log_prefix, candidate, buf );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
LDAP_BACK_CONN_BINDING_SET( msc );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
|
||||
if ( retcode != META_SEARCH_BINDING ) {
|
||||
@ -120,8 +159,8 @@ meta_search_dobind_init(
|
||||
* state, with eventual connection expiration or invalidation)
|
||||
* it was not initialized as expected */
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] ld=NULL\n",
|
||||
op->o_log_prefix, candidate, 0 );
|
||||
Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n",
|
||||
op->o_log_prefix, candidate, (void *)mc );
|
||||
|
||||
rc = meta_back_init_one_conn( op, rs, *mcp, candidate,
|
||||
LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND );
|
||||
@ -185,6 +224,18 @@ meta_search_dobind_init(
|
||||
|
||||
rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
|
||||
NULL, NULL, &candidates[ candidate ].sr_msgid );
|
||||
|
||||
#ifdef DEBUG_205
|
||||
{
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
|
||||
snprintf( buf, sizeof( buf ), "meta_search_dobind_init[%d] mc=%p ld=%p rc=%d",
|
||||
candidate, (void *)mc, (void *)mc->mc_conns[ candidate ].msc_ld, rc );
|
||||
Debug( LDAP_DEBUG_ANY, "### %s %s\n",
|
||||
op->o_log_prefix, buf, 0 );
|
||||
}
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_SUCCESS:
|
||||
assert( candidates[ candidate ].sr_msgid >= 0 );
|
||||
@ -222,9 +273,9 @@ other:;
|
||||
retcode = META_SEARCH_ERR;
|
||||
|
||||
} else {
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
retcode = META_SEARCH_NOT_CANDIDATE;
|
||||
}
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
break;
|
||||
}
|
||||
@ -271,17 +322,22 @@ meta_search_dobind_result(
|
||||
|
||||
} else {
|
||||
/* FIXME: check if bound as idassert authcDN! */
|
||||
if ( be_isroot( op ) ) {
|
||||
LDAP_BACK_CONN_ISBOUND_SET( msc );
|
||||
} else {
|
||||
if ( BER_BVISNULL( &msc->msc_bound_ndn )
|
||||
|| BER_BVISEMPTY( &msc->msc_bound_ndn ) )
|
||||
{
|
||||
LDAP_BACK_CONN_ISANON_SET( msc );
|
||||
|
||||
} else {
|
||||
LDAP_BACK_CONN_ISBOUND_SET( msc );
|
||||
}
|
||||
retcode = META_SEARCH_CANDIDATE;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
META_BINDING_CLEAR( &candidates[ candidate ] );
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
@ -317,6 +373,7 @@ meta_back_search_start(
|
||||
if ( META_BACK_ONERR_STOP( mi ) ) {
|
||||
return META_SEARCH_ERR;
|
||||
}
|
||||
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
|
||||
return META_SEARCH_NOT_CANDIDATE;
|
||||
}
|
||||
|
||||
@ -567,8 +624,17 @@ getconn:;
|
||||
* Inits searches
|
||||
*/
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
/* reset sr_msgid; it is used in most loops
|
||||
* to check if that target is still to be considered */
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
|
||||
/* a target is marked as candidate by meta_back_getconn();
|
||||
* if for any reason (an error, it's over or so) it is
|
||||
* no longer active, sr_msgid is set to META_MSGID_IGNORE
|
||||
* but it remains candidate, which means it has been active
|
||||
* at some point during the operation. This allows to
|
||||
* use its response code and more to compute the final
|
||||
* response */
|
||||
if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
|
||||
continue;
|
||||
}
|
||||
@ -589,6 +655,7 @@ getconn:;
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
||||
{
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
break;
|
||||
|
||||
case META_SEARCH_NEED_BIND:
|
||||
@ -612,15 +679,31 @@ getconn:;
|
||||
}
|
||||
|
||||
if ( ncandidates > 0 && needbind == ncandidates ) {
|
||||
assert( ( sendok & LDAP_BACK_BINDING ) == 0 );
|
||||
/*
|
||||
* give up the second time...
|
||||
*
|
||||
* NOTE: this should not occur the second time, since a fresh
|
||||
* connection has ben created; however, targets may also
|
||||
* need bind because the bind timed out or so.
|
||||
*/
|
||||
if ( sendok & LDAP_BACK_BINDING ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s meta_back_search: unable to initialize conn\n",
|
||||
op->o_log_prefix, 0, 0 );
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
rs->sr_text = "unable to initialize connection to remote targets";
|
||||
send_ldap_result( op, rs );
|
||||
rc = -1;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* FIXME: better create a separate connection? */
|
||||
sendok |= LDAP_BACK_BINDING;
|
||||
|
||||
#if 0
|
||||
Debug( LDAP_DEBUG_TRACE, "*** %s drop mc=%p create new connection\n",
|
||||
op->o_log_prefix, mc, 0 );
|
||||
#endif
|
||||
#ifdef DEBUG_205
|
||||
Debug( LDAP_DEBUG_ANY, "*** %s drop mc=%p create new connection\n",
|
||||
op->o_log_prefix, (void *)mc, 0 );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
meta_back_release_conn( op, mc );
|
||||
mc = NULL;
|
||||
@ -634,7 +717,7 @@ getconn:;
|
||||
initial_candidates = ncandidates;
|
||||
|
||||
if ( LogTest( LDAP_DEBUG_TRACE ) ) {
|
||||
char cnd[ BUFSIZ ];
|
||||
char cnd[ SLAP_TEXT_BUFLEN ];
|
||||
int c;
|
||||
|
||||
for ( c = 0; c < mi->mi_ntargets; c++ ) {
|
||||
@ -719,10 +802,12 @@ getconn:;
|
||||
metasingleconn_t *msc = &mc->mc_conns[ i ];
|
||||
LDAPMessage *res = NULL, *msg;
|
||||
|
||||
/* if msgid is invalid, don't ldap_result() */
|
||||
if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if target still needs bind, retry */
|
||||
if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND ) {
|
||||
meta_search_candidate_t retcode;
|
||||
|
||||
@ -805,6 +890,23 @@ getconn:;
|
||||
if ( op->o_abandon ) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_205
|
||||
if ( msc->msc_ld == NULL ) {
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
|
||||
snprintf( buf, sizeof( buf ),
|
||||
"%s meta_back_search[%ld] mc=%p msgid=%d%s%s\n",
|
||||
op->o_log_prefix, (long)i, (void *)mc,
|
||||
candidates[ i ].sr_msgid,
|
||||
META_IS_BINDING( &candidates[ i ] ) ? " binding" : "",
|
||||
LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ? " connbinding" : "" );
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "!!! %s\n", buf, 0, 0 );
|
||||
}
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
/*
|
||||
* FIXME: handle time limit as well?
|
||||
@ -833,7 +935,8 @@ really_bad:;
|
||||
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
|
||||
{
|
||||
case META_SEARCH_CANDIDATE:
|
||||
break;
|
||||
/* get back into business... */
|
||||
continue;
|
||||
|
||||
/* means that failed but onerr == continue */
|
||||
case META_SEARCH_NOT_CANDIDATE:
|
||||
@ -855,6 +958,7 @@ really_bad:;
|
||||
|
||||
default:
|
||||
/* unrecoverable error */
|
||||
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
|
||||
rc = rs->sr_err = LDAP_OTHER;
|
||||
goto finish;
|
||||
}
|
||||
@ -1225,11 +1329,16 @@ really_bad:;
|
||||
if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
|
||||
/* if still binding, destroy */
|
||||
|
||||
#if 0
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(abandon) "
|
||||
"ldap_unbind_ext[%ld] ld=%p\n",
|
||||
op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
|
||||
#endif
|
||||
#ifdef DEBUG_205
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
|
||||
snprintf( buf, sizeof( buf), "%s meta_back_search(abandon) "
|
||||
"ldap_unbind_ext[%ld] mc=%p ld=%p",
|
||||
op->o_log_prefix, i, (void *)mc,
|
||||
(void *)mc->mc_conns[i].msc_ld );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "### %s\n", buf, 0, 0 );
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
ldap_unbind_ext( mc->mc_conns[ i ].msc_ld, NULL, NULL );
|
||||
mc->mc_conns[ i ].msc_ld = NULL;
|
||||
@ -1273,7 +1382,7 @@ really_bad:;
|
||||
|
||||
#if 0
|
||||
if ( LogTest( LDAP_DEBUG_TRACE ) ) {
|
||||
char buf[ BUFSIZ ];
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
|
||||
snprintf( buf, sizeof( buf ), "%s %ld.%06ld %d/%d mc=%p",
|
||||
op->o_log_prefix, save_tv.tv_sec, save_tv.tv_usec,
|
||||
@ -1390,8 +1499,8 @@ really_bad:;
|
||||
|
||||
#if 0
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
char cnd[BUFSIZ];
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
char cnd[ SLAP_TEXT_BUFLEN ];
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < mi->mi_ntargets; i++ ) {
|
||||
@ -1449,11 +1558,11 @@ finish:;
|
||||
assert( candidates[ i ].sr_msgid >= 0 );
|
||||
assert( mc->mc_conns[ i ].msc_ld != NULL );
|
||||
|
||||
#if 0
|
||||
#ifdef DEBUG_205
|
||||
Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
|
||||
"ldap_unbind_ext[%ld] ld=%p\n",
|
||||
op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
|
||||
#endif
|
||||
#endif /* DEBUG_205 */
|
||||
|
||||
/* if still binding, destroy */
|
||||
ldap_unbind_ext( mc->mc_conns[ i ].msc_ld, NULL, NULL );
|
||||
|
Loading…
Reference in New Issue
Block a user