mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-24 00:29:35 -05:00
pool privileged connections (ITS#4791)
This commit is contained in:
parent
1939ed3fc2
commit
7e8242d50d
12 changed files with 693 additions and 198 deletions
|
|
@ -44,22 +44,57 @@ typedef struct ldap_monitor_info_t {
|
|||
struct berval lmi_more_filter;
|
||||
} ldap_monitor_info_t;
|
||||
|
||||
enum {
|
||||
/* even numbers are connection types */
|
||||
LDAP_BACK_PCONN_FIRST = 0,
|
||||
LDAP_BACK_PCONN_ROOTDN = LDAP_BACK_PCONN_FIRST,
|
||||
LDAP_BACK_PCONN_ANON = 2,
|
||||
LDAP_BACK_PCONN_BIND = 4,
|
||||
|
||||
/* add the TLS bit */
|
||||
LDAP_BACK_PCONN_TLS = 0x1U,
|
||||
|
||||
LDAP_BACK_PCONN_ROOTDN_TLS = (LDAP_BACK_PCONN_ROOTDN|LDAP_BACK_PCONN_TLS),
|
||||
LDAP_BACK_PCONN_ANON_TLS = (LDAP_BACK_PCONN_ANON|LDAP_BACK_PCONN_TLS),
|
||||
LDAP_BACK_PCONN_BIND_TLS = (LDAP_BACK_PCONN_BIND|LDAP_BACK_PCONN_TLS),
|
||||
|
||||
LDAP_BACK_PCONN_LAST
|
||||
};
|
||||
|
||||
typedef struct ldapconn_t {
|
||||
Connection *lc_conn;
|
||||
#define LDAP_BACK_PCONN ((void *)0x0)
|
||||
#define LDAP_BACK_PCONN_TLS ((void *)0x1)
|
||||
#define LDAP_BACK_PCONN_BIND ((void *)0x2)
|
||||
#define LDAP_BACK_PCONN_BIND_TLS ((void *)0x3)
|
||||
#define LDAP_BACK_PCONN_LAST ((void *)0x4)
|
||||
#define LDAP_BACK_PCONN_ISPRIV(lc) ((void *)(lc)->lc_conn < LDAP_BACK_PCONN_LAST)
|
||||
#define LDAP_BACK_PCONN_ID(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) ? ( -1 - (long)(lc)->lc_conn ): (lc)->lc_conn->c_connid )
|
||||
#define LDAP_BACK_CONN2PRIV(lc) ((unsigned long)(lc)->lc_conn)
|
||||
#define LDAP_BACK_PCONN_ISPRIV(lc) ((void *)(lc)->lc_conn >= (void *)LDAP_BACK_PCONN_FIRST \
|
||||
&& (void *)(lc)->lc_conn < (void *)LDAP_BACK_PCONN_LAST)
|
||||
#define LDAP_BACK_PCONN_ISROOTDN(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
|
||||
&& (LDAP_BACK_CONN2PRIV((lc)) < LDAP_BACK_PCONN_ANON))
|
||||
#define LDAP_BACK_PCONN_ISANON(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
|
||||
&& (LDAP_BACK_CONN2PRIV((lc)) < LDAP_BACK_PCONN_BIND) \
|
||||
&& (LDAP_BACK_CONN2PRIV((lc)) >= LDAP_BACK_PCONN_ANON))
|
||||
#define LDAP_BACK_PCONN_ISBIND(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
|
||||
&& (LDAP_BACK_CONN2PRIV((lc)) >= LDAP_BACK_PCONN_BIND))
|
||||
#define LDAP_BACK_PCONN_ISTLS(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) \
|
||||
&& (LDAP_BACK_CONN2PRIV((lc)) & LDAP_BACK_PCONN_TLS))
|
||||
#define LDAP_BACK_PCONN_ID(lc) (LDAP_BACK_PCONN_ISPRIV((lc)) ? \
|
||||
( -1 - (long)(lc)->lc_conn ) : (lc)->lc_conn->c_connid )
|
||||
#ifdef HAVE_TLS
|
||||
#define LDAP_BACK_PCONN_SET(op) ((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_TLS : LDAP_BACK_PCONN)
|
||||
#define LDAP_BACK_PCONN_BIND_SET(op) ((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_BIND_TLS : LDAP_BACK_PCONN_BIND)
|
||||
#define LDAP_BACK_PCONN_ROOTDN_SET(lc, op) \
|
||||
((lc)->lc_conn = (void *)((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_ROOTDN_TLS : LDAP_BACK_PCONN_ROOTDN))
|
||||
#define LDAP_BACK_PCONN_ANON_SET(lc, op) \
|
||||
((lc)->lc_conn = (void *)((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_ANON_TLS : LDAP_BACK_PCONN_ANON))
|
||||
#define LDAP_BACK_PCONN_BIND_SET(lc, op) \
|
||||
((lc)->lc_conn = (void *)((op)->o_conn->c_is_tls ? LDAP_BACK_PCONN_BIND_TLS : LDAP_BACK_PCONN_BIND))
|
||||
#else /* ! HAVE_TLS */
|
||||
#define LDAP_BACK_PCONN_SET(op) (LDAP_BACK_PCONN)
|
||||
#define LDAP_BACK_PCONN_BIND_SET(op) (LDAP_BACK_PCONN_BIND)
|
||||
#define LDAP_BACK_PCONN_ROOTDN_SET(lc, op) \
|
||||
((lc)->lc_conn = (void *)LDAP_BACK_PCONN_ROOTDN)
|
||||
#define LDAP_BACK_PCONN_ANON_SET(lc, op) \
|
||||
((lc)->lc_conn = (void *)LDAP_BACK_PCONN_ANON)
|
||||
#define LDAP_BACK_PCONN_BIND_SET(lc, op) \
|
||||
((lc)->lc_conn = (void *)LDAP_BACK_PCONN_BIND)
|
||||
#endif /* ! HAVE_TLS */
|
||||
#define LDAP_BACK_PCONN_SET(lc, op) \
|
||||
(BER_BVISEMPTY(&(op)->o_ndn) ? \
|
||||
LDAP_BACK_PCONN_ANON_SET((lc), (op)) : LDAP_BACK_PCONN_ROOTDN_SET((lc), (op)))
|
||||
|
||||
LDAP *lc_ld;
|
||||
struct berval lc_cred;
|
||||
|
|
@ -93,6 +128,7 @@ typedef struct ldapconn_t {
|
|||
#define LDAP_BACK_FCONN_BINDING (0x00000010U)
|
||||
#define LDAP_BACK_FCONN_TAINTED (0x00000020U)
|
||||
#define LDAP_BACK_FCONN_ISIDASR (0x00000040U)
|
||||
#define LDAP_BACK_FCONN_CACHED (0x00000080U)
|
||||
|
||||
#define LDAP_BACK_CONN_ISBOUND(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
|
||||
#define LDAP_BACK_CONN_ISBOUND_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
|
||||
|
|
@ -120,12 +156,17 @@ typedef struct ldapconn_t {
|
|||
#define LDAP_BACK_CONN_ISIDASSERT_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISIDASR)
|
||||
#define LDAP_BACK_CONN_ISIDASSERT_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_ISIDASR)
|
||||
#define LDAP_BACK_CONN_ISIDASSERT_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), LDAP_BACK_FCONN_ISIDASR, (mlc))
|
||||
#define LDAP_BACK_CONN_CACHED(lc) LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_CACHED)
|
||||
#define LDAP_BACK_CONN_CACHED_SET(lc) LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_CACHED)
|
||||
#define LDAP_BACK_CONN_CACHED_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_CACHED)
|
||||
|
||||
unsigned lc_refcnt;
|
||||
unsigned lc_binding;
|
||||
unsigned lc_flags;
|
||||
time_t lc_create_time;
|
||||
time_t lc_time;
|
||||
|
||||
LDAP_TAILQ_ENTRY(ldapconn_t) lc_q;
|
||||
} ldapconn_t;
|
||||
|
||||
typedef struct ldap_avl_info_t {
|
||||
|
|
@ -259,8 +300,11 @@ typedef struct ldapinfo_t {
|
|||
#define LDAP_BACK_F_CANCEL_MASK (LDAP_BACK_F_CANCEL_IGNORE|LDAP_BACK_F_CANCEL_EXOP)
|
||||
#define LDAP_BACK_F_CANCEL_MASK2 (LDAP_BACK_F_CANCEL_MASK|LDAP_BACK_F_CANCEL_EXOP_DISCOVER)
|
||||
|
||||
#define LDAP_BACK_ISSET(li,f) ( ( (li)->li_flags & (f) ) == (f) )
|
||||
#define LDAP_BACK_ISMASK(li,m,f) ( ( (li)->li_flags & (m) ) == (f) )
|
||||
#define LDAP_BACK_ISSET_F(ff,f) ( ( (ff) & (f) ) == (f) )
|
||||
#define LDAP_BACK_ISMASK_F(ff,m,f) ( ( (ff) & (m) ) == (f) )
|
||||
|
||||
#define LDAP_BACK_ISSET(li,f) LDAP_BACK_ISSET_F( (li)->li_flags, (f) )
|
||||
#define LDAP_BACK_ISMASK(li,m,f) LDAP_BACK_ISMASK_F( (li)->li_flags, (m), (f) )
|
||||
|
||||
#define LDAP_BACK_SAVECRED(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_SAVECRED )
|
||||
#define LDAP_BACK_USE_TLS(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_USE_TLS )
|
||||
|
|
@ -269,6 +313,10 @@ typedef struct ldapinfo_t {
|
|||
#define LDAP_BACK_CHASE_REFERRALS(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_CHASE_REFERRALS )
|
||||
#define LDAP_BACK_PROXY_WHOAMI(li) LDAP_BACK_ISSET( (li), LDAP_BACK_F_PROXY_WHOAMI )
|
||||
|
||||
#define LDAP_BACK_USE_TLS_F(ff) LDAP_BACK_ISSET_F( (ff), LDAP_BACK_F_USE_TLS )
|
||||
#define LDAP_BACK_PROPAGATE_TLS_F(ff) LDAP_BACK_ISSET_F( (ff), LDAP_BACK_F_PROPAGATE_TLS )
|
||||
#define LDAP_BACK_TLS_CRITICAL_F(ff) LDAP_BACK_ISSET_F( (ff), LDAP_BACK_F_TLS_CRITICAL )
|
||||
|
||||
#define LDAP_BACK_T_F(li) LDAP_BACK_ISMASK( (li), LDAP_BACK_F_T_F_MASK, LDAP_BACK_F_T_F )
|
||||
#define LDAP_BACK_T_F_DISCOVER(li) LDAP_BACK_ISMASK( (li), LDAP_BACK_F_T_F_MASK2, LDAP_BACK_F_T_F_DISCOVER )
|
||||
|
||||
|
|
@ -285,10 +333,23 @@ typedef struct ldapinfo_t {
|
|||
|
||||
int li_version;
|
||||
|
||||
/* cached connections;
|
||||
* special conns are in tailq rather than in tree */
|
||||
ldap_avl_info_t li_conninfo;
|
||||
|
||||
ldap_monitor_info_t li_monitor_info;
|
||||
|
||||
struct {
|
||||
int lic_num;
|
||||
LDAP_TAILQ_HEAD(lc_conn_priv_q, ldapconn_t) lic_priv;
|
||||
} li_conn_priv[ LDAP_BACK_PCONN_LAST ];
|
||||
int li_conn_priv_max;
|
||||
#define LDAP_BACK_CONN_PRIV_MIN (1)
|
||||
#define LDAP_BACK_CONN_PRIV_MAX (256)
|
||||
/* must be between LDAP_BACK_CONN_PRIV_MIN
|
||||
* and LDAP_BACK_CONN_PRIV_MAX ! */
|
||||
#define LDAP_BACK_CONN_PRIV_DEFAULT (16)
|
||||
|
||||
sig_atomic_t li_isquarantined;
|
||||
#define LDAP_BACK_FQ_NO (0)
|
||||
#define LDAP_BACK_FQ_YES (1)
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
static void
|
||||
ravl_print( Avlnode *root, int depth )
|
||||
ldap_back_ravl_print( Avlnode *root, int depth )
|
||||
{
|
||||
int i;
|
||||
ldapconn_t *lc;
|
||||
|
|
@ -50,38 +50,70 @@ ravl_print( Avlnode *root, int depth )
|
|||
return;
|
||||
}
|
||||
|
||||
ravl_print( root->avl_right, depth+1 );
|
||||
ldap_back_ravl_print( root->avl_right, depth+1 );
|
||||
|
||||
for ( i = 0; i < depth; i++ ) {
|
||||
fprintf( stderr, "-" );
|
||||
}
|
||||
|
||||
lc = root->avl_data;
|
||||
fprintf( stderr, "lc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
|
||||
fprintf( stderr, "lc=%p local=\"%s\" conn=%p %s refcnt=%d flags=0x%08x\n",
|
||||
(void *)lc,
|
||||
lc->lc_local_ndn.bv_val ? lc->lc_local_ndn.bv_val : "",
|
||||
(void *)lc->lc_conn,
|
||||
avl_bf2str( root->avl_bf ), lc->lc_refcnt );
|
||||
avl_bf2str( root->avl_bf ), lc->lc_refcnt, lc->lc_lcflags );
|
||||
|
||||
ravl_print( root->avl_left, depth+1 );
|
||||
ldap_back_ravl_print( root->avl_left, depth+1 );
|
||||
}
|
||||
|
||||
static char* priv2str[] = {
|
||||
"privileged",
|
||||
"privileged/TLS",
|
||||
"anonymous",
|
||||
"anonymous/TLS",
|
||||
"bind",
|
||||
"bind/TLS",
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
ldap_back_print_conntree( Avlnode *root, char *msg )
|
||||
ldap_back_print_conntree( ldapinfo_t *li, char *msg )
|
||||
{
|
||||
int c;
|
||||
|
||||
fprintf( stderr, "========> %s\n", msg );
|
||||
|
||||
for ( c = LDAP_BACK_PCONN_FIRST; c < LDAP_BACK_PCONN_LAST; c++ ) {
|
||||
int i = 0;
|
||||
ldapconn_t *lc;
|
||||
|
||||
fprintf( stderr, " %s[%d]\n", priv2str[ c ], li->li_conn_priv[ c ].lic_num );
|
||||
|
||||
LDAP_TAILQ_FOREACH( lc, &li->li_conn_priv[ c ].lic_priv, lc_q )
|
||||
{
|
||||
fprintf( stderr, " [%d] lc=%p local=\"%s\" conn=%p refcnt=%d flags=0x%08x\n",
|
||||
i,
|
||||
(void *)lc,
|
||||
lc->lc_local_ndn.bv_val ? lc->lc_local_ndn.bv_val : "",
|
||||
(void *)lc->lc_conn, lc->lc_refcnt, lc->lc_lcflags );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( root == 0 ) {
|
||||
if ( li->li_conninfo.lai_tree == 0 ) {
|
||||
fprintf( stderr, "\t(empty)\n" );
|
||||
|
||||
} else {
|
||||
ravl_print( root, 0 );
|
||||
ldap_back_ravl_print( li->li_conninfo.lai_tree, 0 );
|
||||
}
|
||||
|
||||
fprintf( stderr, "<======== %s\n", msg );
|
||||
}
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
static int
|
||||
ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock );
|
||||
|
||||
static ldapconn_t *
|
||||
ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok,
|
||||
struct berval *binddn, struct berval *bindcred );
|
||||
|
|
@ -116,10 +148,17 @@ ldap_back_bind( Operation *op, SlapReply *rs )
|
|||
return rs->sr_err;
|
||||
}
|
||||
|
||||
/* we can do (almost) whatever we want with this conn,
|
||||
* because either it's temporary, or it's marked as binding */
|
||||
if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
|
||||
ch_free( lc->lc_bound_ndn.bv_val );
|
||||
BER_BVZERO( &lc->lc_bound_ndn );
|
||||
}
|
||||
if ( !BER_BVISNULL( &lc->lc_cred ) ) {
|
||||
memset( lc->lc_cred.bv_val, 0, lc->lc_cred.bv_len );
|
||||
ch_free( lc->lc_cred.bv_val );
|
||||
BER_BVZERO( &lc->lc_cred );
|
||||
}
|
||||
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
|
||||
|
||||
retry:;
|
||||
|
|
@ -159,13 +198,17 @@ retry:;
|
|||
LDAP_BACK_CONN_ISBOUND_SET( lc );
|
||||
ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn );
|
||||
|
||||
if ( !BER_BVISNULL( &lc->lc_cred ) ) {
|
||||
memset( lc->lc_cred.bv_val, 0,
|
||||
lc->lc_cred.bv_len );
|
||||
}
|
||||
|
||||
if ( LDAP_BACK_SAVECRED( li ) ) {
|
||||
if ( !BER_BVISNULL( &lc->lc_cred ) ) {
|
||||
memset( lc->lc_cred.bv_val, 0,
|
||||
lc->lc_cred.bv_len );
|
||||
}
|
||||
ber_bvreplace( &lc->lc_cred, &op->orb_cred );
|
||||
ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
|
||||
|
||||
} else {
|
||||
lc->lc_cred.bv_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -174,8 +217,8 @@ retry:;
|
|||
|
||||
/* must re-insert if local DN changed as result of bind */
|
||||
if ( !LDAP_BACK_CONN_ISBOUND( lc )
|
||||
|| ( LDAP_BACK_CONN_ISBOUND( lc )
|
||||
&& !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) ) )
|
||||
|| ( !dn_match( &op->o_req_ndn, &lc->lc_local_ndn )
|
||||
&& !LDAP_BACK_PCONN_ISPRIV( lc ) ) )
|
||||
{
|
||||
int lerr = -1;
|
||||
ldapconn_t *tmplc;
|
||||
|
|
@ -190,13 +233,31 @@ retry_lock:;
|
|||
}
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, ">>> ldap_back_bind" );
|
||||
ldap_back_print_conntree( li, ">>> ldap_back_bind" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
|
||||
assert( lc->lc_refcnt == 1 );
|
||||
tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndnlc_cmp );
|
||||
assert( tmplc == NULL || lc == tmplc );
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( lc ) ) {
|
||||
/* this can happen, for example, if the bind fails
|
||||
* for some reason... */
|
||||
if ( lc->lc_q.tqe_prev != NULL ) {
|
||||
assert( LDAP_BACK_CONN_CACHED( lc ) );
|
||||
assert( li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num > 0 );
|
||||
LDAP_TAILQ_REMOVE( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, lc, lc_q );
|
||||
li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num--;
|
||||
lc->lc_q.tqe_prev = NULL;
|
||||
lc->lc_q.tqe_next = NULL;
|
||||
|
||||
} else {
|
||||
assert( !LDAP_BACK_CONN_CACHED( lc ) );
|
||||
}
|
||||
|
||||
} else {
|
||||
tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndnlc_cmp );
|
||||
assert( ( LDAP_BACK_CONN_TAINTED( lc ) && tmplc == NULL ) || lc == tmplc );
|
||||
}
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( lc );
|
||||
|
||||
/* delete all cached connections with the current connection */
|
||||
if ( LDAP_BACK_SINGLECONN( li ) ) {
|
||||
|
|
@ -209,6 +270,7 @@ retry_lock:;
|
|||
if ( tmplc->lc_refcnt != 0 ) {
|
||||
/* taint it */
|
||||
LDAP_BACK_CONN_TAINTED_SET( tmplc );
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( tmplc );
|
||||
|
||||
} else {
|
||||
/*
|
||||
|
|
@ -224,19 +286,20 @@ retry_lock:;
|
|||
if ( LDAP_BACK_CONN_ISBOUND( lc ) ) {
|
||||
ber_bvreplace( &lc->lc_local_ndn, &op->o_req_ndn );
|
||||
if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
|
||||
lc->lc_conn = LDAP_BACK_PCONN_SET( op );
|
||||
LDAP_BACK_PCONN_ROOTDN_SET( lc, op );
|
||||
}
|
||||
lerr = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndn_cmp, ldap_back_conndn_dup );
|
||||
}
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, "<<< ldap_back_bind" );
|
||||
ldap_back_print_conntree( li, "<<< ldap_back_bind" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
|
||||
switch ( lerr ) {
|
||||
case 0:
|
||||
LDAP_BACK_CONN_CACHED_SET( lc );
|
||||
break;
|
||||
|
||||
case -1:
|
||||
|
|
@ -350,29 +413,51 @@ ldap_back_conndn_dup( void *c1, void *c2 )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock )
|
||||
{
|
||||
ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
|
||||
ldapconn_t *tmplc;
|
||||
|
||||
if ( dolock ) {
|
||||
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
|
||||
}
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, ">>> ldap_back_freeconn" );
|
||||
ldap_back_print_conntree( li, ">>> ldap_back_freeconn" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndnlc_cmp );
|
||||
assert( LDAP_BACK_CONN_TAINTED( lc ) || tmplc == lc );
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( lc ) ) {
|
||||
if ( lc->lc_q.tqe_prev != NULL ) {
|
||||
assert( LDAP_BACK_CONN_CACHED( lc ) );
|
||||
assert( li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num > 0 );
|
||||
li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num--;
|
||||
LDAP_TAILQ_REMOVE( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, lc, lc_q );
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( lc );
|
||||
|
||||
} else {
|
||||
assert( !LDAP_BACK_CONN_CACHED( lc ) );
|
||||
}
|
||||
lc->lc_q.tqe_prev = NULL;
|
||||
lc->lc_q.tqe_next = NULL;
|
||||
|
||||
} else {
|
||||
ldapconn_t *tmplc = NULL;
|
||||
|
||||
if ( LDAP_BACK_CONN_CACHED( lc ) ) {
|
||||
tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndnlc_cmp );
|
||||
assert( tmplc == lc );
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( lc );
|
||||
}
|
||||
assert( LDAP_BACK_CONN_TAINTED( lc ) || tmplc == lc );
|
||||
}
|
||||
|
||||
if ( lc->lc_refcnt == 0 ) {
|
||||
ldap_back_conn_free( (void *)lc );
|
||||
}
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, "<<< ldap_back_freeconn" );
|
||||
ldap_back_print_conntree( li, "<<< ldap_back_freeconn" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
if ( dolock ) {
|
||||
|
|
@ -394,13 +479,9 @@ ldap_back_start_tls(
|
|||
const char **text )
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
ldapinfo_t dummy;
|
||||
|
||||
/* this is ridiculous... */
|
||||
dummy.li_flags = flags;
|
||||
|
||||
/* start TLS ("tls-[try-]{start,propagate}" statements) */
|
||||
if ( ( LDAP_BACK_USE_TLS( &dummy ) || ( *is_tls && LDAP_BACK_PROPAGATE_TLS( &dummy ) ) )
|
||||
if ( ( LDAP_BACK_USE_TLS_F( flags ) || ( *is_tls && LDAP_BACK_PROPAGATE_TLS_F( flags ) ) )
|
||||
&& !ldap_is_ldaps_url( url ) )
|
||||
{
|
||||
#ifdef SLAP_STARTTLS_ASYNCHRONOUS
|
||||
|
|
@ -509,7 +590,7 @@ retry:;
|
|||
break;
|
||||
|
||||
default:
|
||||
if ( LDAP_BACK_TLS_CRITICAL( &dummy ) ) {
|
||||
if ( LDAP_BACK_TLS_CRITICAL_F( flags ) ) {
|
||||
*text = "could not start TLS";
|
||||
break;
|
||||
}
|
||||
|
|
@ -655,19 +736,21 @@ ldap_back_getconn(
|
|||
slap_retry_info_t *ri = &li->li_quarantine;
|
||||
int dont_retry = 1;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex );
|
||||
if ( li->li_isquarantined == LDAP_BACK_FQ_YES ) {
|
||||
dont_retry = ( ri->ri_num[ ri->ri_idx ] == SLAP_RETRYNUM_TAIL
|
||||
|| slap_get_time() < ri->ri_last + ri->ri_interval[ ri->ri_idx ] );
|
||||
if ( !dont_retry ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: ldap_back_getconn quarantine "
|
||||
"retry block #%d try #%d.\n",
|
||||
op->o_log_prefix, ri->ri_idx, ri->ri_count );
|
||||
li->li_isquarantined = LDAP_BACK_FQ_RETRYING;
|
||||
if ( li->li_quarantine.ri_interval ) {
|
||||
ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex );
|
||||
if ( li->li_isquarantined == LDAP_BACK_FQ_YES ) {
|
||||
dont_retry = ( ri->ri_num[ ri->ri_idx ] == SLAP_RETRYNUM_TAIL
|
||||
|| slap_get_time() < ri->ri_last + ri->ri_interval[ ri->ri_idx ] );
|
||||
if ( !dont_retry ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: ldap_back_getconn quarantine "
|
||||
"retry block #%d try #%d.\n",
|
||||
op->o_log_prefix, ri->ri_idx, ri->ri_count );
|
||||
li->li_isquarantined = LDAP_BACK_FQ_RETRYING;
|
||||
}
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );
|
||||
|
||||
if ( dont_retry ) {
|
||||
rs->sr_err = LDAP_UNAVAILABLE;
|
||||
|
|
@ -682,7 +765,7 @@ ldap_back_getconn(
|
|||
if ( op->o_do_not_cache || be_isroot( op ) ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( &lc_curr );
|
||||
lc_curr.lc_local_ndn = op->o_bd->be_rootndn;
|
||||
lc_curr.lc_conn = LDAP_BACK_PCONN_SET( op );
|
||||
LDAP_BACK_PCONN_ROOTDN_SET( &lc_curr, op );
|
||||
|
||||
} else {
|
||||
struct berval tmpbinddn,
|
||||
|
|
@ -723,12 +806,12 @@ ldap_back_getconn(
|
|||
} else {
|
||||
if ( isproxyauthz && !( sendok & LDAP_BACK_BINDING ) ) {
|
||||
lc_curr.lc_local_ndn = *binddn;
|
||||
lc_curr.lc_conn = LDAP_BACK_PCONN_SET( op );
|
||||
LDAP_BACK_PCONN_ROOTDN_SET( &lc_curr, op );
|
||||
LDAP_BACK_CONN_ISIDASSERT_SET( &lc_curr );
|
||||
|
||||
} else if ( isproxyauthz && ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) {
|
||||
lc_curr.lc_local_ndn = slap_empty_bv;
|
||||
lc_curr.lc_conn = LDAP_BACK_PCONN_BIND_SET( op );
|
||||
LDAP_BACK_PCONN_BIND_SET( &lc_curr, op );
|
||||
LDAP_BACK_CONN_ISIDASSERT_SET( &lc_curr );
|
||||
lookupconn = 1;
|
||||
|
||||
|
|
@ -736,19 +819,51 @@ ldap_back_getconn(
|
|||
lc_curr.lc_conn = op->o_conn;
|
||||
|
||||
} else {
|
||||
lc_curr.lc_conn = LDAP_BACK_PCONN_SET( op );
|
||||
LDAP_BACK_PCONN_ANON_SET( &lc_curr, op );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Explicit Bind requests always get their own conn */
|
||||
if ( lookupconn ) {
|
||||
/* Searches for a ldapconn in the avl tree */
|
||||
retry_lock:
|
||||
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( &lc_curr ) ) {
|
||||
/* lookup a conn that's not binding */
|
||||
LDAP_TAILQ_FOREACH( lc,
|
||||
&li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_priv,
|
||||
lc_q )
|
||||
{
|
||||
if ( !LDAP_BACK_CONN_BINDING( lc ) && lc->lc_refcnt == 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( lc != NULL ) {
|
||||
if ( lc != LDAP_TAILQ_LAST( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv,
|
||||
ldapconn_t, lc_q ) )
|
||||
{
|
||||
LDAP_TAILQ_REMOVE( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv,
|
||||
lc, lc_q );
|
||||
lc->lc_q.tqe_prev = NULL;
|
||||
lc->lc_q.tqe_next = NULL;
|
||||
LDAP_TAILQ_INSERT_TAIL( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv,
|
||||
lc, lc_q );
|
||||
}
|
||||
|
||||
} else if ( !LDAP_BACK_USE_TEMPORARIES( li )
|
||||
&& li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_num == li->li_conn_priv_max )
|
||||
{
|
||||
lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_priv );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* Searches for a ldapconn in the avl tree */
|
||||
lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree,
|
||||
(caddr_t)&lc_curr, ldap_back_conndn_cmp );
|
||||
}
|
||||
|
||||
lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree,
|
||||
(caddr_t)&lc_curr, ldap_back_conndn_cmp );
|
||||
if ( lc != NULL ) {
|
||||
/* Don't reuse connections while they're still binding */
|
||||
if ( LDAP_BACK_CONN_BINDING( lc ) ) {
|
||||
|
|
@ -758,11 +873,10 @@ retry_lock:
|
|||
ldap_pvt_thread_yield();
|
||||
goto retry_lock;
|
||||
}
|
||||
|
||||
lc = NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( lc != NULL ) {
|
||||
if ( op->o_tag == LDAP_REQ_BIND ) {
|
||||
/* right now, this is the only possible case */
|
||||
assert( ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) );
|
||||
|
|
@ -813,8 +927,10 @@ retry_lock:
|
|||
LDAP_BACK_CONN_ISPRIV_SET( lc );
|
||||
|
||||
} else if ( LDAP_BACK_CONN_ISIDASSERT( &lc_curr ) ) {
|
||||
ber_dupbv( &lc->lc_bound_ndn, &li->li_idassert_authcDN );
|
||||
ber_dupbv( &lc->lc_cred, &li->li_idassert_passwd );
|
||||
if ( !LDAP_BACK_PCONN_ISBIND( &lc_curr ) ) {
|
||||
ber_dupbv( &lc->lc_bound_ndn, &li->li_idassert_authcDN );
|
||||
ber_dupbv( &lc->lc_cred, &li->li_idassert_passwd );
|
||||
}
|
||||
LDAP_BACK_CONN_ISIDASSERT_SET( lc );
|
||||
|
||||
} else {
|
||||
|
|
@ -832,15 +948,22 @@ retry_lock:
|
|||
* check if the non-TLS connection was already
|
||||
* in cache; in case, destroy the newly created
|
||||
* connection and use the existing one */
|
||||
if ( lc->lc_conn == LDAP_BACK_PCONN_TLS
|
||||
if ( LDAP_BACK_PCONN_ISTLS( lc )
|
||||
&& !ldap_tls_inplace( lc->lc_ld ) )
|
||||
{
|
||||
ldapconn_t *tmplc;
|
||||
ldapconn_t *tmplc = NULL;
|
||||
int idx = LDAP_BACK_CONN2PRIV( &lc_curr ) - 1;
|
||||
|
||||
lc_curr.lc_conn = LDAP_BACK_PCONN;
|
||||
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
|
||||
tmplc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree,
|
||||
(caddr_t)&lc_curr, ldap_back_conndn_cmp );
|
||||
LDAP_TAILQ_FOREACH( tmplc,
|
||||
&li->li_conn_priv[ idx ].lic_priv,
|
||||
lc_q )
|
||||
{
|
||||
if ( !LDAP_BACK_CONN_BINDING( tmplc ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tmplc != NULL ) {
|
||||
refcnt = ++tmplc->lc_refcnt;
|
||||
binding = ++tmplc->lc_binding;
|
||||
|
|
@ -855,56 +978,83 @@ retry_lock:
|
|||
}
|
||||
#endif /* HAVE_TLS */
|
||||
|
||||
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
|
||||
|
||||
/* Inserts the newly created ldapconn in the avl tree */
|
||||
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, ">>> ldap_back_getconn(insert)" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
LDAP_BACK_CONN_ISBOUND_CLEAR( lc );
|
||||
|
||||
assert( lc->lc_refcnt == 1 );
|
||||
assert( lc->lc_binding == 1 );
|
||||
rs->sr_err = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndn_cmp, ldap_back_conndn_dup );
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, "<<< ldap_back_getconn(insert)" );
|
||||
ldap_back_print_conntree( li, ">>> ldap_back_getconn(insert)" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( lc ) ) {
|
||||
if ( li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num < li->li_conn_priv_max ) {
|
||||
LDAP_TAILQ_INSERT_TAIL( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, lc, lc_q );
|
||||
li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num++;
|
||||
LDAP_BACK_CONN_CACHED_SET( lc );
|
||||
|
||||
} else {
|
||||
LDAP_BACK_CONN_TAINTED_SET( lc );
|
||||
}
|
||||
rs->sr_err = 0;
|
||||
|
||||
} else {
|
||||
rs->sr_err = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndn_cmp, ldap_back_conndn_dup );
|
||||
LDAP_BACK_CONN_CACHED_SET( lc );
|
||||
}
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li, "<<< ldap_back_getconn(insert)" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=>ldap_back_getconn: conn %p inserted refcnt=%u binding=%u\n",
|
||||
(void *)lc, refcnt, binding );
|
||||
if ( LogTest( LDAP_DEBUG_TRACE ) ) {
|
||||
char buf[ SLAP_TEXT_BUFLEN ];
|
||||
|
||||
snprintf( buf, sizeof( buf ),
|
||||
"lc=%p inserted refcnt=%u binding=%u rc=%d",
|
||||
(void *)lc, refcnt, binding, rs->sr_err );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"=>ldap_back_getconn: %s: %s\n",
|
||||
op->o_log_prefix, buf, 0 );
|
||||
}
|
||||
|
||||
/* Err could be -1 in case a duplicate ldapconn is inserted */
|
||||
switch ( rs->sr_err ) {
|
||||
case 0:
|
||||
break;
|
||||
if ( !LDAP_BACK_PCONN_ISPRIV( lc ) ) {
|
||||
/* Err could be -1 in case a duplicate ldapconn is inserted */
|
||||
switch ( rs->sr_err ) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case -1:
|
||||
if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( li ) ) {
|
||||
/* duplicate: free and try to get the newly created one */
|
||||
case -1:
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( lc );
|
||||
if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( li ) ) {
|
||||
/* duplicate: free and try to get the newly created one */
|
||||
ldap_back_conn_free( lc );
|
||||
lc = NULL;
|
||||
goto retry_lock;
|
||||
}
|
||||
|
||||
/* taint connection, so that it'll be freed when released */
|
||||
LDAP_BACK_CONN_TAINTED_SET( lc );
|
||||
break;
|
||||
|
||||
default:
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( lc );
|
||||
ldap_back_conn_free( lc );
|
||||
lc = NULL;
|
||||
goto retry_lock;
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "proxy bind collision";
|
||||
if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_text = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* taint connection, so that it'll be freed when released */
|
||||
LDAP_BACK_CONN_TAINTED_SET( lc );
|
||||
break;
|
||||
|
||||
default:
|
||||
ldap_back_conn_free( lc );
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "proxy bind collision";
|
||||
if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_text = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -918,16 +1068,37 @@ retry_lock:
|
|||
/* let it be used, but taint/delete it so that
|
||||
* no-one else can look it up any further */
|
||||
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, ">>> ldap_back_getconn(timeout)" );
|
||||
ldap_back_print_conntree( li, ">>> ldap_back_getconn(timeout)" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
(void *)avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( lc ) ) {
|
||||
if ( lc->lc_q.tqe_prev != NULL ) {
|
||||
assert( LDAP_BACK_CONN_CACHED( lc ) );
|
||||
assert( li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num > 0 );
|
||||
LDAP_TAILQ_REMOVE( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv,
|
||||
lc, lc_q );
|
||||
li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num--;
|
||||
lc->lc_q.tqe_prev = NULL;
|
||||
lc->lc_q.tqe_next = NULL;
|
||||
|
||||
} else {
|
||||
assert( !LDAP_BACK_CONN_CACHED( lc ) );
|
||||
}
|
||||
|
||||
} else {
|
||||
(void)avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
|
||||
ldap_back_conndnlc_cmp );
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, "<<< ldap_back_getconn(timeout)" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
|
||||
}
|
||||
LDAP_BACK_CONN_TAINTED_SET( lc );
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( lc );
|
||||
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li, "<<< ldap_back_getconn(timeout)" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
|
||||
}
|
||||
|
||||
if ( LogTest( LDAP_DEBUG_TRACE ) ) {
|
||||
|
|
@ -1620,8 +1791,9 @@ retry:;
|
|||
int
|
||||
ldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok )
|
||||
{
|
||||
int rc = 0;
|
||||
ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private;
|
||||
int rc = 0,
|
||||
binding;
|
||||
|
||||
assert( lcp != NULL );
|
||||
assert( *lcp != NULL );
|
||||
|
|
@ -1629,6 +1801,8 @@ ldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_
|
|||
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
|
||||
|
||||
if ( (*lcp)->lc_refcnt == 1 ) {
|
||||
binding = LDAP_BACK_CONN_BINDING( *lcp );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s ldap_back_retry: retrying URI=\"%s\" DN=\"%s\"\n",
|
||||
|
|
@ -1651,6 +1825,9 @@ ldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_
|
|||
rc = 0;
|
||||
|
||||
} else if ( ( sendok & LDAP_BACK_BINDING ) ) {
|
||||
if ( binding ) {
|
||||
LDAP_BACK_CONN_BINDING_SET( *lcp );
|
||||
}
|
||||
rc = 1;
|
||||
|
||||
} else {
|
||||
|
|
@ -1937,13 +2114,17 @@ ldap_back_proxy_authz_bind(
|
|||
LDAP_BACK_CONN_ISBOUND_SET( lc );
|
||||
ber_bvreplace( &lc->lc_bound_ndn, binddn );
|
||||
|
||||
if ( !BER_BVISNULL( &lc->lc_cred ) ) {
|
||||
memset( lc->lc_cred.bv_val, 0,
|
||||
lc->lc_cred.bv_len );
|
||||
}
|
||||
|
||||
if ( LDAP_BACK_SAVECRED( li ) ) {
|
||||
if ( !BER_BVISNULL( &lc->lc_cred ) ) {
|
||||
memset( lc->lc_cred.bv_val, 0,
|
||||
lc->lc_cred.bv_len );
|
||||
}
|
||||
ber_bvreplace( &lc->lc_cred, bindcred );
|
||||
ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );
|
||||
|
||||
} else {
|
||||
lc->lc_cred.bv_len = 0;
|
||||
}
|
||||
}
|
||||
done:;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ enum {
|
|||
LDAP_BACK_CFG_VERSION,
|
||||
LDAP_BACK_CFG_SINGLECONN,
|
||||
LDAP_BACK_CFG_USETEMP,
|
||||
LDAP_BACK_CFG_CONNPOOLMAX,
|
||||
LDAP_BACK_CFG_CANCEL,
|
||||
LDAP_BACK_CFG_QUARANTINE,
|
||||
LDAP_BACK_CFG_REWRITE,
|
||||
|
|
@ -286,6 +287,14 @@ static ConfigTable ldapcfg[] = {
|
|||
"SYNTAX OMsBoolean "
|
||||
"SINGLE-VALUE )",
|
||||
NULL, NULL },
|
||||
{ "conn-pool-max", "<n>", 2, 0, 0,
|
||||
ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
|
||||
ldap_back_cf_gen, "( OLcfgDbAt:3.23 "
|
||||
"NAME 'olcDbConnectionPoolMax' "
|
||||
"DESC 'Max size of privileged connections pool' "
|
||||
"SYNTAX OMsInteger "
|
||||
"SINGLE-VALUE )",
|
||||
NULL, NULL },
|
||||
{ "suffixmassage", "[virtual]> <real", 2, 3, 0,
|
||||
ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
|
||||
ldap_back_cf_gen, NULL, NULL, NULL },
|
||||
|
|
@ -324,6 +333,7 @@ static ConfigOCs ldapocs[] = {
|
|||
"$ olcDbCancel "
|
||||
"$ olcDbQuarantine "
|
||||
"$ olcDbUseTemporaryConn "
|
||||
"$ olcDbConnectionPoolMax "
|
||||
") )",
|
||||
Cft_Database, ldapcfg},
|
||||
{ NULL, 0, NULL }
|
||||
|
|
@ -1060,6 +1070,10 @@ ldap_back_cf_gen( ConfigArgs *c )
|
|||
c->value_int = LDAP_BACK_USE_TEMPORARIES( li );
|
||||
break;
|
||||
|
||||
case LDAP_BACK_CFG_CONNPOOLMAX:
|
||||
c->value_int = li->li_conn_priv_max;
|
||||
break;
|
||||
|
||||
case LDAP_BACK_CFG_CANCEL: {
|
||||
slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2;
|
||||
|
||||
|
|
@ -1190,6 +1204,10 @@ ldap_back_cf_gen( ConfigArgs *c )
|
|||
li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
|
||||
break;
|
||||
|
||||
case LDAP_BACK_CFG_CONNPOOLMAX:
|
||||
li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN;
|
||||
break;
|
||||
|
||||
case LDAP_BACK_CFG_QUARANTINE:
|
||||
if ( !LDAP_BACK_QUARANTINE( li ) ) {
|
||||
break;
|
||||
|
|
@ -1744,6 +1762,24 @@ done_url:;
|
|||
}
|
||||
break;
|
||||
|
||||
case LDAP_BACK_CFG_CONNPOOLMAX:
|
||||
if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
|
||||
|| c->value_int > LDAP_BACK_CONN_PRIV_MAX )
|
||||
{
|
||||
snprintf( c->msg, sizeof( c->msg ),
|
||||
"invalid max size " "of privileged "
|
||||
"connections pool \"%s\" "
|
||||
"in \"conn-pool-max <n> "
|
||||
"(must be between %d and %d)\"",
|
||||
c->argv[ 1 ],
|
||||
LDAP_BACK_CONN_PRIV_MIN,
|
||||
LDAP_BACK_CONN_PRIV_MAX );
|
||||
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
|
||||
return 1;
|
||||
}
|
||||
li->li_conn_priv_max = c->value_int;
|
||||
break;
|
||||
|
||||
case LDAP_BACK_CFG_CANCEL: {
|
||||
slap_mask_t mask;
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ ldap_back_db_init( Backend *be )
|
|||
{
|
||||
ldapinfo_t *li;
|
||||
int rc;
|
||||
unsigned i;
|
||||
|
||||
li = (ldapinfo_t *)ch_calloc( 1, sizeof( ldapinfo_t ) );
|
||||
if ( li == NULL ) {
|
||||
|
|
@ -146,6 +147,12 @@ ldap_back_db_init( Backend *be )
|
|||
|
||||
ldap_pvt_thread_mutex_init( &li->li_conninfo.lai_mutex );
|
||||
|
||||
for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
|
||||
li->li_conn_priv[ i ].lic_num = 0;
|
||||
LDAP_TAILQ_INIT( &li->li_conn_priv[ i ].lic_priv );
|
||||
}
|
||||
li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_DEFAULT;
|
||||
|
||||
be->be_private = li;
|
||||
SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_NOLASTMOD;
|
||||
|
||||
|
|
@ -244,6 +251,8 @@ ldap_back_conn_free( void *v_lc )
|
|||
if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
|
||||
ch_free( lc->lc_local_ndn.bv_val );
|
||||
}
|
||||
lc->lc_q.tqe_prev = NULL;
|
||||
lc->lc_q.tqe_next = NULL;
|
||||
ch_free( lc );
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +273,7 @@ ldap_back_db_destroy( Backend *be )
|
|||
{
|
||||
if ( be->be_private ) {
|
||||
ldapinfo_t *li = ( ldapinfo_t * )be->be_private;
|
||||
unsigned i;
|
||||
|
||||
(void)ldap_back_monitor_db_destroy( be );
|
||||
|
||||
|
|
@ -328,6 +338,14 @@ ldap_back_db_destroy( Backend *be )
|
|||
if ( li->li_conninfo.lai_tree ) {
|
||||
avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
|
||||
}
|
||||
for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
|
||||
while ( !LDAP_TAILQ_EMPTY( &li->li_conn_priv[ i ].lic_priv ) ) {
|
||||
ldapconn_t *lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ i ].lic_priv );
|
||||
|
||||
LDAP_TAILQ_REMOVE( &li->li_conn_priv[ i ].lic_priv, lc, lc_q );
|
||||
ldap_back_conn_free( lc );
|
||||
}
|
||||
}
|
||||
if ( LDAP_BACK_QUARANTINE( li ) ) {
|
||||
slap_retry_info_destroy( &li->li_quarantine );
|
||||
ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ extern BI_connection_destroy ldap_back_conn_destroy;
|
|||
|
||||
extern BI_entry_get_rw ldap_back_entry_get;
|
||||
|
||||
int ldap_back_freeconn( Operation *op, ldapconn_t *lc, int dolock );
|
||||
void ldap_back_release_conn_lock( Operation *op, SlapReply *rs, ldapconn_t **lcp, int dolock );
|
||||
#define ldap_back_release_conn(op, rs, lc) ldap_back_release_conn_lock((op), (rs), &(lc), 1)
|
||||
int ldap_back_dobind( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok );
|
||||
|
|
@ -83,7 +82,7 @@ ldap_back_quarantine(
|
|||
|
||||
#ifdef LDAP_BACK_PRINT_CONNTREE
|
||||
extern void
|
||||
ldap_back_print_conntree( Avlnode *root, char *msg );
|
||||
ldap_back_print_conntree( ldapinfo_t *li, char *msg );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
|
||||
extern void slap_retry_info_destroy( slap_retry_info_t *ri );
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ ldap_back_conn_destroy(
|
|||
|
||||
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, ">>> ldap_back_conn_destroy" );
|
||||
ldap_back_print_conntree( li, ">>> ldap_back_conn_destroy" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
while ( ( lc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)&lc_curr, ldap_back_conn_cmp ) ) != NULL )
|
||||
{
|
||||
|
|
@ -67,7 +67,7 @@ ldap_back_conn_destroy(
|
|||
ldap_back_conn_free( lc );
|
||||
}
|
||||
#if LDAP_BACK_PRINT_CONNTREE > 0
|
||||
ldap_back_print_conntree( li->li_conninfo.lai_tree, "<<< ldap_back_conn_destroy" );
|
||||
ldap_back_print_conntree( li, "<<< ldap_back_conn_destroy" );
|
||||
#endif /* LDAP_BACK_PRINT_CONNTREE */
|
||||
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
|
||||
|
||||
|
|
|
|||
|
|
@ -241,6 +241,8 @@ typedef struct metaconn_t {
|
|||
|
||||
struct metainfo_t *mc_info;
|
||||
|
||||
LDAP_TAILQ_ENTRY(metaconn_t) mc_q;
|
||||
|
||||
/* supersedes the connection stuff */
|
||||
metasingleconn_t mc_conns[ 1 ];
|
||||
/* NOTE: mc_conns must be last, because
|
||||
|
|
@ -346,7 +348,14 @@ typedef struct metainfo_t {
|
|||
|
||||
metadncache_t mi_cache;
|
||||
|
||||
/* cached connections;
|
||||
* special conns are in tailq rather than in tree */
|
||||
ldap_avl_info_t mi_conninfo;
|
||||
struct {
|
||||
int mic_num;
|
||||
LDAP_TAILQ_HEAD(mc_conn_priv_q, metaconn_t) mic_priv;
|
||||
} mi_conn_priv[ LDAP_BACK_PCONN_LAST ];
|
||||
int mi_conn_priv_max;
|
||||
|
||||
/* NOTE: quarantine uses the connection mutex */
|
||||
slap_retry_info_t mi_quarantine;
|
||||
|
|
@ -417,7 +426,7 @@ meta_back_conn_free(
|
|||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
extern void
|
||||
meta_back_print_conntree(
|
||||
Avlnode *root,
|
||||
metainfo_t *mi,
|
||||
char *msg );
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ retry_lock:;
|
|||
|
||||
assert( mc->mc_refcnt == 1 );
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_bind" );
|
||||
meta_back_print_conntree( mi, ">>> meta_back_bind" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
|
||||
meta_back_conndn_cmp );
|
||||
|
|
@ -252,12 +252,12 @@ 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 );
|
||||
LDAP_BACK_PCONN_SET( mc, op );
|
||||
}
|
||||
lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
|
||||
meta_back_conndn_cmp, meta_back_conndn_dup );
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_bind" );
|
||||
meta_back_print_conntree( mi, "<<< meta_back_bind" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
if ( lerr == -1 ) {
|
||||
|
|
|
|||
|
|
@ -877,6 +877,32 @@ meta_back_db_config(
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* privileged connections pool max size ? */
|
||||
} else if ( strcasecmp( argv[ 0 ], "conn-pool-max" ) == 0 ) {
|
||||
if ( argc != 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: \"conn-pool-max <n>\" takes 1 argument\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( mi->mi_ntargets > 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: \"conn-pool-max\" must appear before target definitions\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( lutil_atoi( &mi->mi_conn_priv_max, argv[1] )
|
||||
|| mi->mi_conn_priv_max < LDAP_BACK_CONN_PRIV_MIN
|
||||
|| mi->mi_conn_priv_max > LDAP_BACK_CONN_PRIV_MAX )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: \"conn-pool-max <n>\": invalid arg \"%s\".\n",
|
||||
fname, lineno, argv[ 1 ] );
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) {
|
||||
unsigned flag = 0;
|
||||
unsigned *flagsp = mi->mi_ntargets ?
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ meta_back_conndn_dup(
|
|||
*/
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
static void
|
||||
ravl_print( Avlnode *root, int depth )
|
||||
meta_back_ravl_print( Avlnode *root, int depth )
|
||||
{
|
||||
int i;
|
||||
metaconn_t *mc;
|
||||
|
|
@ -149,7 +149,7 @@ ravl_print( Avlnode *root, int depth )
|
|||
return;
|
||||
}
|
||||
|
||||
ravl_print( root->avl_right, depth + 1 );
|
||||
meta_back_ravl_print( root->avl_right, depth + 1 );
|
||||
|
||||
for ( i = 0; i < depth; i++ ) {
|
||||
fprintf( stderr, "-" );
|
||||
|
|
@ -163,19 +163,49 @@ ravl_print( Avlnode *root, int depth )
|
|||
avl_bf2str( root->avl_bf ), mc->mc_refcnt,
|
||||
LDAP_BACK_CONN_TAINTED( mc ) ? " tainted" : "" );
|
||||
|
||||
ravl_print( root->avl_left, depth + 1 );
|
||||
meta_back_ravl_print( root->avl_left, depth + 1 );
|
||||
}
|
||||
|
||||
/* NOTE: duplicate from back-ldap/bind.c */
|
||||
static char* priv2str[] = {
|
||||
"privileged",
|
||||
"privileged/TLS",
|
||||
"anonymous",
|
||||
"anonymous/TLS",
|
||||
"bind",
|
||||
"bind/TLS",
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
meta_back_print_conntree( Avlnode *root, char *msg )
|
||||
meta_back_print_conntree( metainfo_t *mi, char *msg )
|
||||
{
|
||||
int c;
|
||||
|
||||
fprintf( stderr, "========> %s\n", msg );
|
||||
|
||||
if ( root == 0 ) {
|
||||
for ( c = LDAP_BACK_PCONN_FIRST; c < LDAP_BACK_PCONN_LAST; c++ ) {
|
||||
int i = 0;
|
||||
metaconn_t *mc;
|
||||
|
||||
fprintf( stderr, " %s[%d]\n", priv2str[ c ], mi->mi_conn_priv[ c ].mic_num );
|
||||
|
||||
LDAP_TAILQ_FOREACH( mc, &mi->mi_conn_priv[ c ].mic_priv, mc_q )
|
||||
{
|
||||
fprintf( stderr, " [%d] mc=%p local=\"%s\" conn=%p refcnt=%d flags=0x%08x\n",
|
||||
i,
|
||||
(void *)mc,
|
||||
mc->mc_local_ndn.bv_val ? mc->mc_local_ndn.bv_val : "",
|
||||
(void *)mc->mc_conn, mc->mc_refcnt, mc->msc_mscflags );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mi->mi_conninfo.lai_tree == NULL ) {
|
||||
fprintf( stderr, "\t(empty)\n" );
|
||||
|
||||
} else {
|
||||
ravl_print( root, 0 );
|
||||
meta_back_ravl_print( mi->mi_conninfo.lai_tree, 0 );
|
||||
}
|
||||
|
||||
fprintf( stderr, "<======== %s\n", msg );
|
||||
|
|
@ -708,13 +738,33 @@ meta_back_retry(
|
|||
|
||||
} else {
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_retry" );
|
||||
meta_back_print_conntree( mi, ">>> meta_back_retry" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
|
||||
/* FIXME: could be done better, reworking meta_back_release_conn_lock() */
|
||||
(void)avl_delete( &mi->mi_conninfo.lai_tree,
|
||||
( caddr_t )mc, meta_back_conndnmc_cmp );
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
|
||||
if ( mc->mc_q.tqe_prev != NULL ) {
|
||||
assert( LDAP_BACK_CONN_CACHED( mc ) );
|
||||
assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
|
||||
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
|
||||
mc, mc_q );
|
||||
mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
|
||||
mc->mc_q.tqe_prev = NULL;
|
||||
mc->mc_q.tqe_next = NULL;
|
||||
|
||||
} else {
|
||||
assert( !LDAP_BACK_CONN_CACHED( mc ) );
|
||||
}
|
||||
|
||||
} else {
|
||||
/* FIXME: check if in tree, for consistency? */
|
||||
(void)avl_delete( &mi->mi_conninfo.lai_tree,
|
||||
( caddr_t )mc, meta_back_conndnmc_cmp );
|
||||
}
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( mc );
|
||||
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_retry" );
|
||||
meta_back_print_conntree( mi, "<<< meta_back_retry" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
}
|
||||
}
|
||||
|
|
@ -970,7 +1020,7 @@ meta_back_getconn(
|
|||
if ( META_BACK_PROXYAUTHZ_ALWAYS( mi ) || op->o_do_not_cache || be_isroot( op ) ) {
|
||||
mc_curr.mc_local_ndn = op->o_bd->be_rootndn;
|
||||
LDAP_BACK_CONN_ISPRIV_SET( &mc_curr );
|
||||
mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
|
||||
LDAP_BACK_PCONN_ROOTDN_SET( &mc_curr, op );
|
||||
|
||||
} else {
|
||||
mc_curr.mc_local_ndn = op->o_ndn;
|
||||
|
|
@ -980,7 +1030,8 @@ meta_back_getconn(
|
|||
mc_curr.mc_conn = op->o_conn;
|
||||
|
||||
} else {
|
||||
mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
|
||||
LDAP_BACK_CONN_ISANON_SET( &mc_curr );
|
||||
LDAP_BACK_PCONN_ANON_SET( &mc_curr, op );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -989,8 +1040,41 @@ meta_back_getconn(
|
|||
/* Searches for a metaconn in the avl tree */
|
||||
retry_lock:;
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
|
||||
mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree,
|
||||
(caddr_t)&mc_curr, meta_back_conndn_cmp );
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( &mc_curr ) ) {
|
||||
/* lookup a conn that's not binding */
|
||||
LDAP_TAILQ_FOREACH( mc,
|
||||
&mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_priv,
|
||||
mc_q )
|
||||
{
|
||||
if ( !LDAP_BACK_CONN_BINDING( mc ) && mc->mc_refcnt == 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mc != NULL ) {
|
||||
if ( mc != LDAP_TAILQ_LAST( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
|
||||
metaconn_t, mc_q ) )
|
||||
{
|
||||
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
|
||||
mc, mc_q );
|
||||
mc->mc_q.tqe_prev = NULL;
|
||||
mc->mc_q.tqe_next = NULL;
|
||||
LDAP_TAILQ_INSERT_TAIL( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
|
||||
mc, mc_q );
|
||||
}
|
||||
|
||||
} else if ( !LDAP_BACK_USE_TEMPORARIES( mi )
|
||||
&& mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_num == mi->mi_conn_priv_max )
|
||||
{
|
||||
mc = LDAP_TAILQ_FIRST( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( &mc_curr ) ].mic_priv );
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree,
|
||||
(caddr_t)&mc_curr, meta_back_conndn_cmp );
|
||||
}
|
||||
|
||||
if ( mc ) {
|
||||
/* catch taint errors */
|
||||
assert( !LDAP_BACK_CONN_TAINTED( mc ) );
|
||||
|
|
@ -1013,17 +1097,36 @@ retry_lock:;
|
|||
|| ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
|
||||
{
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree,
|
||||
meta_back_print_conntree( mi,
|
||||
">>> meta_back_getconn(expired)" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
|
||||
/* don't let anyone else use this expired connection */
|
||||
(void)avl_delete( &mi->mi_conninfo.lai_tree,
|
||||
(caddr_t)mc, meta_back_conndnmc_cmp );
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
|
||||
if ( mc->mc_q.tqe_prev != NULL ) {
|
||||
assert( LDAP_BACK_CONN_CACHED( mc ) );
|
||||
assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
|
||||
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv,
|
||||
mc, mc_q );
|
||||
mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
|
||||
mc->mc_q.tqe_prev = NULL;
|
||||
mc->mc_q.tqe_next = NULL;
|
||||
|
||||
} else {
|
||||
assert( !LDAP_BACK_CONN_CACHED( mc ) );
|
||||
}
|
||||
|
||||
} else {
|
||||
(void)avl_delete( &mi->mi_conninfo.lai_tree,
|
||||
(caddr_t)mc, meta_back_conndnmc_cmp );
|
||||
}
|
||||
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree,
|
||||
meta_back_print_conntree( mi,
|
||||
"<<< meta_back_getconn(expired)" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
LDAP_BACK_CONN_TAINTED_SET( mc );
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( mc );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "%s meta_back_getconn: mc=%p conn=%ld expired (tainted).\n",
|
||||
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
|
||||
|
|
@ -1092,6 +1195,9 @@ retry_lock:;
|
|||
}
|
||||
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( mc );
|
||||
|
||||
} else if ( LDAP_BACK_CONN_ISANON( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISANON_SET( mc );
|
||||
}
|
||||
|
||||
} else if ( 0 ) {
|
||||
|
|
@ -1261,6 +1367,9 @@ retry_lock2:;
|
|||
}
|
||||
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( mc );
|
||||
|
||||
} else if ( LDAP_BACK_CONN_ISANON( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISANON_SET( mc );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1319,6 +1428,9 @@ retry_lock2:;
|
|||
new_conn = 1;
|
||||
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISPRIV_SET( mc );
|
||||
|
||||
} else if ( LDAP_BACK_CONN_ISANON( &mc_curr ) ) {
|
||||
LDAP_BACK_CONN_ISANON_SET( mc );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1452,51 +1564,71 @@ done:;
|
|||
*/
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_getconn" );
|
||||
meta_back_print_conntree( mi, ">>> meta_back_getconn" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
err = avl_insert( &mi->mi_conninfo.lai_tree, ( caddr_t )mc,
|
||||
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
|
||||
if ( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num < mi->mi_conn_priv_max ) {
|
||||
LDAP_TAILQ_INSERT_TAIL( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv, mc, mc_q );
|
||||
mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num++;
|
||||
LDAP_BACK_CONN_CACHED_SET( mc );
|
||||
|
||||
} else {
|
||||
LDAP_BACK_CONN_TAINTED_SET( mc );
|
||||
}
|
||||
rs->sr_err = 0;
|
||||
|
||||
} else {
|
||||
err = avl_insert( &mi->mi_conninfo.lai_tree, ( caddr_t )mc,
|
||||
meta_back_conndn_cmp, meta_back_conndn_dup );
|
||||
LDAP_BACK_CONN_CACHED_SET( mc );
|
||||
}
|
||||
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_getconn" );
|
||||
meta_back_print_conntree( mi, ">>> meta_back_getconn" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
|
||||
/*
|
||||
* Err could be -1 in case a duplicate metaconn is inserted
|
||||
*/
|
||||
switch ( err ) {
|
||||
case 0:
|
||||
break;
|
||||
if ( !LDAP_BACK_PCONN_ISPRIV( mc ) ) {
|
||||
/*
|
||||
* Err could be -1 in case a duplicate metaconn is inserted
|
||||
*/
|
||||
switch ( err ) {
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case -1:
|
||||
/* duplicate: free and try to get the newly created one */
|
||||
if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
|
||||
case -1:
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( mc );
|
||||
/* duplicate: free and try to get the newly created one */
|
||||
if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
|
||||
mc->mc_refcnt = 0;
|
||||
meta_back_conn_free( mc );
|
||||
|
||||
new_conn = 0;
|
||||
goto retry_lock;
|
||||
}
|
||||
|
||||
LDAP_BACK_CONN_TAINTED_SET( mc );
|
||||
break;
|
||||
|
||||
default:
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( mc );
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
|
||||
op->o_log_prefix, ncandidates,
|
||||
LDAP_BACK_PCONN_ID( mc ) );
|
||||
|
||||
mc->mc_refcnt = 0;
|
||||
meta_back_conn_free( mc );
|
||||
|
||||
new_conn = 0;
|
||||
goto retry_lock;
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "proxy bind collision";
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_text = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LDAP_BACK_CONN_TAINTED_SET( mc );
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
|
||||
op->o_log_prefix, ncandidates,
|
||||
LDAP_BACK_PCONN_ID( mc ) );
|
||||
|
||||
mc->mc_refcnt = 0;
|
||||
meta_back_conn_free( mc );
|
||||
|
||||
rs->sr_err = LDAP_OTHER;
|
||||
rs->sr_text = "proxy bind collision";
|
||||
if ( sendok & LDAP_BACK_SENDERR ) {
|
||||
send_ldap_result( op, rs );
|
||||
rs->sr_text = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
|
|
@ -1535,28 +1667,46 @@ meta_back_release_conn_lock(
|
|||
* that are not privileged would live forever and pollute
|
||||
* the connection space (and eat up resources). Maybe this
|
||||
* should be configurable... */
|
||||
if ( LDAP_BACK_CONN_TAINTED( mc ) ||
|
||||
( !LDAP_BACK_CONN_ISPRIV( mc ) && LDAP_BACK_PCONN_ISPRIV( mc ) && mc->mc_refcnt == 0 ) )
|
||||
{
|
||||
metaconn_t *tmpmc;
|
||||
|
||||
if ( LDAP_BACK_CONN_TAINTED( mc ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "%s meta_back_release_conn: mc=%p conn=%ld tainted.\n",
|
||||
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_release_conn" );
|
||||
meta_back_print_conntree( mi, ">>> meta_back_release_conn" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
tmpmc = avl_delete( &mi->mi_conninfo.lai_tree,
|
||||
( caddr_t )mc, meta_back_conndnmc_cmp );
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_release_conn" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
if ( tmpmc == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_release_conn: unable to find mc=%p\n",
|
||||
op->o_log_prefix, (void *)mc, 0 );
|
||||
|
||||
if ( LDAP_BACK_PCONN_ISPRIV( mc ) ) {
|
||||
if ( mc->mc_q.tqe_prev != NULL ) {
|
||||
assert( LDAP_BACK_CONN_CACHED( mc ) );
|
||||
assert( mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num > 0 );
|
||||
mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_num--;
|
||||
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ LDAP_BACK_CONN2PRIV( mc ) ].mic_priv, mc, mc_q );
|
||||
|
||||
} else {
|
||||
assert( !LDAP_BACK_CONN_CACHED( mc ) );
|
||||
}
|
||||
mc->mc_q.tqe_prev = NULL;
|
||||
mc->mc_q.tqe_next = NULL;
|
||||
|
||||
} else {
|
||||
assert( tmpmc == mc );
|
||||
metaconn_t *tmpmc;
|
||||
|
||||
tmpmc = avl_delete( &mi->mi_conninfo.lai_tree,
|
||||
( caddr_t )mc, meta_back_conndnmc_cmp );
|
||||
|
||||
if ( tmpmc == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_release_conn: unable to find mc=%p\n",
|
||||
op->o_log_prefix, (void *)mc, 0 );
|
||||
} else {
|
||||
assert( tmpmc == mc );
|
||||
}
|
||||
}
|
||||
|
||||
LDAP_BACK_CONN_CACHED_CLEAR( mc );
|
||||
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi, "<<< meta_back_release_conn" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
|
||||
if ( mc->mc_refcnt == 0 ) {
|
||||
meta_back_conn_free( mc );
|
||||
mc = NULL;
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ meta_back_db_init(
|
|||
Backend *be )
|
||||
{
|
||||
metainfo_t *mi;
|
||||
int i;
|
||||
|
||||
mi = ch_calloc( 1, sizeof( metainfo_t ) );
|
||||
if ( mi == NULL ) {
|
||||
|
|
@ -113,6 +114,12 @@ meta_back_db_init(
|
|||
/* safe default */
|
||||
mi->mi_nretries = META_RETRY_DEFAULT;
|
||||
mi->mi_version = LDAP_VERSION3;
|
||||
|
||||
for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
|
||||
mi->mi_conn_priv[ i ].mic_num = 0;
|
||||
LDAP_TAILQ_INIT( &mi->mi_conn_priv[ i ].mic_priv );
|
||||
}
|
||||
mi->mi_conn_priv_max = LDAP_BACK_CONN_PRIV_DEFAULT;
|
||||
|
||||
be->be_private = mi;
|
||||
|
||||
|
|
@ -298,6 +305,14 @@ meta_back_db_destroy(
|
|||
if ( mi->mi_conninfo.lai_tree ) {
|
||||
avl_free( mi->mi_conninfo.lai_tree, meta_back_conn_free );
|
||||
}
|
||||
for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
|
||||
while ( !LDAP_TAILQ_EMPTY( &mi->mi_conn_priv[ i ].mic_priv ) ) {
|
||||
metaconn_t *mc = LDAP_TAILQ_FIRST( &mi->mi_conn_priv[ i ].mic_priv );
|
||||
|
||||
LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ i ].mic_priv, mc, mc_q );
|
||||
meta_back_conn_free( mc );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy the per-target stuff (assuming there's at
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ meta_back_conn_destroy(
|
|||
|
||||
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_conn_destroy" );
|
||||
meta_back_print_conntree( mi, ">>> meta_back_conn_destroy" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
while ( ( mc = avl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )&mc_curr, meta_back_conn_cmp ) ) != NULL )
|
||||
{
|
||||
|
|
@ -65,7 +65,7 @@ meta_back_conn_destroy(
|
|||
meta_back_conn_free( mc );
|
||||
}
|
||||
#if META_BACK_PRINT_CONNTREE > 0
|
||||
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_conn_destroy" );
|
||||
meta_back_print_conntree( mi, "<<< meta_back_conn_destroy" );
|
||||
#endif /* META_BACK_PRINT_CONNTREE */
|
||||
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue