mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-01-21 06:14:40 -05:00
clear shared connections when ldap_result fails with -1 (typically, remote server is down); fixes ITS#3217
This commit is contained in:
parent
c3984d9f59
commit
277d921945
5 changed files with 65 additions and 27 deletions
|
|
@ -164,6 +164,7 @@ typedef struct dncookie {
|
|||
#endif
|
||||
} dncookie;
|
||||
|
||||
int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
|
||||
struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs);
|
||||
int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs);
|
||||
int ldap_back_map_result(SlapReply *rs);
|
||||
|
|
|
|||
|
|
@ -209,6 +209,20 @@ static void myprint( Avlnode *root )
|
|||
}
|
||||
#endif /* PRINT_CONNTREE */
|
||||
|
||||
int
|
||||
ldap_back_freeconn( Operation *op, struct ldapconn *lc )
|
||||
{
|
||||
struct ldapinfo *li = (struct ldapinfo *) op->o_bd->be_private;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->conn_mutex );
|
||||
lc = avl_delete( &li->conntree, (caddr_t)lc,
|
||||
ldap_back_conn_cmp );
|
||||
ldap_back_conn_free( (void *)lc );
|
||||
ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ldapconn *
|
||||
ldap_back_getconn(Operation *op, SlapReply *rs)
|
||||
{
|
||||
|
|
@ -645,16 +659,16 @@ ldap_back_op_result(struct ldapconn *lc, Operation *op, SlapReply *rs,
|
|||
if ( ERR_OK( rs->sr_err ) ) {
|
||||
/* if result parsing fails, note the failure reason */
|
||||
if ( ldap_result( lc->ld, msgid, 1, NULL, &res ) == -1 ) {
|
||||
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
|
||||
&rs->sr_err);
|
||||
ldap_get_option( lc->ld, LDAP_OPT_ERROR_NUMBER,
|
||||
&rs->sr_err );
|
||||
|
||||
/* otherwise get the result; if it is not
|
||||
* LDAP_SUCCESS, record it in the reply
|
||||
* structure (this includes
|
||||
* LDAP_COMPARE_{TRUE|FALSE}) */
|
||||
} else {
|
||||
int rc = ldap_parse_result(lc->ld, res, &rs->sr_err,
|
||||
&match, &text, NULL, NULL, 1);
|
||||
int rc = ldap_parse_result( lc->ld, res, &rs->sr_err,
|
||||
&match, &text, NULL, NULL, 1 );
|
||||
rs->sr_text = text;
|
||||
if ( rc != LDAP_SUCCESS ) rs->sr_err = rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -501,6 +501,9 @@ ldap_back_exop_whoami(
|
|||
if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
|
||||
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
|
||||
&rs->sr_err);
|
||||
ldap_back_freeconn( op, lc );
|
||||
lc = NULL;
|
||||
|
||||
} else {
|
||||
rs->sr_err = ldap_parse_whoami(lc->ld, res, &bv);
|
||||
ldap_msgfree(res);
|
||||
|
|
|
|||
|
|
@ -145,6 +145,9 @@ ldap_back_exop_passwd(
|
|||
if (rc == LDAP_SUCCESS) {
|
||||
if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
|
||||
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &rc);
|
||||
ldap_back_freeconn( op, lc );
|
||||
lc = NULL;
|
||||
|
||||
} else {
|
||||
/* sigh. parse twice, because parse_passwd doesn't give
|
||||
* us the err / match / msg info.
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ ldap_back_search(
|
|||
struct berval mbase;
|
||||
struct berval mfilter = BER_BVNULL;
|
||||
int dontfreetext = 0;
|
||||
int freeconn = 0;
|
||||
dncookie dc;
|
||||
LDAPControl **ctrls = NULL;
|
||||
|
||||
|
|
@ -75,11 +76,14 @@ ldap_back_search(
|
|||
}
|
||||
|
||||
/* should we check return values? */
|
||||
if (op->ors_deref != -1)
|
||||
ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&op->ors_deref);
|
||||
if (op->ors_tlimit != SLAP_NO_LIMIT) {
|
||||
if ( op->ors_deref != -1 ) {
|
||||
ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&op->ors_deref );
|
||||
}
|
||||
|
||||
if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
|
||||
tv.tv_sec = op->ors_tlimit;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
} else {
|
||||
tv.tv_sec = 0;
|
||||
}
|
||||
|
|
@ -125,7 +129,7 @@ ldap_back_search(
|
|||
rs->sr_err = ldap_back_map_attrs( &li->rwmap.rwm_at,
|
||||
op->ors_attrs,
|
||||
BACKLDAP_MAP, &mapped_attrs );
|
||||
if ( rs->sr_err ) {
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
rc = -1;
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -139,7 +143,7 @@ ldap_back_search(
|
|||
}
|
||||
#endif /* LDAP_BACK_PROXY_AUTHZ */
|
||||
|
||||
rs->sr_err = ldap_search_ext(lc->ld, mbase.bv_val,
|
||||
rs->sr_err = ldap_search_ext( lc->ld, mbase.bv_val,
|
||||
op->ors_scope, mfilter.bv_val,
|
||||
mapped_attrs, op->ors_attrsonly,
|
||||
ctrls, NULL,
|
||||
|
|
@ -148,7 +152,11 @@ ldap_back_search(
|
|||
|
||||
if ( rs->sr_err != LDAP_SUCCESS ) {
|
||||
fail:;
|
||||
rc = ldap_back_op_result(lc, op, rs, msgid, 0);
|
||||
rc = ldap_back_op_result( lc, op, rs, msgid, 0 );
|
||||
if ( freeconn ) {
|
||||
ldap_back_freeconn( op, lc );
|
||||
lc = NULL;
|
||||
}
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -157,27 +165,28 @@ fail:;
|
|||
* but this is necessary for version matching, and for ACL processing.
|
||||
*/
|
||||
|
||||
for ( rc=0; rc != -1; rc = ldap_result(lc->ld, msgid, 0, &tv, &res))
|
||||
for ( rc = 0; rc != -1; rc = ldap_result( lc->ld, msgid, 0, &tv, &res ) )
|
||||
{
|
||||
/* check for abandon */
|
||||
if (op->o_abandon) {
|
||||
ldap_abandon(lc->ld, msgid);
|
||||
if ( op->o_abandon ) {
|
||||
ldap_abandon( lc->ld, msgid );
|
||||
rc = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
if ( rc == 0 ) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100000;
|
||||
ldap_pvt_thread_yield();
|
||||
|
||||
} else if (rc == LDAP_RES_SEARCH_ENTRY) {
|
||||
} else if ( rc == LDAP_RES_SEARCH_ENTRY ) {
|
||||
Entry ent = {0};
|
||||
struct berval bdn;
|
||||
int abort = 0;
|
||||
e = ldap_first_entry(lc->ld,res);
|
||||
if ( ( rc = ldap_build_entry(op, e, &ent, &bdn,
|
||||
LDAP_BUILD_ENTRY_PRIVATE)) == LDAP_SUCCESS ) {
|
||||
e = ldap_first_entry( lc->ld, res );
|
||||
rc = ldap_build_entry( op, e, &ent, &bdn,
|
||||
LDAP_BUILD_ENTRY_PRIVATE );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
rs->sr_entry = &ent;
|
||||
rs->sr_attrs = op->ors_attrs;
|
||||
rs->sr_flags = 0;
|
||||
|
|
@ -190,10 +199,12 @@ fail:;
|
|||
ent.e_attrs = a->a_next;
|
||||
|
||||
v = a->a_vals;
|
||||
if (a->a_vals != &dummy)
|
||||
if ( a->a_vals != &dummy ) {
|
||||
ber_bvarray_free(a->a_vals);
|
||||
if (a->a_nvals != v)
|
||||
}
|
||||
if ( a->a_nvals != v ) {
|
||||
ber_bvarray_free(a->a_nvals);
|
||||
}
|
||||
ch_free(a);
|
||||
}
|
||||
|
||||
|
|
@ -202,9 +213,9 @@ fail:;
|
|||
if ( ent.e_ndn )
|
||||
free( ent.e_ndn );
|
||||
}
|
||||
ldap_msgfree(res);
|
||||
ldap_msgfree( res );
|
||||
if ( abort ) {
|
||||
ldap_abandon(lc->ld, msgid);
|
||||
ldap_abandon( lc->ld, msgid );
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
|
@ -249,18 +260,24 @@ fail:;
|
|||
}
|
||||
|
||||
} else {
|
||||
rc = ldap_parse_result(lc->ld, res, &rs->sr_err,
|
||||
rc = ldap_parse_result( lc->ld, res, &rs->sr_err,
|
||||
&match.bv_val, (char **)&rs->sr_text,
|
||||
NULL, NULL, 1);
|
||||
if (rc != LDAP_SUCCESS ) rs->sr_err = rc;
|
||||
NULL, NULL, 1 );
|
||||
if (rc != LDAP_SUCCESS ) {
|
||||
rs->sr_err = rc;
|
||||
}
|
||||
rs->sr_err = slap_map_api2result( rs );
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == -1)
|
||||
if ( rc == -1 ) {
|
||||
/* FIXME: invalidate the connection? */
|
||||
rs->sr_err = LDAP_SERVER_DOWN;
|
||||
freeconn = 1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewrite the matched portion of the search base, if required
|
||||
|
|
@ -275,7 +292,7 @@ fail:;
|
|||
dc.normalized = 0;
|
||||
#endif
|
||||
match.bv_len = strlen( match.bv_val );
|
||||
ldap_back_dn_massage(&dc, &match, &mdn);
|
||||
ldap_back_dn_massage( &dc, &match, &mdn );
|
||||
rs->sr_matched = mdn.bv_val;
|
||||
}
|
||||
if ( rs->sr_v2ref ) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue