Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15-SP4
openldap2.23628
0226-ITS-9197-back-ldap-added-task-that-prunes-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0226-ITS-9197-back-ldap-added-task-that-prunes-expired-co.patch of Package openldap2.23628
From 8ee47ce0fdb1e6796fdf46c3eb7bd453933c3a6b Mon Sep 17 00:00:00 2001 From: Tero Saarni <tero.saarni@gmail.com> Date: Wed, 24 Feb 2021 22:07:48 +0000 Subject: [PATCH 226/230] ITS#9197 back-ldap: added task that prunes expired connections --- servers/slapd/back-ldap/back-ldap.h | 3 +- servers/slapd/back-ldap/bind.c | 206 +++++++++++++++--- servers/slapd/back-ldap/chain.c | 141 +++++------- servers/slapd/back-ldap/config.c | 2 +- servers/slapd/back-ldap/distproc.c | 114 +++++----- servers/slapd/back-ldap/init.c | 16 +- servers/slapd/back-ldap/monitor.c | 10 +- servers/slapd/back-ldap/unbind.c | 2 +- servers/slapd/back-meta/bind.c | 4 +- servers/slapd/back-meta/conn.c | 14 +- servers/slapd/back-meta/init.c | 2 +- servers/slapd/back-meta/unbind.c | 2 +- tests/data/slapd-proxytimeout.conf | 71 ++++++ tests/scripts/conf.sh | 1 + tests/scripts/defines.sh | 1 + tests/scripts/test079-proxy-timeout | 324 ++++++++++++++++++++++++++++ 16 files changed, 716 insertions(+), 197 deletions(-) create mode 100644 tests/data/slapd-proxytimeout.conf create mode 100644 tests/scripts/test079-proxy-timeout diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h index c4639e4f4..1f5054cf3 100644 --- a/servers/slapd/back-ldap/back-ldap.h +++ b/servers/slapd/back-ldap/back-ldap.h @@ -180,7 +180,7 @@ typedef struct ldapconn_t { typedef struct ldap_avl_info_t { ldap_pvt_thread_mutex_t lai_mutex; - Avlnode *lai_tree; + TAvlnode *lai_tree; } ldap_avl_info_t; typedef struct slap_retry_info_t { @@ -414,6 +414,7 @@ typedef struct ldapinfo_t { ldap_pvt_thread_mutex_t li_counter_mutex; ldap_pvt_mp_t li_ops_completed[SLAP_OP_LAST]; + struct re_s* li_conn_expire_task; } ldapinfo_t; #define LDAP_ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE) diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c index 998b2c796..1f9cbf185 100644 --- a/servers/slapd/back-ldap/bind.c +++ b/servers/slapd/back-ldap/bind.c @@ -34,6 +34,7 @@ #include "back-ldap.h" #include "lutil.h" #include "lutil_ldap.h" +#include "ldap_rq.h" #define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ "2.16.840.1.113730.3.4.12" @@ -60,7 +61,7 @@ static const struct { }; static void -ldap_back_conn_print( ldapconn_t *lc, const char *avlstr ) +ldap_back_conn_print( ldapconn_t *lc ) { char buf[ SLAP_TEXT_BUFLEN ]; char fbuf[ sizeof("BAPTIENSC") ]; @@ -77,31 +78,10 @@ ldap_back_conn_print( ldapconn_t *lc, const char *avlstr ) } fbuf[i] = '\0'; - fprintf( stderr, "lc=%p %s %s flags=0x%08x (%s)\n", - (void *)lc, buf, avlstr, lc->lc_lcflags, fbuf ); + fprintf( stderr, "lc=%p %s flags=0x%08x (%s)\n", + (void *)lc, buf, lc->lc_lcflags, fbuf ); } -static void -ldap_back_ravl_print( Avlnode *root, int depth ) -{ - int i; - ldapconn_t *lc; - - if ( root == 0 ) { - return; - } - - ldap_back_ravl_print( root->avl_right, depth+1 ); - - for ( i = 0; i < depth; i++ ) { - fprintf( stderr, "-" ); - } - - lc = root->avl_data; - ldap_back_conn_print( lc, avl_bf2str( root->avl_bf ) ); - - ldap_back_ravl_print( root->avl_left, depth + 1 ); -} static char* priv2str[] = { "privileged", @@ -129,7 +109,7 @@ ldap_back_print_conntree( ldapinfo_t *li, char *msg ) LDAP_TAILQ_FOREACH( lc, &li->li_conn_priv[ c ].lic_priv, lc_q ) { fprintf( stderr, " [%d] ", i ); - ldap_back_conn_print( lc, "" ); + ldap_back_conn_print( lc ); i++; } } @@ -138,7 +118,11 @@ ldap_back_print_conntree( ldapinfo_t *li, char *msg ) fprintf( stderr, "\t(empty)\n" ); } else { - ldap_back_ravl_print( li->li_conninfo.lai_tree, 0 ); + TAvlnode *edge = tavl_end( li->li_conninfo.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + ldap_back_conn_print( (ldapconn_t *)edge->avl_data ); + edge = tavl_next( edge, TAVL_DIR_RIGHT ); + } } fprintf( stderr, "<======== %s\n", msg ); @@ -167,6 +151,12 @@ ldap_back_prepare_conn( ldapconn_t *lc, Operation *op, SlapReply *rs, static int ldap_back_conndnlc_cmp( const void *c1, const void *c2 ); +static void +ldap_back_conn_prune( ldapinfo_t *li ); + +static void +ldap_back_schedule_conn_expiry( ldapinfo_t *li, ldapconn_t *lc ); + ldapconn_t * ldap_back_conn_delete( ldapinfo_t *li, ldapconn_t *lc ) { @@ -189,7 +179,7 @@ ldap_back_conn_delete( ldapinfo_t *li, ldapconn_t *lc ) if ( LDAP_BACK_CONN_CACHED( lc ) ) { assert( !LDAP_BACK_CONN_TAINTED( lc ) ); - tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, + tmplc = tavl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conndnlc_cmp ); assert( tmplc == lc ); LDAP_BACK_CONN_CACHED_CLEAR( lc ); @@ -343,7 +333,7 @@ retry_lock:; /* delete all cached connections with the current connection */ if ( LDAP_BACK_SINGLECONN( li ) ) { - while ( ( tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conn_cmp ) ) != NULL ) + while ( ( tmplc = tavl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conn_cmp ) ) != NULL ) { assert( !LDAP_BACK_PCONN_ISPRIV( lc ) ); Debug( LDAP_DEBUG_TRACE, @@ -371,7 +361,7 @@ retry_lock:; if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) { LDAP_BACK_PCONN_ROOTDN_SET( lc, op ); } - lerr = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc, + lerr = tavl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conndn_cmp, ldap_back_conndn_dup ); } @@ -938,7 +928,7 @@ retry_lock: } else { /* Searches for a ldapconn in the avl tree */ - lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, + lc = (ldapconn_t *)tavl_find( li->li_conninfo.lai_tree, (caddr_t)&lc_curr, ldap_back_conndn_cmp ); } @@ -1084,7 +1074,7 @@ retry_lock: rs->sr_err = 0; } else { - rs->sr_err = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc, + rs->sr_err = tavl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conndn_cmp, ldap_back_conndn_dup ); LDAP_BACK_CONN_CACHED_SET( lc ); } @@ -1137,6 +1127,7 @@ retry_lock: return NULL; } } + ldap_back_schedule_conn_expiry( li, lc ); } else { int expiring = 0; @@ -3066,3 +3057,156 @@ ldap_back_connid2str( const ldapconn_base_t *lc, char *buf, ber_len_t buflen ) return len; } + +void * +ldap_back_conn_expire_fn( void *ctx, void *arg ) +{ + struct re_s *rtask = arg; + ldapinfo_t *li = (ldapinfo_t *)rtask->arg; + ldap_back_conn_prune( li ); + + return NULL; +} + +/* Pick which expires first: connection TTL or idle timeout */ +static time_t +ldap_back_conn_expire_time( ldapinfo_t *li, ldapconn_t *lc) { + if ( li->li_conn_ttl != 0 && li->li_idle_timeout != 0 ) { + return ( lc->lc_create_time + li->li_conn_ttl ) < ( lc->lc_time + li->li_idle_timeout ) ? + ( lc->lc_create_time + li->li_conn_ttl ) : ( lc->lc_time + li->li_idle_timeout ); + } else if ( li->li_conn_ttl != 0 ) { + return lc->lc_create_time + li->li_conn_ttl; + } else if ( li->li_idle_timeout != 0 ) { + return lc->lc_time + li->li_idle_timeout; + } + return -1; +} + +static void +ldap_back_conn_prune( ldapinfo_t *li ) +{ + time_t now = slap_get_time(); + time_t next_timeout = -1; /* -1 means uninitialized */ + TAvlnode *edge; + int c; + + /* + * Iterate though connections and close those that are pass the expiry time. + * Also calculate the time for next connection to to expire. + */ + ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); + + for ( c = LDAP_BACK_PCONN_FIRST; c < LDAP_BACK_PCONN_LAST; c++ ) { + ldapconn_t *lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ c ].lic_priv ); + + while ( lc ) { + ldapconn_t *next = LDAP_TAILQ_NEXT( lc, lc_q ); + time_t conn_expires = ldap_back_conn_expire_time( li, lc ); + + if ( now >= conn_expires ) { + if ( lc->lc_refcnt == 0 ) { + Debug( LDAP_DEBUG_TRACE, + "ldap_back_conn_prune: closing expired connection lc=%p\n", + lc, 0, 0 ); + ldap_back_freeconn( li, lc, 0 ); + } else { + Debug( LDAP_DEBUG_TRACE, + "ldap_back_conn_prune: tainting expired connection lc=%p\n", + lc, 0, 0 ); + LDAP_BACK_CONN_TAINTED_SET( lc ); + } + } else if ( next_timeout == -1 || conn_expires < next_timeout ) { + /* next_timeout was not yet initialized or current connection expires sooner */ + next_timeout = conn_expires; + } + + lc = next; + } + } + + edge = tavl_end( li->li_conninfo.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapconn_t *lc = (ldapconn_t *)edge->avl_data; + time_t conn_expires = ldap_back_conn_expire_time( li, lc ); + + if ( now >= conn_expires ) { + if ( lc->lc_refcnt == 0 ) { + Debug( LDAP_DEBUG_TRACE, + "ldap_back_conn_prune: closing expired connection lc=%p\n", + lc, 0, 0 ); + ldap_back_freeconn( li, lc, 0 ); + } else { + Debug( LDAP_DEBUG_TRACE, + "ldap_back_conn_prune: tainting expired connection lc=%p\n", + lc, 0, 0 ); + LDAP_BACK_CONN_TAINTED_SET( lc ); + } + } else if ( next_timeout == -1 || conn_expires < next_timeout ) { + next_timeout = conn_expires; + } + + edge = next; + } + + ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); + + /* Reschedule for next timeout or cancel the task */ + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + if ( next_timeout > 0 ) { + if ( ldap_pvt_runqueue_isrunning( &slapd_rq, li->li_conn_expire_task ) ) { + ldap_pvt_runqueue_stoptask( &slapd_rq, li->li_conn_expire_task ); + } + li->li_conn_expire_task->interval.tv_sec = next_timeout - now; + ldap_pvt_runqueue_resched( &slapd_rq, li->li_conn_expire_task, 0 ); + + /* + * The thread that handles runqueue might have already processed all tasks + * before we insertered new task or rescheduled the existing task with new + * timeout period. Wake it up to ensure that the task will be picked up. + */ + slap_wake_listener(); + Debug( LDAP_DEBUG_TRACE, + "ldap_back_conn_prune: scheduled connection expiry timer to %ld sec\n", + li->li_conn_expire_task->interval.tv_sec, 0, 0 ); + } else if ( next_timeout == -1 && li->li_conn_expire_task != NULL ) { + if ( ldap_pvt_runqueue_isrunning( &slapd_rq, li->li_conn_expire_task ) ) { + ldap_pvt_runqueue_stoptask( &slapd_rq, li->li_conn_expire_task ); + } + ldap_pvt_runqueue_remove( &slapd_rq, li->li_conn_expire_task ); + li->li_conn_expire_task = NULL; + } + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + + return; +} + +static void +ldap_back_schedule_conn_expiry( ldapinfo_t *li, ldapconn_t *lc ) { + /* Do nothing if timeouts are not set. */ + if ( li->li_conn_ttl == 0 && li->li_idle_timeout == 0 ) { + return; + } + + /* + * If connection expire task is not running, create it and schedule for + * timeout of this connection. + * + * If the task is already running, this connection cannot be next one + * to expire and therefore timeout does not need to be re-calculated. + */ + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + if ( li->li_conn_expire_task == NULL ) { + li->li_conn_expire_task = ldap_pvt_runqueue_insert( &slapd_rq, + ldap_back_conn_expire_time( li, lc ) - slap_get_time(), + ldap_back_conn_expire_fn, li, "ldap_back_conn_expire_fn", + "ldap_back_conn_expire_timer" ); + slap_wake_listener(); + Debug( LDAP_DEBUG_TRACE, + "ldap_back_conn_prune: scheduled connection expiry timer to %ld sec\n", + li->li_conn_expire_task->interval.tv_sec, 0, 0 ); + } + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + + return; +} \ No newline at end of file diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c index eeceb4c66..643fce9cf 100644 --- a/servers/slapd/back-ldap/chain.c +++ b/servers/slapd/back-ldap/chain.c @@ -556,7 +556,7 @@ Document: RFC 4511 /* Searches for a ldapinfo in the avl tree */ ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); - lip = (ldapinfo_t *)avl_find( lc->lc_lai.lai_tree, + lip = (ldapinfo_t *)tavl_find( lc->lc_lai.lai_tree, (caddr_t)&li, ldap_chain_uri_cmp ); ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex ); @@ -588,7 +588,7 @@ Document: RFC 4511 if ( LDAP_CHAIN_CACHE_URI( lc ) ) { ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); - if ( avl_insert( &lc->lc_lai.lai_tree, + if ( tavl_insert( &lc->lc_lai.lai_tree, (caddr_t)lip, ldap_chain_uri_cmp, ldap_chain_uri_dup ) ) { /* someone just inserted another; @@ -828,7 +828,7 @@ ldap_chain_search( /* Searches for a ldapinfo in the avl tree */ ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); - lip = (ldapinfo_t *)avl_find( lc->lc_lai.lai_tree, + lip = (ldapinfo_t *)tavl_find( lc->lc_lai.lai_tree, (caddr_t)&li, ldap_chain_uri_cmp ); ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex ); @@ -861,7 +861,7 @@ ldap_chain_search( if ( LDAP_CHAIN_CACHE_URI( lc ) ) { ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); - if ( avl_insert( &lc->lc_lai.lai_tree, + if ( tavl_insert( &lc->lc_lai.lai_tree, (caddr_t)lip, ldap_chain_uri_cmp, ldap_chain_uri_dup ) ) { /* someone just inserted another; @@ -1366,7 +1366,7 @@ fail: if ( at ) { li->li_uri = ch_strdup( at->a_vals[ 0 ].bv_val ); value_add_one( &li->li_bvuri, &at->a_vals[ 0 ] ); - if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)li, + if ( tavl_insert( &lc->lc_lai.lai_tree, (caddr_t)li, ldap_chain_uri_cmp, ldap_chain_uri_dup ) ) { Debug( LDAP_DEBUG_ANY, "slapd-chain: " @@ -1389,34 +1389,27 @@ done:; return rc; } -typedef struct ldap_chain_cfadd_apply_t { - Operation *op; - SlapReply *rs; - Entry *p; - ConfigArgs *ca; - int count; -} ldap_chain_cfadd_apply_t; - -static int -ldap_chain_cfadd_apply( void *datum, void *arg ) +static void +ldap_chain_cfadd_apply( + ldapinfo_t *li, + Operation *op, + SlapReply *rs, + Entry *p, + ConfigArgs *ca, + int count ) { - ldapinfo_t *li = (ldapinfo_t *)datum; - ldap_chain_cfadd_apply_t *lca = (ldap_chain_cfadd_apply_t *)arg; - struct berval bv; /* FIXME: should not hardcode "olcDatabase" here */ - bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ), - "olcDatabase={%d}%s", lca->count, lback->bi_type ); - bv.bv_val = lca->ca->cr_msg; + bv.bv_len = snprintf( ca->cr_msg, sizeof( ca->cr_msg ), + "olcDatabase={%d}%s", count, lback->bi_type ); + bv.bv_val = ca->cr_msg; - lca->ca->be->be_private = (void *)li; - config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca, + ca->be->be_private = (void *)li; + config_build_entry( op, rs, p->e_private, ca, &bv, lback->bi_cf_ocs, &chainocs[1] ); - lca->count++; - - return 0; + return; } static int @@ -1426,20 +1419,20 @@ chain_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ) slap_overinst *on = (slap_overinst *)pe->ce_bi; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; void *priv = (void *)ca->be->be_private; + TAvlnode *edge; + int count = 0; if ( lback->bi_cf_ocs ) { - ldap_chain_cfadd_apply_t lca = { 0 }; - - lca.op = op; - lca.rs = rs; - lca.p = p; - lca.ca = ca; - lca.count = 0; - (void)ldap_chain_cfadd_apply( (void *)lc->lc_common_li, (void *)&lca ); + ldap_chain_cfadd_apply( lc->lc_common_li, op, rs, p, ca, count++ ); - (void)avl_apply( lc->lc_lai.lai_tree, ldap_chain_cfadd_apply, - &lca, 1, AVL_INORDER ); + edge = tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; + ldap_chain_cfadd_apply( li, op, rs, p, ca, count++ ); + edge = next; + } ca->be->be_private = priv; } @@ -1457,7 +1450,7 @@ chain_lddel( CfEntryInfo *ce, Operation *op ) ldapinfo_t *li = (ldapinfo_t *) ce->ce_be->be_private; if ( li != lc->lc_common_li ) { - if (! avl_delete( &lc->lc_lai.lai_tree, li, ldap_chain_uri_cmp ) ) { + if (! tavl_delete( &lc->lc_lai.lai_tree, li, ldap_chain_uri_cmp ) ) { Debug( LDAP_DEBUG_ANY, "slapd-chain: avl_delete failed. " "\"%s\" not found.\n", li->li_uri, 0, 0 ); return -1; @@ -1866,7 +1859,7 @@ private_destroy:; goto private_destroy; } - if ( avl_insert( &lc->lc_lai.lai_tree, + if ( tavl_insert( &lc->lc_lai.lai_tree, (caddr_t)lc->lc_cfg_li, ldap_chain_uri_cmp, ldap_chain_uri_dup ) ) { @@ -1891,22 +1884,6 @@ enum db_which { db_last }; -typedef struct ldap_chain_db_apply_t { - BackendDB *be; - BI_db_func *func; -} ldap_chain_db_apply_t; - -static int -ldap_chain_db_apply( void *datum, void *arg ) -{ - ldapinfo_t *li = (ldapinfo_t *)datum; - ldap_chain_db_apply_t *lca = (ldap_chain_db_apply_t *)arg; - - lca->be->be_private = (void *)li; - - return lca->func( lca->be, NULL ); -} - static int ldap_chain_db_func( BackendDB *be, @@ -1934,14 +1911,17 @@ ldap_chain_db_func( } if ( lc->lc_lai.lai_tree != NULL ) { - ldap_chain_db_apply_t lca; - - lca.be = &db; - lca.func = func; - - rc = avl_apply( lc->lc_lai.lai_tree, - ldap_chain_db_apply, (void *)&lca, - 1, AVL_INORDER ) != AVL_NOMORE; + TAvlnode *edge = tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; + db.be_private = (void *)li; + rc = func( &db, NULL ); + if ( rc == 1 ) { + break; + } + edge = next; + } } } } @@ -2008,7 +1988,7 @@ ldap_chain_db_destroy( rc = ldap_chain_db_func( be, db_destroy ); if ( lc ) { - avl_free( lc->lc_lai.lai_tree, NULL ); + tavl_free( lc->lc_lai.lai_tree, NULL ); ldap_pvt_thread_mutex_destroy( &lc->lc_lai.lai_mutex ); ch_free( lc ); } @@ -2122,22 +2102,6 @@ ldap_chain_db_open_one( return lback->bi_db_open( be, NULL ); } -typedef struct ldap_chain_conn_apply_t { - BackendDB *be; - Connection *conn; -} ldap_chain_conn_apply_t; - -static int -ldap_chain_conn_apply( void *datum, void *arg ) -{ - ldapinfo_t *li = (ldapinfo_t *)datum; - ldap_chain_conn_apply_t *lca = (ldap_chain_conn_apply_t *)arg; - - lca->be->be_private = (void *)li; - - return lback->bi_connection_destroy( lca->be, lca->conn ); -} - static int ldap_chain_connection_destroy( BackendDB *be, @@ -2147,15 +2111,24 @@ ldap_chain_connection_destroy( slap_overinst *on = (slap_overinst *) be->bd_info; ldap_chain_t *lc = (ldap_chain_t *)on->on_bi.bi_private; void *private = be->be_private; - ldap_chain_conn_apply_t lca; + TAvlnode *edge; int rc; be->be_private = NULL; - lca.be = be; - lca.conn = conn; ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); - rc = avl_apply( lc->lc_lai.lai_tree, ldap_chain_conn_apply, - (void *)&lca, 1, AVL_INORDER ) != AVL_NOMORE; + edge = tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; + be->be_private = (void *)li; + rc = lback->bi_connection_destroy( be, conn ); + if ( rc == 1 ) { + break; + } + edge = next; + } + + ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex ); be->be_private = private; diff --git a/servers/slapd/back-ldap/config.c b/servers/slapd/back-ldap/config.c index 38da178d1..cff5cd289 100644 --- a/servers/slapd/back-ldap/config.c +++ b/servers/slapd/back-ldap/config.c @@ -1424,7 +1424,7 @@ ldap_back_cf_gen( ConfigArgs *c ) /* NOTE: don't worry about locking: if we got here, * other threads are suspended. */ if ( li->li_conninfo.lai_tree != NULL ) { - avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free ); + tavl_free( li->li_conninfo.lai_tree, ldap_back_conn_free ); li->li_conninfo.lai_tree = NULL; } diff --git a/servers/slapd/back-ldap/distproc.c b/servers/slapd/back-ldap/distproc.c index ed978728a..a8ea803b0 100644 --- a/servers/slapd/back-ldap/distproc.c +++ b/servers/slapd/back-ldap/distproc.c @@ -435,7 +435,7 @@ distproc_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) if ( lc->lc_common_li == NULL ) { lc->lc_common_li = li; - } else if ( avl_insert( &lc->lc_lai.lai_tree, (caddr_t)li, + } else if ( tavl_insert( &lc->lc_lai.lai_tree, (caddr_t)li, ldap_distproc_uri_cmp, ldap_distproc_uri_dup ) ) { Debug( LDAP_DEBUG_ANY, "slapd-distproc: " @@ -463,26 +463,27 @@ typedef struct ldap_distproc_cfadd_apply_t { int count; } ldap_distproc_cfadd_apply_t; -static int -ldap_distproc_cfadd_apply( void *datum, void *arg ) +static void +ldap_distproc_cfadd_apply( + ldapinfo_t *li, + Operation *op, + SlapReply *rs, + Entry *p, + ConfigArgs *ca, + int count ) { - ldapinfo_t *li = (ldapinfo_t *)datum; - ldap_distproc_cfadd_apply_t *lca = (ldap_distproc_cfadd_apply_t *)arg; - struct berval bv; /* FIXME: should not hardcode "olcDatabase" here */ - bv.bv_len = snprintf( lca->ca->cr_msg, sizeof( lca->ca->cr_msg ), - "olcDatabase={%d}%s", lca->count, lback->bi_type ); - bv.bv_val = lca->ca->cr_msg; + bv.bv_len = snprintf( ca->cr_msg, sizeof( ca->cr_msg ), + "olcDatabase={%d}%s", count, lback->bi_type ); + bv.bv_val = ca->cr_msg; - lca->ca->be->be_private = (void *)li; - config_build_entry( lca->op, lca->rs, lca->p->e_private, lca->ca, + ca->be->be_private = (void *)li; + config_build_entry( op, rs, p->e_private, ca, &bv, lback->bi_cf_ocs, &distproc_ocs[ 1 ] ); - lca->count++; - - return 0; + return; } static int @@ -492,6 +493,8 @@ distproc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ) slap_overinst *on = (slap_overinst *)pe->ce_bi; ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; void *priv = (void *)ca->be->be_private; + TAvlnode *edge; + int count = 0; if ( lback->bi_cf_ocs ) { ldap_distproc_cfadd_apply_t lca = { 0 }; @@ -502,10 +505,15 @@ distproc_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *ca ) lca.ca = ca; lca.count = 0; - (void)ldap_distproc_cfadd_apply( (void *)lc->lc_common_li, (void *)&lca ); + ldap_distproc_cfadd_apply( lc->lc_common_li, op, rs, p, ca, count++ ); - (void)avl_apply( lc->lc_lai.lai_tree, ldap_distproc_cfadd_apply, - &lca, 1, AVL_INORDER ); + edge = tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; + ldap_distproc_cfadd_apply( li, op, rs, p, ca, count++ ); + edge = next; + } ca->be->be_private = priv; } @@ -675,7 +683,7 @@ private_destroy:; goto private_destroy; } - if ( avl_insert( &lc->lc_lai.lai_tree, + if ( tavl_insert( &lc->lc_lai.lai_tree, (caddr_t)lc->lc_cfg_li, ldap_distproc_uri_cmp, ldap_distproc_uri_dup ) ) { @@ -700,22 +708,6 @@ enum db_which { db_last }; -typedef struct ldap_distproc_db_apply_t { - BackendDB *be; - BI_db_func *func; -} ldap_distproc_db_apply_t; - -static int -ldap_distproc_db_apply( void *datum, void *arg ) -{ - ldapinfo_t *li = (ldapinfo_t *)datum; - ldap_distproc_db_apply_t *lca = (ldap_distproc_db_apply_t *)arg; - - lca->be->be_private = (void *)li; - - return lca->func( lca->be, NULL ); -} - static int ldap_distproc_db_func( BackendDB *be, @@ -743,14 +735,17 @@ ldap_distproc_db_func( } if ( lc->lc_lai.lai_tree != NULL ) { - ldap_distproc_db_apply_t lca; - - lca.be = &db; - lca.func = func; - - rc = avl_apply( lc->lc_lai.lai_tree, - ldap_distproc_db_apply, (void *)&lca, - 1, AVL_INORDER ) != AVL_NOMORE; + TAvlnode *edge = tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; + be->be_private = (void *)li; + rc = func( &db, NULL ); + if ( rc == 1 ) { + break; + } + edge = next; + } } } } @@ -787,7 +782,7 @@ ldap_distproc_db_destroy( rc = ldap_distproc_db_func( be, db_destroy ); if ( lc ) { - avl_free( lc->lc_lai.lai_tree, NULL ); + tavl_free( lc->lc_lai.lai_tree, NULL ); ldap_pvt_thread_mutex_destroy( &lc->lc_lai.lai_mutex ); ch_free( lc ); } @@ -857,22 +852,6 @@ ldap_distproc_db_init_one( return 0; } -typedef struct ldap_distproc_conn_apply_t { - BackendDB *be; - Connection *conn; -} ldap_distproc_conn_apply_t; - -static int -ldap_distproc_conn_apply( void *datum, void *arg ) -{ - ldapinfo_t *li = (ldapinfo_t *)datum; - ldap_distproc_conn_apply_t *lca = (ldap_distproc_conn_apply_t *)arg; - - lca->be->be_private = (void *)li; - - return lback->bi_connection_destroy( lca->be, lca->conn ); -} - static int ldap_distproc_connection_destroy( BackendDB *be, @@ -882,15 +861,22 @@ ldap_distproc_connection_destroy( slap_overinst *on = (slap_overinst *) be->bd_info; ldap_distproc_t *lc = (ldap_distproc_t *)on->on_bi.bi_private; void *private = be->be_private; - ldap_distproc_conn_apply_t lca; int rc; + TAvlnode *edge; be->be_private = NULL; - lca.be = be; - lca.conn = conn; ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex ); - rc = avl_apply( lc->lc_lai.lai_tree, ldap_distproc_conn_apply, - (void *)&lca, 1, AVL_INORDER ) != AVL_NOMORE; + edge = tavl_end( lc->lc_lai.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapinfo_t *li = (ldapinfo_t *)edge->avl_data; + be->be_private = (void *)li; + rc = lback->bi_connection_destroy( be, conn ); + if ( rc == 1 ) { + break; + } + edge = next; + } ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex ); be->be_private = private; diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index f73344c99..8b801ff67 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -31,6 +31,7 @@ #include "slap.h" #include "config.h" #include "back-ldap.h" +#include "ldap_rq.h" static const ldap_extra_t ldap_extra = { ldap_back_proxy_authz_ctrl, @@ -185,6 +186,8 @@ ldap_back_db_init( Backend *be, ConfigReply *cr ) ldap_pvt_mp_init( li->li_ops_completed[ i ] ); } + li->li_conn_expire_task = NULL; + be->be_private = li; SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_NOLASTMOD; @@ -303,6 +306,16 @@ ldap_back_db_destroy( Backend *be, ConfigReply *cr ) (void)ldap_back_monitor_db_destroy( be ); + /* Stop and remove the task that prunes expired connections */ + if ( li->li_conn_expire_task != NULL ) { + ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); + if ( ldap_pvt_runqueue_isrunning( &slapd_rq, li->li_conn_expire_task ) ) { + ldap_pvt_runqueue_stoptask( &slapd_rq, li->li_conn_expire_task ); + } + ldap_pvt_runqueue_remove( &slapd_rq, li->li_conn_expire_task ); + ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); + } + ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); if ( li->li_uri != NULL ) { @@ -323,7 +336,7 @@ ldap_back_db_destroy( Backend *be, ConfigReply *cr ) li->li_idassert_authz = NULL; } if ( li->li_conninfo.lai_tree ) { - avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free ); + tavl_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 ) ) { @@ -359,4 +372,3 @@ ldap_back_db_destroy( Backend *be, ConfigReply *cr ) SLAP_BACKEND_INIT_MODULE( ldap ) #endif /* SLAPD_LDAP == SLAPD_MOD_DYNAMIC */ - diff --git a/servers/slapd/back-ldap/monitor.c b/servers/slapd/back-ldap/monitor.c index e12de8e4e..77f11ccb5 100644 --- a/servers/slapd/back-ldap/monitor.c +++ b/servers/slapd/back-ldap/monitor.c @@ -540,6 +540,7 @@ ldap_back_monitor_conn_create( struct ldap_back_monitor_conn_arg *arg; int conn_type; + TAvlnode *edge; assert( e_parent->e_private != NULL ); @@ -564,8 +565,13 @@ ldap_back_monitor_conn_create( } } - avl_apply( li->li_conninfo.lai_tree, (AVL_APPLY)ldap_back_monitor_conn_entry, - arg, -1, AVL_INORDER ); + edge = tavl_end( li->li_conninfo.lai_tree, TAVL_DIR_LEFT ); + while ( edge ) { + TAvlnode *next = tavl_next( edge, TAVL_DIR_RIGHT ); + ldapconn_t *lc = (ldapconn_t *)edge->avl_data; + ldap_back_monitor_conn_entry( lc, arg ); + edge = next; + } ch_free( arg ); diff --git a/servers/slapd/back-ldap/unbind.c b/servers/slapd/back-ldap/unbind.c index d8121f72d..6768baf16 100644 --- a/servers/slapd/back-ldap/unbind.c +++ b/servers/slapd/back-ldap/unbind.c @@ -51,7 +51,7 @@ ldap_back_conn_destroy( #if LDAP_BACK_PRINT_CONNTREE > 0 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 ) + while ( ( lc = tavl_delete( &li->li_conninfo.lai_tree, (caddr_t)&lc_curr, ldap_back_conn_cmp ) ) != NULL ) { assert( !LDAP_BACK_PCONN_ISPRIV( lc ) ); Debug( LDAP_DEBUG_TRACE, diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index f5d4df4e8..0e5e8853b 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -220,7 +220,7 @@ meta_back_bind( Operation *op, SlapReply *rs ) if ( LDAP_BACK_SINGLECONN( mi ) ) { metaconn_t *tmpmc; - while ( ( tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc, meta_back_conn_cmp ) ) != NULL ) + while ( ( tmpmc = tavl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc, meta_back_conn_cmp ) ) != NULL ) { assert( !LDAP_BACK_PCONN_ISPRIV( mc ) ); Debug( LDAP_DEBUG_TRACE, @@ -243,7 +243,7 @@ meta_back_bind( Operation *op, SlapReply *rs ) } ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn ); - lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc, + lerr = tavl_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, "<<< meta_back_bind" ); diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 8a781e573..239c86e5e 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -160,7 +160,7 @@ meta_back_print( metaconn_t *mc, char *avlstr ) } static void -meta_back_ravl_print( Avlnode *root, int depth ) +meta_back_ravl_print( TAvlnode *root, int depth ) { int i; @@ -849,7 +849,7 @@ meta_back_retry( } else { /* FIXME: check if in tree, for consistency? */ - (void)avl_delete( &mi->mi_conninfo.lai_tree, + (void)tavl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )mc, meta_back_conndnmc_cmp ); } LDAP_BACK_CONN_CACHED_CLEAR( mc ); @@ -1174,7 +1174,7 @@ retry_lock:; } else { - mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree, + mc = (metaconn_t *)tavl_find( mi->mi_conninfo.lai_tree, (caddr_t)&mc_curr, meta_back_conndn_cmp ); } @@ -1219,7 +1219,7 @@ retry_lock:; } } else { - (void)avl_delete( &mi->mi_conninfo.lai_tree, + (void)tavl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc, meta_back_conndnmc_cmp ); } @@ -1439,7 +1439,7 @@ retry_lock:; if ( !( sendok & LDAP_BACK_BINDING ) ) { retry_lock2:; ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); - mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree, + mc = (metaconn_t *)tavl_find( mi->mi_conninfo.lai_tree, (caddr_t)&mc_curr, meta_back_conndn_cmp ); if ( mc != NULL ) { /* catch taint errors */ @@ -1688,7 +1688,7 @@ done:; rs->sr_err = 0; } else if ( !( sendok & LDAP_BACK_BINDING ) ) { - err = avl_insert( &mi->mi_conninfo.lai_tree, ( caddr_t )mc, + err = tavl_insert( &mi->mi_conninfo.lai_tree, ( caddr_t )mc, meta_back_conndn_cmp, meta_back_conndn_dup ); LDAP_BACK_CONN_CACHED_SET( mc ); } @@ -1805,7 +1805,7 @@ meta_back_release_conn_lock( } else if ( LDAP_BACK_CONN_CACHED( mc ) ) { metaconn_t *tmpmc; - tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, + tmpmc = tavl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )mc, meta_back_conndnmc_cmp ); /* Overparanoid, but useful... */ diff --git a/servers/slapd/back-meta/init.c b/servers/slapd/back-meta/init.c index fefdba812..d98fe3625 100644 --- a/servers/slapd/back-meta/init.c +++ b/servers/slapd/back-meta/init.c @@ -407,7 +407,7 @@ meta_back_db_destroy( ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); if ( mi->mi_conninfo.lai_tree ) { - avl_free( mi->mi_conninfo.lai_tree, meta_back_conn_free ); + tavl_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 ) ) { diff --git a/servers/slapd/back-meta/unbind.c b/servers/slapd/back-meta/unbind.c index 2a866a6c7..8589262e6 100644 --- a/servers/slapd/back-meta/unbind.c +++ b/servers/slapd/back-meta/unbind.c @@ -54,7 +54,7 @@ meta_back_conn_destroy( #if META_BACK_PRINT_CONNTREE > 0 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 ) + while ( ( mc = tavl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )&mc_curr, meta_back_conn_cmp ) ) != NULL ) { assert( !LDAP_BACK_PCONN_ISPRIV( mc ) ); Debug( LDAP_DEBUG_TRACE, diff --git a/tests/data/slapd-proxytimeout.conf b/tests/data/slapd-proxytimeout.conf new file mode 100644 index 000000000..2fb7c6dfa --- /dev/null +++ b/tests/data/slapd-proxytimeout.conf @@ -0,0 +1,71 @@ +# provider slapd config -- for testing +# $OpenLDAP$ +## This work is part of OpenLDAP Software <http://www.openldap.org/>. +## +## Copyright 1998-2021 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## <http://www.OpenLDAP.org/license.html>. + +include @SCHEMADIR@/core.schema +include @SCHEMADIR@/cosine.schema +include @SCHEMADIR@/inetorgperson.schema +include @SCHEMADIR@/openldap.schema +include @SCHEMADIR@/nis.schema +pidfile @TESTDIR@/slapd.m.pid +argsfile @TESTDIR@/slapd.m.args + +####################################################################### +# database definitions +####################################################################### + +#mod#modulepath ../servers/slapd/back-@BACKEND@/:../servers/slapd/overlays +#mod#moduleload back_@BACKEND@.la +#ldapmod#modulepath ../servers/slapd/back-ldap/ +#ldapmod#moduleload back_ldap.la +#rwmmod#modulepath ../servers/slapd/overlays/ +#rwmmod#moduleload rwm.la +#monitormod#modulepath ../servers/slapd/back-monitor/ +#monitormod#moduleload back_monitor.la + +# here the proxy is not only acting as a proxy, but it also has a local database dc=local,dc=com" +database @BACKEND@ +suffix "dc=local,dc=com" +rootdn "cn=Manager,dc=local,dc=com" +rootpw "secret" +#~null~#directory @TESTDIR@/db.2.a + + +# Configure proxy +# - normal user binds to "*,dc=example,dc=com" are proxied through to the remote slapd +# - admin bind to local "cn=Manager,dc=local,dc=com" is overwritten by using idassert-bind +database ldap +uri "@URI1@" +suffix "dc=idle-timeout,dc=example,dc=com" +idassert-bind bindmethod=simple binddn="cn=Manager,dc=example,dc=com" credentials="secret" +idassert-authzFrom "dn.exact:cn=Manager,dc=local,dc=com" +rebind-as-user yes +monitoring on +idle-timeout @TIMEOUT@ +overlay rwm +rwm-suffixmassage "dc=idle-timeout,dc=example,dc=com" "ou=People,dc=example,dc=com" + +database ldap +uri "@URI1@" +suffix "dc=conn-ttl,dc=example,dc=com" +idassert-bind bindmethod=simple binddn="cn=Manager,dc=example,dc=com" credentials="secret" +idassert-authzFrom "dn.exact:cn=Manager,dc=local,dc=com" +rebind-as-user yes +monitoring on +conn-ttl @TIMEOUT@ +overlay rwm +rwm-suffixmassage "dc=conn-ttl,dc=example,dc=com" "ou=People,dc=example,dc=com" + +database monitor + diff --git a/tests/scripts/conf.sh b/tests/scripts/conf.sh index 98bfb5194..6200880c4 100755 --- a/tests/scripts/conf.sh +++ b/tests/scripts/conf.sh @@ -79,4 +79,5 @@ sed -e "s/@BACKEND@/${BACKEND}/" \ -e "s;@TESTWD@;${TESTWD};" \ -e "s;@DATADIR@;${DATADIR};" \ -e "s;@SCHEMADIR@;${SCHEMADIR};" \ + -e "s;@TIMEOUT@;${TIMEOUT};" \ -e "/^#/d" diff --git a/tests/scripts/defines.sh b/tests/scripts/defines.sh index 97cf08fd7..273f039cf 100755 --- a/tests/scripts/defines.sh +++ b/tests/scripts/defines.sh @@ -50,6 +50,7 @@ THREADS=${AC_THREADS-threadsno} SLEEP0=${SLEEP0-1} SLEEP1=${SLEEP1-7} SLEEP2=${SLEEP2-15} +TIMEOUT=${TIMEOUT-4} # dirs PROGDIR=./progs diff --git a/tests/scripts/test079-proxy-timeout b/tests/scripts/test079-proxy-timeout new file mode 100644 index 000000000..e097c0739 --- /dev/null +++ b/tests/scripts/test079-proxy-timeout @@ -0,0 +1,324 @@ +#! /bin/sh +# $OpenLDAP$ +## This work is part of OpenLDAP Software <http://www.openldap.org/>. +## +## Copyright 1998-2021 The OpenLDAP Foundation. +## All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted only as authorized by the OpenLDAP +## Public License. +## +## A copy of this license is available in the file LICENSE in the +## top-level directory of the distribution or, alternatively, at +## <http://www.OpenLDAP.org/license.html>. + +echo "running defines.sh" +. $SRCDIR/scripts/defines.sh + +if test $BACKLDAP = "ldapno" ; then + echo "LDAP backend not available, test skipped" + exit 0 +fi +if test $RWM = "rwmno" ; then + echo "rwm (rewrite/remap) overlay not available, test skipped" + exit 0 +fi + +mkdir -p $TESTDIR $DBDIR1 $DBDIR2 +$SLAPPASSWD -g -n >$CONFIGPWF + +# +# Start slapd that acts as a remote LDAP server that will be proxied +# +echo "Running slapadd to build database for the remote slapd server..." +. $CONFFILTER $BACKEND < $CONF > $CONF1 +$SLAPADD -f $CONF1 -l $LDIFORDERED +RC=$? +if test $RC != 0 ; then + echo "slapadd failed ($RC)!" + exit $RC +fi + +echo "Starting remote slapd server on TCP/IP port $PORT1..." +$SLAPD -f $CONF1 -h $URI1 -d $LVL > $LOG1 2>&1 & +SERVERPID=$! +if test $WAIT != 0 ; then + echo SERVERPID $SERVERPID + read foo +fi + +# +# Start ldapd that will proxy for the remote server +# +# Proxy is configured with two slapd-ldap backends: +# - one with idle timeout set: dc=idle-timeout,$BASED +# - one with connection TTL set: dc=conn-ttl,$BASEDN +# +echo "Starting slapd proxy on TCP/IP port $PORT2..." +. $CONFFILTER $BACKEND < $DATADIR/slapd-proxytimeout.conf > $CONF2 +$SLAPD -f $CONF2 -h $URI2 -d $LVL > $LOG2 2>&1 & +PROXYPID=$! +if test $WAIT != 0 ; then + echo PROXYPID $PROXYPID + read foo +fi + +KILLPIDS="$SERVERPID $PROXYPID" + +sleep $SLEEP0 + +############################################################################## +# +# Test 1: Test that shared connections are timed out +# + +NOW=`date +%s` +echo "Create shared connection towards remote LDAP (time_t now=$NOW timeout=`expr $NOW + $TIMEOUT`)" + +$LDAPSEARCH -b "dc=idle-timeout,$BASEDN" \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD \ + 'objectclass=*' > $TESTOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed for base: dc=idle-timeout,$BASEDN ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$LDAPSEARCH -b "dc=conn-ttl,$BASEDN" \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD \ + 'objectclass=*' >> $TESTOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed for base: dc=conn-ttl,$BASEDN ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +# Check that connections are established by searching for olmDbConnURI from Monitor + +echo "Checking that proxy has created connections towards backend" + +$LDAPSEARCH -b "cn=Connections,cn=database 2,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 0 ; then + echo "Error: LDAP connection to remote LDAP server is not found ($RC)" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$LDAPSEARCH -b "cn=Connections,cn=database 3,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 0 ; then + echo "Error: LDAP connection to remote LDAP server is not found ($RC)" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +# Wait for connections to be closed, either due to +# - idle-timeout and +# - conn-ttl + +echo "Sleeping until idle-timeout and conn-ttl have passed" +sleep `expr $TIMEOUT + 1` + +echo "Checking that proxy has closed expired connections towards the remote LDAP server (time_t now=`date +%s`)" + +$LDAPSEARCH -b "cn=Connections,cn=database 2,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 1 ; then + echo "Error: LDAP connection to remote LDAP server was not closed" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +$LDAPSEARCH -b "cn=Connections,cn=database 3,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 1 ; then + echo "Error: LDAP connection to remote LDAP server was not closed" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + + +############################################################################## +# +# Test 2: Test that private connections are timed out +# + +NOW=`date +%s` +echo "Create private connection towards remote LDAP (time_t now=$NOW timeout=`expr $NOW + $TIMEOUT`)" + +# Create fifos that are used to pass searches from the test case to ldapsearch +rm -f $TESTDIR/ldapsearch1.fifo $TESTDIR/ldapsearch2.fifo +mkfifo $TESTDIR/ldapsearch1.fifo $TESTDIR/ldapsearch2.fifo + +# Execute ldapsearch on background and have it read searches from the fifo +$LDAPSEARCH -b "dc=idle-timeout,$BASEDN" \ + -D "cn=Barbara Jensen,ou=Information Technology Division,dc=idle-timeout,$BASEDN" \ + -H $URI2 \ + -w "bjensen" \ + -f $TESTDIR/ldapsearch1.fifo >> $TESTOUT 2>&1 & +LDAPSEARCHPIDS=$! + +$LDAPSEARCH -b "dc=conn-ttl,$BASEDN" \ + -D "cn=Barbara Jensen,ou=Information Technology Division,dc=conn-ttl,$BASEDN" \ + -H $URI2 \ + -w "bjensen" \ + -f $TESTDIR/ldapsearch2.fifo >> $TESTOUT 2>&1 & +LDAPSEARCHPIDS="$LDAPSEARCHPIDS $!" + +# Open fifos as file descriptor +exec 3>$TESTDIR/ldapsearch1.fifo +exec 4>$TESTDIR/ldapsearch2.fifo + +# Trigger LDAP connections towards the proxy by executing a search +echo 'objectclass=*' >&3 +echo 'objectclass=*' >&4 +sleep 1 + +echo "Checking that proxy has created connections towards backend" + +$LDAPSEARCH -b "cn=Connections,cn=database 2,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 0 ; then + echo "Error: LDAP connection to remote LDAP server is not found ($RC)" + test $KILLSERVERS != no && kill -HUP $KILLPIDS $LDAPSEARCHPIDS + exit $RC +fi + +$LDAPSEARCH -b "cn=Connections,cn=database 3,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 0 ; then + echo "Error: LDAP connection to remote LDAP server is not found ($RC)" + test $KILLSERVERS != no && kill -HUP $KILLPIDS $LDAPSEARCHPIDS + exit $RC +fi + + +echo "Sleeping until idle-timeout and conn-ttl have passed" +sleep `expr $TIMEOUT + 1` + +echo "Checking that proxy has closed expired connections towards the remote LDAP server (time_t now=`date +%s`)" + +$LDAPSEARCH -b "cn=Connections,cn=database 2,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 1 ; then + echo "Error: LDAP connection to remote LDAP server was not closed" + test $KILLSERVERS != no && kill -HUP $KILLPIDS $LDAPSEARCHPIDS + exit $RC +fi + +$LDAPSEARCH -b "cn=Connections,cn=database 3,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 1 ; then + echo "Error: LDAP connection to remote LDAP server was not closed" + test $KILLSERVERS != no && kill -HUP $KILLPIDS $LDAPSEARCHPIDS + exit $RC +fi + +# Close the file descriptors associated with the fifos. +# This will trigger EOF to ldapsearch which will cause it to exit. +exec 3>&- +exec 4>&- + + +############################################################################## +# +# Test 3: Check that idle-timeout is reset on activity +# + +echo "Checking that idle-timeout is reset on activity" +NOW=`date +%s` +echo "Create cached connection: idle-timeout timeout starts (time_t now=$NOW, original_timeout=`expr $NOW + $TIMEOUT`)" +$LDAPSEARCH -b "dc=idle-timeout,$BASEDN" \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD \ + 'objectclass=*' >> $TESTOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed for base: dc=idle-timeout,$BASEDN ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +# sleep second less than idle-timeout to extend the timeout +sleep `expr $TIMEOUT - 1` +NOW=`date +%s` +echo "Do another search to reset the timeout (time_t now=$NOW, new_timeout=`expr $NOW + $TIMEOUT`)" +$LDAPSEARCH -b "dc=idle-timeout,$BASEDN" \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD \ + 'objectclass=*' >> $TESTOUT 2>&1 +RC=$? +if test $RC != 0 ; then + echo "ldapsearch failed for base: dc=idle-timeout,$BASEDN ($RC)!" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +sleep `expr $TIMEOUT - 1` +echo "Check that connection is still alive due to idle-timeout reset (time_t now=`date +%s`)" +$LDAPSEARCH -b "cn=Connections,cn=database 2,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 0 ; then + echo "Error: LDAP connection to remote LDAP server is not found ($RC)" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + +sleep 2 +echo "Check that connection is closed after extended idle-timeout has passed (time_t now=`date +%s`)" +$LDAPSEARCH -b "cn=Connections,cn=database 2,cn=databases,cn=monitor" -s one -LLL olmDbConnURI \ + -D "cn=Manager,dc=local,dc=com" \ + -H $URI2 \ + -w $PASSWD 2>&1 | tee -a $TESTOUT | grep ldap://${LOCALHOST}:$PORT1 >/dev/null +RC=$? +if test $RC != 1 ; then + echo "Error: LDAP connection to remote LDAP server was not closed" + test $KILLSERVERS != no && kill -HUP $KILLPIDS + exit $RC +fi + + +test $KILLSERVERS != no && kill -HUP $KILLPIDS + +echo ">>>>> Test succeeded" + +test $KILLSERVERS != no && wait + +exit 0 -- 2.30.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor