#include "ldap-int.h"
#include "lber.h"
+/* used by ldap_send_server_request and ldap_new_connection */
+#ifdef LDAP_R_COMPILE
+#define LDAP_CONN_LOCK_IF(nolock) \
+ { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); }
+#define LDAP_CONN_UNLOCK_IF(nolock) \
+ { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); }
+#define LDAP_REQ_LOCK_IF(nolock) \
+ { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); }
+#define LDAP_REQ_UNLOCK_IF(nolock) \
+ { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); }
+#define LDAP_RES_LOCK_IF(nolock) \
+ { if (nolock) LDAP_MUTEX_LOCK( &ld->ld_res_mutex ); }
+#define LDAP_RES_UNLOCK_IF(nolock) \
+ { if (nolock) LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex ); }
+#else
+#define LDAP_CONN_LOCK_IF(nolock)
+#define LDAP_CONN_UNLOCK_IF(nolock)
+#define LDAP_REQ_LOCK_IF(nolock)
+#define LDAP_REQ_UNLOCK_IF(nolock)
+#define LDAP_RES_LOCK_IF(nolock)
+#define LDAP_RES_UNLOCK_IF(nolock)
+#endif
+
static LDAPConn *find_connection LDAP_P(( LDAP *ld, LDAPURLDesc *srv, int any ));
static void use_connection LDAP_P(( LDAP *ld, LDAPConn *lc ));
static void ldap_free_request_int LDAP_P(( LDAP *ld, LDAPRequest *lr ));
void
ldap_set_ber_options( LDAP *ld, BerElement *ber )
{
+ /* ld_lberoptions is constant, hence no lock */
ber->ber_options = ld->ld_lberoptions;
}
+/* sets needed mutexes - no mutexes set to this point */
ber_int_t
ldap_send_initial_request(
LDAP *ld,
Debug( LDAP_DEBUG_TRACE, "ldap_send_initial_request\n", 0, 0, 0 );
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
+ LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
/* not connected yet */
rc = ldap_open_defconn( ld );
}
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
if( rc < 0 ) {
ber_free( ber, 1 );
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
return( -1 );
} else if ( rc == 0 ) {
Debug( LDAP_DEBUG_TRACE,
#ifdef LDAP_CONNECTIONLESS
if (LDAP_IS_UDP(ld)) {
if (msgtype == LDAP_REQ_BIND) {
+ LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
if (ld->ld_options.ldo_cldapdn)
ldap_memfree(ld->ld_options.ldo_cldapdn);
ld->ld_options.ldo_cldapdn = ldap_strdup(dn);
ber_free( ber, 1 );
+ LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
return 0;
}
if (msgtype != LDAP_REQ_ABANDON && msgtype != LDAP_REQ_SEARCH)
{
ber_free( ber, 1 );
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
return LDAP_PARAM_ERROR;
}
}
#endif
LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
rc = ldap_send_server_request( ld, ber, msgid, NULL,
- NULL, NULL, NULL );
+ NULL, NULL, NULL, 0, 0 );
LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
return(rc);
}
+/* protected by conn_mutex */
int
ldap_int_flush_request(
LDAP *ld,
{
LDAPConn *lc = lr->lr_conn;
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
if ( ber_flush2( lc->lconn_sb, lr->lr_ber, LBER_FLUSH_FREE_NEVER ) != 0 ) {
if ( sock_errno() == EAGAIN ) {
/* need to continue write later */
return 0;
}
+/*
+ * protected by req_mutex
+ * if m_noconn then protect using conn_lock
+ * else already protected with conn_lock
+ * if m_res then also protected by res_mutex
+ */
+
int
ldap_send_server_request(
LDAP *ld,
LDAPRequest *parentreq,
LDAPURLDesc **srvlist,
LDAPConn *lc,
- LDAPreqinfo *bind )
+ LDAPreqinfo *bind,
+ int m_noconn,
+ int m_res )
{
LDAPRequest *lr;
int incparent, rc;
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 );
incparent = 0;
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
+ LDAP_CONN_LOCK_IF(m_noconn);
if ( lc == NULL ) {
if ( srvlist == NULL ) {
lc = ld->ld_defconn;
incparent = 1;
++parentreq->lr_outrefcnt;
}
- lc = ldap_new_connection( ld, srvlist, 0, 1, bind );
+ lc = ldap_new_connection( ld, srvlist, 0,
+ 1, bind, 1, m_res );
}
}
}
/* async only occurs if a network timeout is set */
/* honor network timeout */
+ LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec )
{
/* caller will have to call again */
ld->ld_errno = LDAP_X_CONNECTING;
}
+ LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
/* fallthru */
default:
/* Forget about the bind */
--parentreq->lr_outrefcnt;
}
+ LDAP_CONN_UNLOCK_IF(m_noconn);
return( -1 );
}
if ( LDAP_IS_UDP( ld )) {
BerElement tmpber = *ber;
ber_rewind( &tmpber );
+ LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex );
rc = ber_write( &tmpber, ld->ld_options.ldo_peer,
sizeof( struct sockaddr ), 0 );
+ LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex );
if ( rc == -1 ) {
ld->ld_errno = LDAP_ENCODING_ERROR;
+ LDAP_CONN_UNLOCK_IF(m_noconn);
return rc;
}
}
{
rc = -1;
}
- if ( rc ) return rc;
+ if ( rc ) {
+ LDAP_CONN_UNLOCK_IF(m_noconn);
+ return rc;
+ }
lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) );
if ( lr == NULL ) {
/* Forget about the bind */
--parentreq->lr_outrefcnt;
}
+ LDAP_CONN_UNLOCK_IF(m_noconn);
return( -1 );
}
lr->lr_msgid = msgid;
msgid = -1;
}
+ LDAP_CONN_UNLOCK_IF(m_noconn);
return( msgid );
}
}
/*
- * caller must hold ld_req_mutex or be exclusive user of ld
- * if ( connect != 0 ) or ( bind != NULL ) caller must also hold
- * ld_req_mutex and ld_res_mutex
+ * always protected by conn_mutex
+ * optionally protected by req_mutex and res_mutex
*/
-
LDAPConn *
ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb,
- int connect, LDAPreqinfo *bind )
+ int connect, LDAPreqinfo *bind, int m_req, int m_res )
{
LDAPConn *lc;
int async = 0;
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n",
use_ldsb, connect, (bind != NULL) );
/*
}
lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED;
- LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
lc->lconn_next = ld->ld_conns;
ld->ld_conns = lc;
- LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
if ( connect ) {
- LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
- LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
-
#ifdef HAVE_TLS
if ( lc->lconn_server->lud_exts ) {
int rc, ext = find_tls_ext( lc->lconn_server );
++lc->lconn_refcnt; /* avoid premature free */
ld->ld_defconn = lc;
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
- LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
+ LDAP_REQ_UNLOCK_IF(m_req);
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
+ LDAP_RES_UNLOCK_IF(m_res);
rc = ldap_start_tls_s( ld, NULL, NULL );
- LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
+ LDAP_RES_LOCK_IF(m_res);
+ LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
+ LDAP_REQ_LOCK_IF(m_req);
ld->ld_defconn = savedefconn;
--lc->lconn_refcnt;
int err = 0;
LDAPConn *savedefconn;
- LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
- LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
-
/* Set flag to prevent additional referrals
* from being processed on this
* connection until the bind has completed
ld->ld_defconn = lc;
Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0);
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
- LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
+ LDAP_REQ_UNLOCK_IF(m_req);
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
+ LDAP_RES_UNLOCK_IF(m_res);
err = (*ld->ld_rebind_proc)( ld,
bind->ri_url, bind->ri_request, bind->ri_msgid,
ld->ld_rebind_params );
- LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
+ LDAP_RES_LOCK_IF(m_res);
+ LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
+ LDAP_REQ_LOCK_IF(m_req);
ld->ld_defconn = savedefconn;
--lc->lconn_refcnt;
"anonymous rebind via ldap_sasl_bind(\"\")\n",
0, 0, 0);
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
- LDAP_MUTEX_UNLOCK( &ld->ld_res_mutex );
+ LDAP_REQ_UNLOCK_IF(m_req);
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
+ LDAP_RES_UNLOCK_IF(m_res);
rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd,
NULL, NULL, &msgid );
if ( rc != LDAP_SUCCESS ) {
}
}
}
- LDAP_MUTEX_LOCK( &ld->ld_res_mutex );
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
+ LDAP_RES_LOCK_IF(m_res);
+ LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
+ LDAP_REQ_LOCK_IF(m_req);
ld->ld_defconn = savedefconn;
--lc->lconn_refcnt;
if ( lc != NULL )
lc->lconn_rebind_inprogress = 0;
}
-
return( lc );
}
+/* protected by ld_conn_mutex */
static LDAPConn *
find_connection( LDAP *ld, LDAPURLDesc *srv, int any )
/*
int lcu_port, lsu_port;
int found = 0;
- LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
lcu = lc->lconn_server;
lcu_port = ldap_pvt_url_scheme_port( lcu->lud_scheme,
if ( found )
break;
}
- LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
return lc;
}
-/*
- * NOTE: the caller holds ld_req_mutex
- */
+/* protected by ld_conn_mutex */
static void
use_connection( LDAP *ld, LDAPConn *lc )
{
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
++lc->lconn_refcnt;
lc->lconn_lastused = time( NULL );
}
+/* protected by ld_conn_mutex */
void
ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
{
LDAPConn *tmplc, *prevlc;
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
Debug( LDAP_DEBUG_TRACE,
"ldap_free_connection %d %d\n",
force, unbind, 0 );
if ( force || --lc->lconn_refcnt <= 0 ) {
/* remove from connections list first */
- LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
for ( prevlc = NULL, tmplc = ld->ld_conns;
tmplc != NULL;
}
prevlc = tmplc;
}
- LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
/* process connection callbacks */
{
ldap_conncb *cb;
lo = &ld->ld_options;
+ LDAP_MUTEX_LOCK( &lo->ldo_mutex );
if ( lo->ldo_conn_cbs ) {
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
cb = ll->ll_data;
cb->lc_del( ld, lc->lconn_sb, cb );
}
}
+ LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
lo = LDAP_INT_GLOBAL_OPT();
+ LDAP_MUTEX_LOCK( &lo->ldo_mutex );
if ( lo->ldo_conn_cbs ) {
for ( ll=lo->ldo_conn_cbs; ll; ll=ll->ll_next ) {
cb = ll->ll_data;
cb->lc_del( ld, lc->lconn_sb, cb );
}
}
+ LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
}
if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
}
+/* Protects self with ld_conn_mutex */
#ifdef LDAP_DEBUG
void
ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all )
char timebuf[32];
Debug( LDAP_DEBUG_TRACE, "** ld %p Connection%s:\n", (void *)ld, all ? "s" : "", 0 );
+ LDAP_MUTEX_LOCK( &ld->ld_conn_mutex );
for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
if ( lc->lconn_server != NULL ) {
Debug( LDAP_DEBUG_TRACE, "* host: %s port: %d%s\n",
break;
}
}
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
}
+/* protected by req_mutex and res_mutex */
void
ldap_dump_requests_and_responses( LDAP *ld )
{
}
#endif /* LDAP_DEBUG */
+/* protected by req_mutex */
static void
ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
{
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
/* if lr_refcnt > 0, the request has been looked up
* by ldap_find_request_by_msgid(); if in the meanwhile
* the request is free()'d by someone else, just decrease
LDAP_FREE( lr );
}
+/* protected by req_mutex */
void
ldap_free_request( LDAP *ld, LDAPRequest *lr )
{
LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
-
Debug( LDAP_DEBUG_TRACE, "ldap_free_request (origid %d, msgid %d)\n",
lr->lr_origid, lr->lr_msgid, 0 );
* (OUT) hadrefp = 1 if sucessfully followed referral
*
* Return value - number of referrals followed
+ *
+ * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
*/
int
ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp )
LDAPreqinfo rinfo;
LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref;
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
+ Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 );
+
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
*hadrefp = 0;
- Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 );
-
unfollowed = NULL;
rc = count = 0;
/* Send the new request to the server - may require a bind */
rinfo.ri_msgid = origreq->lr_origid;
rinfo.ri_url = refarray[i];
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
rc = ldap_send_server_request( ld, ber, id,
- origreq, &srv, NULL, &rinfo );
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
+ origreq, &srv, NULL, &rinfo, 0, 1 );
if ( rc < 0 ) {
/* Failure, try next referral in the list */
Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n",
if ( lc == NULL ) {
ld->ld_errno = LDAP_OPERATIONS_ERROR;
rc = -1;
+ LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex );
goto done;
}
}
/*
* XXX merging of errors in this routine needs to be improved
+ * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg)
*/
int
ldap_chase_referrals( LDAP *ld,
LDAPreqinfo rinfo;
LDAPConn *lc;
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex );
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex );
+ LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex );
Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 );
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
rinfo.ri_msgid = origreq->lr_origid;
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
rc = ldap_send_server_request( ld, ber, id,
- lr, &srv, NULL, &rinfo );
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
-
+ lr, &srv, NULL, &rinfo, 0, 1 );
LDAP_FREE( rinfo.ri_url );
if( rc >= 0 ) {
}
+/* protected by req_mutex */
LDAPRequest *
ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
{
LDAPRequest *lr;
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
if ( lr->lr_status == LDAP_REQST_COMPLETED ) {
continue; /* Skip completed requests */
break;
}
}
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
return( lr );
}
+/* protected by req_mutex */
void
ldap_return_request( LDAP *ld, LDAPRequest *lrx, int freeit )
{
LDAPRequest *lr;
- LDAP_MUTEX_LOCK( &ld->ld_req_mutex );
for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
if ( lr == lrx ) {
if ( lr->lr_refcnt > 0 ) {
} else if ( freeit ) {
ldap_free_request( ld, lrx );
}
- LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex );
}