diff --git a/servers/slapd/abandon.c b/servers/slapd/abandon.c
index ea29321b3f15ab316a5ef7178227967008fbd878..4a55d34e118809b5b2d17ec3bde3cdb17107f117 100644
--- a/servers/slapd/abandon.c
+++ b/servers/slapd/abandon.c
@@ -49,19 +49,28 @@ do_abandon(
 	 * flag and abort the operation at a convenient time.
 	 */
 
-	ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
+	ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
 	for ( o = conn->c_ops; o != NULL; o = o->o_next ) {
+		if ( o->o_msgid == id )
+			goto found_op;
+	}
+	for ( o = conn->c_pending_ops; o != NULL; o = o->o_next ) {
 		if ( o->o_msgid == id )
 			break;
 	}
 
+found_op:
+
 	if ( o != NULL ) {
 		ldap_pvt_thread_mutex_lock( &o->o_abandonmutex );
 		o->o_abandon = 1;
 		ldap_pvt_thread_mutex_unlock( &o->o_abandonmutex );
+
 	} else {
 		Debug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0,
 		    0 );
 	}
-	ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
+
+	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 }
diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c
index f029d3ccfd47b20005e9671cdef33d98c0fa6676..483aba6dd6bb8eb34416ead1410e80dab8d2a83e 100644
--- a/servers/slapd/acl.c
+++ b/servers/slapd/acl.c
@@ -287,7 +287,9 @@ acl_access_allowed(
 			}
 		}
 		if ( b->a_addrpat != NULL ) {
-			if ( regex_matches( b->a_addrpat, conn->c_addr, edn, matches ) ) {
+			if ( regex_matches( b->a_addrpat, conn->c_client_addr,
+				edn, matches ) )
+			{
 				Debug( LDAP_DEBUG_ACL,
 				    "<= acl_access_allowed: matched by clause #%d access %s\n",
 				    i, (b->a_access & ~ACL_SELF) >= access ?
@@ -299,7 +301,8 @@ acl_access_allowed(
 		if ( b->a_domainpat != NULL ) {
 			Debug( LDAP_DEBUG_ARGS, "<= check a_domainpath: %s\n",
 				b->a_domainpat, 0, 0 );
-			if ( regex_matches( b->a_domainpat, conn->c_domain, edn, matches ) ) 
+			if ( regex_matches( b->a_domainpat, conn->c_client_name,
+				edn, matches ) ) 
 			{
 				Debug( LDAP_DEBUG_ACL,
 				    "<= acl_access_allowed: matched by clause #%d access %s\n",
diff --git a/servers/slapd/add.c b/servers/slapd/add.c
index 7dcd020f920549314776e4d93e8f150b135a6811..16eed3a63c3313b57d98dddc2bdf09b3f05ab459 100644
--- a/servers/slapd/add.c
+++ b/servers/slapd/add.c
@@ -151,6 +151,7 @@ add_created_attrs( Operation *op, Entry *e )
 	Attribute	**a, **next;
 	Attribute	*tmp;
 	struct tm	*ltm;
+	time_t		currenttime;
 
 	Debug( LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0 );
 
@@ -181,7 +182,8 @@ add_created_attrs( Operation *op, Entry *e )
 	}
 	attr_merge( e, "creatorsname", bvals );
 
-	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
+	currenttime = slap_get_time();
+	ldap_pvt_thread_mutex_lock( &gmtime_mutex );
 #ifndef LDAP_LOCALTIME
 	ltm = gmtime( &currenttime );
 	strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@@ -189,7 +191,7 @@ add_created_attrs( Operation *op, Entry *e )
 	ltm = localtime( &currenttime );
 	strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
 #endif
-	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+	ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
 
 	bv.bv_val = buf;
 	bv.bv_len = strlen( bv.bv_val );
diff --git a/servers/slapd/back-ldbm/dbcache.c b/servers/slapd/back-ldbm/dbcache.c
index f563cb61c196215e5c5cb0b42f7bc219b9584fbf..58b7b8571d34c54ed4889bfb168e22f673dd455e 100644
--- a/servers/slapd/back-ldbm/dbcache.c
+++ b/servers/slapd/back-ldbm/dbcache.c
@@ -41,9 +41,7 @@ ldbm_cache_open(
 	    flags, li->li_mode );
 
 	lru = 0;
-	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
-	curtime = currenttime;
-	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+	curtime = slap_get_time();
 	oldtime = curtime;
 
 	ldap_pvt_thread_mutex_lock( &li->li_dbcache_mutex );
diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c
index 5def38a2b33b3f0c5f4e432ab5ee70d1f3f4a159..04e05931930dca8e1a949e167071657ea815e565 100644
--- a/servers/slapd/back-ldbm/search.c
+++ b/servers/slapd/back-ldbm/search.c
@@ -139,6 +139,7 @@ ldbm_back_search(
 	rcur = strchr( rbuf, '\0' );
 	for ( id = idl_firstid( candidates ); id != NOID;
 	    id = idl_nextid( candidates, id ) ) {
+
 		/* check for abandon */
 		ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
 		if ( op->o_abandon ) {
@@ -153,10 +154,7 @@ ldbm_back_search(
 		ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
 
 		/* check time limit */
-		ldap_pvt_thread_mutex_lock( &currenttime_mutex );
-		time( &currenttime );
-		if ( tlimit != -1 && currenttime > stoptime ) {
-			ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+		if ( tlimit != -1 && slap_get_time() > stoptime ) {
 			send_ldap_search_result( conn, op,
 			    LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
 			    NULL, nentries );
@@ -167,7 +165,6 @@ ldbm_back_search(
 			}
 			return( 0 );
 		}
-		ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
 
 		/* get the entry with reader lock */
 		if ( (e = id2entry_r( be, id )) == NULL ) {
diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c
index cf0b2af328eb65760cf0bdbc633c703acc35942a..223401aa1ba863f0b7ed0dfbe15dc997e8b6a329 100644
--- a/servers/slapd/bind.c
+++ b/servers/slapd/bind.c
@@ -135,7 +135,7 @@ do_bind(
 			free( cred.bv_val );
 		}
 
-		ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
+		ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
 		conn->c_protocol = version;
 
@@ -149,7 +149,7 @@ do_bind(
 			conn->c_dn = NULL;
 		}
 
-		ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
+		ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
 		send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
 		return;
@@ -168,7 +168,7 @@ do_bind(
 			free( cred.bv_val );
 		}
 		if ( cred.bv_len == 0 ) {
-			ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
+			ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
 			conn->c_protocol = version;
 
@@ -182,7 +182,7 @@ do_bind(
 				conn->c_dn = NULL;
 			}
 
-			ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
+			ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
 			send_ldap_result( conn, op, LDAP_SUCCESS,
 				NULL, NULL );
@@ -203,7 +203,7 @@ do_bind(
 		ndn = suffixAlias( ndn, op, be );
 
 		if ( (*be->be_bind)( be, conn, op, ndn, method, &cred, &edn ) == 0 ) {
-			ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
+			ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
 			conn->c_protocol = version;
 
@@ -228,7 +228,7 @@ do_bind(
 			Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
 	    		conn->c_cdn, conn->c_dn, method );
 
-			ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
+			ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
 
 			/* send this here to avoid a race condition */
 			send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c
index 75871477337b160daaa42905b991316ab66d4743..4f2a5cec0073a3806518c35b762cd18a5b7a8100 100644
--- a/servers/slapd/connection.c
+++ b/servers/slapd/connection.c
@@ -10,6 +10,16 @@
 
 #include "slap.h"
 
+/* protected by connections_mutex */
+static ldap_pvt_thread_mutex_t connections_mutex;
+static Connection *connections = NULL;
+static int conn_index = -1;
+static long conn_nextid = 0;
+
+static Connection* connection_get( int s );
+
+static int connection_input( Connection *c );
+
 static int connection_op_activate( Connection *conn, Operation *op );
 static int connection_resched( Connection *conn );
 
@@ -18,6 +28,360 @@ struct co_arg {
 	Operation	*co_op;
 };
 
+/*
+ * Initialize connection management infrastructure.
+ */
+int connections_init(void)
+{
+	int i;
+
+	assert( connections == NULL );
+
+	if( connections != NULL) { /* probably should assert this */
+		Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
+			0, 0, 0 );
+		return -1;
+	}
+
+	/* should check return of every call */
+	ldap_pvt_thread_mutex_init( &connections_mutex );
+
+	connections = (Connection *) calloc( dtblsize, sizeof(Connection) );
+
+	if( connections == NULL ) {
+		Debug( LDAP_DEBUG_ANY,
+			"connections_init: allocation (%d*%ld) of connection array failed.\n",
+			dtblsize, (long) sizeof(Connection), 0 );
+		return -1;
+	}
+
+	/*
+	 * per entry initialization of the Connection array initialization
+	 * will be done by connection_init()
+	 */ 
+
+	return 0;
+}
+
+static Connection* connection_get( int s )
+{
+	Connection *c = NULL;
+
+	assert( connections != NULL );
+
+	if(s < 0) {
+		return NULL;
+	}
+
+#ifndef HAVE_WINSOCK
+	assert( connections[s].c_struct_state == SLAP_C_USED );
+	assert( connections[s].c_conn_state != SLAP_C_INVALID );
+	assert( connections[s].c_sb.sb_sd != -1 );
+
+	c = &connections[s];
+#else
+	{
+		int i;
+
+		for(i=0; i<dtblsize; i++) {
+			if( connections[i].c_struct_state == SLAP_C_STRUCT_UNINITIALIZED ) {
+				assert( connections[i].c_conn_state == SLAP_C_INVALID );
+				assert( connections[s].c_sb.sb_sd == 0 );
+				break;
+			}
+
+			if( connections[i].c_struct_state == SLAP_C_STRUCT_UNUSED ) {
+				assert( connections[i].c_conn_state == SLAP_C_INVALID );
+				assert( connections[s].c_sb.sb_sd == -1 );
+				continue;
+			}
+
+			assert( connections[i].c_struct_state == SLAP_C_STRUCT_USED );
+			assert( connections[i].c_conn_state != SLAP_C_INVALID );
+			assert( connections[s].c_sb.sb_sd != -1 );
+
+			if( connections[i].c_sb.sb_sd == s ) {
+				c = &connections[s];
+				break;
+			}
+		}
+	}
+#endif
+	if( c != NULL ) {
+		ldap_pvt_thread_mutex_lock( &c->c_mutex );
+	}
+	return c;
+}
+
+static void connection_return( Connection *c )
+{
+	ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+}
+
+long connection_init(
+	int s,
+	const char* name,
+	const char* addr)
+{
+	long id;
+	Connection *c;
+	assert( connections != NULL );
+
+	if( s < 0 ) {
+		return -1;
+	}
+
+	assert( s >= 0 );
+#ifndef HAVE_WINSOCK
+	assert( s < dtblsize );
+#endif
+
+	ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+#ifndef HAVE_WINSOCK
+	c = &connections[s];
+
+#else
+	{
+		int i;
+
+		for( i=0; i < dtblsize; i++ {
+			if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
+				assert( connections[i].c_sb.sb_sd == 0 );
+				c = &connections[i];
+				break;
+			}
+
+			if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
+				assert( connections[i].c_sb.sb_sd == -1 );
+				c = &connections[i];
+				break;
+			}
+
+			assert( connections[i].c_struct_state == SLAP_C_USED );
+			assert( connections[i].c_conn_state != SLAP_C_INVALID );
+			assert( connections[i].c_sb.sb_sd != -1 );
+		}
+
+		if( c == NULL ) {
+			ldap_pvt_thread_mutex_unlock( &connections_mutex );
+			return -1;
+		}
+	}
+#endif
+
+	assert( c != NULL );
+	assert( c->c_struct_state != SLAP_C_USED );
+	assert( c->c_conn_state == SLAP_C_INVALID );
+
+	if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
+		c->c_dn = NULL;
+		c->c_cdn = NULL;
+		c->c_client_name = NULL;
+		c->c_client_addr = NULL;
+		c->c_ops = NULL;
+		c->c_pending_ops = NULL;
+
+		lber_pvt_sb_init( &c->c_sb );
+
+		/* should check status of thread calls */
+		ldap_pvt_thread_mutex_init( &c->c_mutex );
+		ldap_pvt_thread_mutex_init( &c->c_write_mutex );
+		ldap_pvt_thread_cond_init( &c->c_write_cv );
+
+		c->c_struct_state = SLAP_C_UNUSED;
+	}
+
+	ldap_pvt_thread_mutex_lock( &c->c_mutex );
+
+	assert( c->c_struct_state == SLAP_C_UNUSED );
+	assert(	c->c_dn == NULL );
+	assert(	c->c_cdn == NULL );
+	assert( c->c_client_name == NULL );
+	assert( c->c_client_addr == NULL );
+	assert( c->c_ops == NULL );
+	assert( c->c_pending_ops == NULL );
+
+	c->c_client_name = ch_strdup( name == NULL ? "" : name );
+	c->c_client_addr = ch_strdup( addr );
+
+	c->c_n_ops_received = 0;
+#ifdef LDAP_COUNTERS
+	c->c_n_ops_executing = 0;
+	c->c_n_ops_pending = 0;
+	c->c_n_ops_completed = 0;
+#endif
+
+	c->c_starttime = slap_get_time();
+
+	lber_pvt_sb_set_desc( &c->c_sb, s );
+	lber_pvt_sb_set_io( &c->c_sb, &lber_pvt_sb_io_tcp, NULL );
+
+	if( lber_pvt_sb_set_nonblock( &c->c_sb, 1 ) < 0 ) {
+		Debug( LDAP_DEBUG_ANY,
+			"connection_init(%d, %s, %s): set nonblocking failed\n",
+			s, c->c_client_name, c->c_client_addr);
+	}
+
+	id = c->c_connid = conn_nextid++;
+
+	c->c_conn_state = SLAP_C_INACTIVE;
+	c->c_struct_state = SLAP_C_USED;
+
+	ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+	ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
+	return id;
+}
+
+static void
+connection_destroy( Connection *c )
+{
+	assert( connections != NULL );
+	assert( c != NULL );
+	assert( c->c_struct_state != SLAP_C_UNUSED );
+	assert( c->c_conn_state != SLAP_C_INVALID );
+	assert( c->c_ops == NULL );
+
+	c->c_struct_state = SLAP_C_UNUSED;
+	c->c_conn_state = SLAP_C_INVALID;
+
+	c->c_version = 0;
+	c->c_protocol = 0;
+
+	c->c_starttime = 0;
+
+	if(c->c_dn != NULL) {
+		free(c->c_dn);
+		c->c_dn = NULL;
+	}
+	if(c->c_cdn != NULL) {
+		free(c->c_cdn);
+		c->c_cdn = NULL;
+	}
+	if(c->c_client_name != NULL) {
+		free(c->c_client_name);
+		c->c_client_name = NULL;
+	}
+	if(c->c_client_addr != NULL) {
+		free(c->c_client_addr);
+		c->c_client_addr = NULL;
+	}
+
+	if ( lber_pvt_sb_in_use(&c->c_sb) ) {
+		int sd = lber_pvt_sb_get_desc(&c->c_sb);
+
+		slapd_remove( sd );
+	   	lber_pvt_sb_close( &c->c_sb );
+
+		Statslog( LDAP_DEBUG_STATS,
+		    "conn=%d fd=%d closed.\n",
+			c->c_connid, sd, 0, 0, 0 );
+	}
+
+   	lber_pvt_sb_destroy( &c->c_sb );
+}
+
+static void connection_close( Connection *c )
+{
+	assert( connections != NULL );
+	assert( c != NULL );
+	assert( c->c_struct_state == SLAP_C_USED );
+	assert( c->c_conn_state == SLAP_C_CLOSING );
+
+	if( c->c_ops != NULL ) {
+		Debug( LDAP_DEBUG_TRACE,
+			"connection_close: deferring conn=%ld sd=%d.\n",
+			c->c_connid, c->c_sb.sb_sd, 0 );
+
+		return;
+	}
+
+	Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%ld sd=%d.\n",
+		c->c_connid, c->c_sb.sb_sd, 0 );
+
+	connection_destroy( c );
+}
+
+long connections_nextid(void)
+{
+	long id;
+	assert( connections != NULL );
+
+	ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+	id = conn_nextid;
+
+	ldap_pvt_thread_mutex_unlock( &connections_mutex );
+
+	return id;
+}
+
+Connection* connection_first(void)
+{
+	assert( connections != NULL );
+
+	ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+	assert( conn_index == -1 );
+	conn_index = 0;
+
+	return connection_next(NULL);
+}
+
+Connection* connection_next(Connection *c)
+{
+	assert( connections != NULL );
+	assert( conn_index != -1 );
+	assert( conn_index <= dtblsize );
+
+	if( c != NULL ) {
+		ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+	}
+
+	c = NULL;
+
+	for(; conn_index < dtblsize; conn_index++) {
+		if( connections[conn_index].c_struct_state == SLAP_C_UNINITIALIZED ) {
+			assert( connections[conn_index].c_conn_state == SLAP_C_INVALID );
+#ifndef HAVE_WINSOCK
+			continue;
+#else
+			break;
+#endif
+		}
+
+		if( connections[conn_index].c_struct_state == SLAP_C_USED ) {
+			assert( connections[conn_index].c_conn_state != SLAP_C_INVALID );
+			c = &connections[conn_index++];
+			break;
+		}
+
+		assert( connections[conn_index].c_struct_state == SLAP_C_UNUSED );
+		assert( connections[conn_index].c_conn_state == SLAP_C_INVALID );
+	}
+
+	if( c != NULL ) {
+		ldap_pvt_thread_mutex_lock( &c->c_mutex );
+	}
+
+	return c;
+}
+
+void connection_done(Connection *c)
+{
+	assert( connections != NULL );
+	assert( conn_index != -1 );
+	assert( conn_index <= dtblsize );
+
+	if( c != NULL ) {
+		ldap_pvt_thread_mutex_unlock( &c->c_mutex );
+	}
+
+	conn_index = -1;
+	ldap_pvt_thread_mutex_unlock( &connections_mutex );
+}
+
 /*
  * connection_activity - handle the request operation op on connection
  * conn.  This routine figures out what kind of operation it is and
@@ -31,13 +395,11 @@ connection_operation( void *arg_v )
 	int tag = arg->co_op->o_tag;
 	Connection *conn = arg->co_conn;
 
-	ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
-	conn->c_ops_received++;
-	ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
-
+#ifdef LDAP_COUNTERS
 	ldap_pvt_thread_mutex_lock( &ops_mutex );
 	ops_initiated++;
 	ldap_pvt_thread_mutex_unlock( &ops_mutex );
+#endif
 
 	switch ( tag ) {
 	case LDAP_REQ_BIND:
@@ -91,12 +453,17 @@ connection_operation( void *arg_v )
 		break;
 	}
 
+#ifdef LDAP_COUNTERS
 	ldap_pvt_thread_mutex_lock( &ops_mutex );
 	ops_completed++;
 	ldap_pvt_thread_mutex_unlock( &ops_mutex );
+#endif
+
+	ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
-	ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
+#ifdef LDAP_COUNTERS
 	conn->c_ops_completed++;
+#endif
 
 	slap_op_remove( &conn->c_ops, arg->co_op );
 	slap_op_free( arg->co_op );
@@ -105,11 +472,27 @@ connection_operation( void *arg_v )
 	free( (char *) arg );
 	arg = NULL;
 
-	if((tag == LDAP_REQ_BIND) && (conn->c_state == SLAP_C_BINDING)) {
-		conn->c_state = SLAP_C_ACTIVE;
+	switch( tag ) {
+#ifdef LDAP_COMPAT30
+	case LDAP_REQ_UNBIND_30:
+#endif
+	case LDAP_REQ_UNBIND:
+		conn->c_conn_state = SLAP_C_CLOSING;
+		break;
+
+	case LDAP_REQ_BIND:
+		if( conn->c_conn_state == SLAP_C_BINDING) {
+			conn->c_conn_state = SLAP_C_ACTIVE;
+		}
 	}
 
-	ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
+	if( conn->c_conn_state == SLAP_C_CLOSING ) {
+		Debug( LDAP_DEBUG_TRACE,
+			"connection_operation: attempting closing conn=%ld sd=%d.\n",
+			conn->c_connid, conn->c_sb.sb_sd, 0 );
+
+		connection_close( conn );
+	}
 
 	ldap_pvt_thread_mutex_lock( &active_threads_mutex );
 	active_threads--;
@@ -120,11 +503,58 @@ connection_operation( void *arg_v )
 
 	connection_resched( conn );
 
+	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
 	return NULL;
 }
 
-void
-connection_activity(
+int connection_read(int s)
+{
+	int rc = 0;
+	Connection *c;
+	assert( connections != NULL );
+
+	ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+	c = connection_get( s );
+	if( c == NULL ) {
+		Debug( LDAP_DEBUG_ANY,
+			"connection_read(%d): no connection!\n",
+			s, 0, 0 );
+		return -1;
+	}
+
+	Debug( LDAP_DEBUG_TRACE,
+		"connection_read(%d): checking for input on id=%ld\n",
+		s, c->c_connid, 0 );
+
+#define CONNECTION_INPUT_LOOP 1
+
+#ifdef DATA_READY_LOOP
+	while(!rc && lber_pvt_sb_data_ready(&c->c_sb))
+#elif CONNECTION_INPUT_LOOP
+	while(!rc)
+#endif
+	{
+		rc = connection_input( c );
+	}
+
+	if( rc < 0 ) {
+		Debug( LDAP_DEBUG_TRACE,
+			"connection_read(%d): input error id=%ld, closing.\n",
+			s, c->c_connid, 0 );
+
+		c->c_conn_state = SLAP_C_CLOSING;
+		connection_close( c );
+	}
+
+	connection_return( c );
+	ldap_pvt_thread_mutex_unlock( &connections_mutex );
+	return 0;
+}
+
+static int
+connection_input(
     Connection *conn
 )
 {
@@ -136,30 +566,32 @@ connection_activity(
 	if ( conn->c_currentber == NULL && (conn->c_currentber = ber_alloc())
 	    == NULL ) {
 		Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
-		return;
+		return -1;
 	}
 
 	errno = 0;
 	if ( (tag = ber_get_next( &conn->c_sb, &len, conn->c_currentber ))
-	    != LDAP_TAG_MESSAGE ) {
+	    != LDAP_TAG_MESSAGE )
+	{
 		Debug( LDAP_DEBUG_TRACE,
-		    "ber_get_next on fd %d failed errno %d (%s)\n",
-		    lber_pvt_sb_get_desc(&conn->c_sb), errno, errno > -1 && errno < sys_nerr ?
-		    sys_errlist[errno] : "unknown" );
-		Debug( LDAP_DEBUG_TRACE, "*** got %ld of %lu so far\n",
-		    (long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
-		    conn->c_currentber->ber_len, 0 );
+			"ber_get_next on fd %d failed errno %d (%s)\n",
+			lber_pvt_sb_get_desc(&conn->c_sb), errno,
+			errno > -1 && errno < sys_nerr ?  sys_errlist[errno] : "unknown" );
+		Debug( LDAP_DEBUG_TRACE, "\t*** got %ld of %lu so far\n",
+			(long)(conn->c_currentber->ber_rwptr - conn->c_currentber->ber_buf),
+			conn->c_currentber->ber_len, 0 );
 
 		if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
 			/* log, close and send error */
 			ber_free( conn->c_currentber, 1 );
 			conn->c_currentber = NULL;
 
-			close_connection( conn, conn->c_connid, -1 );
+			return -1;
 		}
 
-		return;
+		return 1;
 	}
+
 	ber = conn->c_currentber;
 	conn->c_currentber = NULL;
 
@@ -168,9 +600,7 @@ connection_activity(
 		Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
 		    0 );
 		ber_free( ber, 1 );
-
-		close_connection( conn, conn->c_connid, -1 );
-		return;
+		return -1;
 	}
 
 	if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
@@ -179,8 +609,7 @@ connection_activity(
 		    0 );
 		ber_free( ber, 1 );
 
-		close_connection( conn, conn->c_connid, -1 );
-		return;
+		return -1;
 	}
 
 #ifdef LDAP_COMPAT30
@@ -189,22 +618,27 @@ connection_activity(
 	}
 #endif
 
-	op = slap_op_alloc( ber, msgid, tag,
-	   	conn->c_ops_received, conn->c_connid );
-
-	if ( conn->c_state == SLAP_C_BINDING ) {
-		/* connection is binding to a dn, make 'em wait */
-		ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
-		slap_op_add( &conn->c_pending_ops, op );
+	op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
 
+	if ( conn->c_conn_state == SLAP_C_BINDING
+		|| conn->c_conn_state == SLAP_C_CLOSING )
+	{
 		Debug( LDAP_DEBUG_ANY, "deferring operation\n", 0, 0, 0 );
+		slap_op_add( &conn->c_pending_ops, op );
 
-		ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
+	} else {
+		connection_op_activate( conn, op );
+	}
 
-		return;
+#ifdef NO_THREADS
+	if ( conn->c_struct_state != SLAP_C_USED ) {
+		/* connection must have got closed underneath us */
+		return 1;
 	}
+#endif
+	assert( conn->c_struct_state == SLAP_C_USED );
 
-	connection_op_activate( conn, op );
+	return 0;
 }
 
 static int
@@ -212,29 +646,21 @@ connection_resched( Connection *conn )
 {
 	Operation *op;
 
-	if( conn->c_state != SLAP_C_ACTIVE ) {
+	if( conn->c_conn_state != SLAP_C_ACTIVE ) {
 		/* other states need different handling */
 		return;
 	}
 
-	ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
-
 	for( op = slap_op_pop( &conn->c_pending_ops );
 		op != NULL;
 		op = slap_op_pop( &conn->c_pending_ops ) )
 	{
-		ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
-
 		connection_op_activate( conn, op );
 
-		ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
-
-		if ( conn->c_state == SLAP_C_BINDING ) {
+		if ( conn->c_conn_state == SLAP_C_BINDING ) {
 			break;
 		}
 	}
-
-	ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
 }
 
 static int connection_op_activate( Connection *conn, Operation *op )
@@ -244,13 +670,11 @@ static int connection_op_activate( Connection *conn, Operation *op )
 	int status;
 	unsigned long tag = op->o_tag;
 
-	ldap_pvt_thread_mutex_lock( &conn->c_dnmutex );
 	if ( conn->c_dn != NULL ) {
 		tmpdn = ch_strdup( conn->c_dn );
 	} else {
 		tmpdn = NULL;
 	}
-	ldap_pvt_thread_mutex_unlock( &conn->c_dnmutex );
 
 	arg = (struct co_arg *) ch_malloc( sizeof(struct co_arg) );
 	arg->co_conn = conn;
@@ -259,16 +683,12 @@ static int connection_op_activate( Connection *conn, Operation *op )
 	arg->co_op->o_dn = ch_strdup( tmpdn != NULL ? tmpdn : "" );
 	arg->co_op->o_ndn = dn_normalize_case( ch_strdup( arg->co_op->o_dn ) );
 
-	ldap_pvt_thread_mutex_lock( &conn->c_opsmutex );
-
 	slap_op_add( &conn->c_ops, arg->co_op );
 
 	if(tag == LDAP_REQ_BIND) {
-		conn->c_state = SLAP_C_BINDING;
+		conn->c_conn_state = SLAP_C_BINDING;
 	}
 
-	ldap_pvt_thread_mutex_unlock( &conn->c_opsmutex );
-
 	if ( tmpdn != NULL ) {
 		free( tmpdn );
 	}
@@ -281,8 +701,37 @@ static int connection_op_activate( Connection *conn, Operation *op )
 					 connection_operation, (void *) arg );
 
 	if ( status != 0 ) {
-		Debug( LDAP_DEBUG_ANY, "ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
+		Debug( LDAP_DEBUG_ANY,
+		"ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
+
+		/* should move op to pending list */
 	}
 
 	return status;
 }
+
+int connection_write(int s)
+{
+	Connection *c;
+	assert( connections != NULL );
+
+	ldap_pvt_thread_mutex_lock( &connections_mutex );
+
+	c = connection_get( s );
+	if( c == NULL ) {
+		Debug( LDAP_DEBUG_ANY,
+			"connection_write(%d): no connection!\n",
+			s, 0, 0 );
+		return -1;
+	}
+
+	Debug( LDAP_DEBUG_TRACE,
+		"connection_write(%d): waking output for id=%ld\n",
+		s, c->c_connid, 0 );
+
+	ldap_pvt_thread_cond_signal( &c->c_write_cv );
+
+	connection_return( c );
+	ldap_pvt_thread_mutex_unlock( &connections_mutex );
+	return 0;
+}
diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c
index 4596840b005c99385285656f93cc8cb2e51b024a..6294f4fb4ad29b896c0bd2dd5fe8e15e007ef8a0 100644
--- a/servers/slapd/daemon.c
+++ b/servers/slapd/daemon.c
@@ -1,10 +1,3 @@
-
-/* Revision history
- *
- * 5-Jun-96	hodges
- *	Added locking of new_conn_mutex when traversing the c[] array.
- */
-
 #include "portable.h"
 
 #include <stdio.h>
@@ -33,26 +26,113 @@ int allow_severity = LOG_INFO;
 int deny_severity = LOG_NOTICE;
 #endif /* TCP Wrappers */
 
-int		dtblsize;
-Connection	*c;
+/* globals */
+int dtblsize;
 
+static ldap_pvt_thread_t	listener_tid;
 static volatile sig_atomic_t slapd_shutdown = 0;
 
-/* a link to the slapd.conf configuration parameters */
-extern char *slapd_pid_file;
-extern char *slapd_args_file;
+struct slap_daemon {
+	ldap_pvt_thread_mutex_t	sd_mutex;
+
+	int sd_nactives;
+
+#ifndef HAVE_WINSOCK
+	/* In winsock, accept() returns values higher than dtblsize
+		so don't bother with this optimization */
+	int sd_nfds;
+#endif
+
+	fd_set sd_actives;
+	fd_set sd_readers;
+	fd_set sd_writers;
+} slap_daemon; 
+
+/*
+ * Add a descriptor to daemon control
+ */
+static void slapd_add(int s) {
+	ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+
+	assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
+	assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
+	assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
+
+	if (s >= slap_daemon.sd_nfds) {
+		slap_daemon.sd_nfds = s + 1;
+	}
+
+	FD_SET( s, &slap_daemon.sd_actives );
+	FD_SET( s, &slap_daemon.sd_readers );
+
+	Debug( LDAP_DEBUG_CONNS, "daemon: added %d%s%s\n", s,
+	    FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
+		FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
+
+	ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+}
+
+/*
+ * Remove the descriptor from daemon control
+ */
+void slapd_remove(int s) {
+	ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+
+	assert( s < slap_daemon.sd_nfds );
+	assert( FD_ISSET( s, &slap_daemon.sd_actives ));
+
+	Debug( LDAP_DEBUG_CONNS, "daemon: removing %d%s%s\n", s,
+	    FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
+		FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
+
+	FD_CLR( s, &slap_daemon.sd_actives );
+	FD_CLR( s, &slap_daemon.sd_readers );
+	FD_CLR( s, &slap_daemon.sd_writers );
+
+	ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+}
+
+void slapd_clr_write(int s, int wake) {
+	ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+
+	assert( s < slap_daemon.sd_nfds );
+	assert( FD_ISSET( s, &slap_daemon.sd_actives) );
+	assert( FD_ISSET( s, &slap_daemon.sd_writers) );
+	FD_SET( s, &slap_daemon.sd_writers );
+
+	ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
+
+	if( wake ) {
+		ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+	}
+}
+
+void slapd_set_write(int s, int wake) {
+	ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
+
+	FD_SET( s, &slap_daemon.sd_writers );
+
+	ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
 
-void *
-slapd_daemon(
+	if( wake ) {
+		ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
+	}
+}
+
+static void slapd_close(int s) {
+	slapd_remove(s);
+
+	Debug( LDAP_DEBUG_CONNS, "daemon: closing %d\n", s, 0, 0 );
+	close(s);
+}
+
+static void *
+slapd_daemon_task(
 	void *ptr
 )
 {
 	struct sockaddr_in *addr = ptr;
-	int			i;
-	int			tcps, ns;
-	fd_set			readfds;
-	fd_set			writefds;
-	FILE			*fp;
+	int	tcps = -1;
 
 #ifdef HAVE_SYSCONF
 	dtblsize = sysconf( _SC_OPEN_MAX );
@@ -68,179 +148,201 @@ slapd_daemon(
 	}
 #endif	/* !FD_SETSIZE */
 
-	c = (Connection *) ch_calloc( (size_t) dtblsize, sizeof(Connection) );
-
-	for ( i = 0; i < dtblsize; i++ ) {
-		c[i].c_dn = NULL;
-		c[i].c_cdn = NULL;
-		c[i].c_addr = NULL;
-		c[i].c_domain = NULL;
-		c[i].c_ops = NULL;
-		lber_pvt_sb_init( &c[i].c_sb );
-		ldap_pvt_thread_mutex_init( &c[i].c_dnmutex );
-		ldap_pvt_thread_mutex_init( &c[i].c_opsmutex );
-		ldap_pvt_thread_mutex_init( &c[i].c_pdumutex );
-		ldap_pvt_thread_cond_init( &c[i].c_wcv );
-	}
+	connections_init();
 
-	if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
-		Debug( LDAP_DEBUG_ANY, "socket() failed errno %d (%s)", errno,
-		    errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
-		    "unknown", 0 );
-		exit( 1 );
-	}
+	ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
+	FD_ZERO( &slap_daemon.sd_readers );
+	FD_ZERO( &slap_daemon.sd_writers );
 
-	i = 1;
-	if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR, (char *) &i,
-	    sizeof(i) ) == -1 ) {
-		Debug( LDAP_DEBUG_ANY, "setsockopt() failed errno %d (%s)",
-		    errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
-		    "unknown", 0 );
-	}
+	if( addr != NULL ) {
+		int	tmp;
 
-	if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
-		Debug( LDAP_DEBUG_ANY, "bind() failed errno %d (%s)\n",
-		    errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
-		    "unknown", 0 );
-		exit( 1 );
-	}
+		if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
+			Debug( LDAP_DEBUG_ANY,
+				"daemon: socket() failed errno %d (%s)", errno,
+		    	errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
+		    	"unknown", 0 );
+			exit( 1 );
+		}
 
-	if ( listen( tcps, 5 ) == -1 ) {
-		Debug( LDAP_DEBUG_ANY, "listen() failed errno %d (%s)",
-		    errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
-		    "unknown", 0 );
-		exit( 1 );
-	}
+#ifndef HAVE_WINSOCK
+		if ( tcps >= dtblsize ) {
+			Debug( LDAP_DEBUG_ANY,
+				"daemon: listener descriptor %d is too great",
+				tcps, dtblsize, 0 );
+			exit( 1 );
+		}
+#endif
 
-	Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
+		tmp = 1;
+		if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR,
+			(char *) &tmp, sizeof(tmp) ) == -1 )
+		{
+			Debug( LDAP_DEBUG_ANY,
+				"slapd(%d): setsockopt() failed errno %d (%s)",
+		    	tcps, errno,
+				errno > -1 && errno < sys_nerr
+					? sys_errlist[errno] : "unknown" );
+
+			errno = 0;
+		}
 
-	if (( slapd_pid_file != NULL ) &&
-			(( fp = fopen( slapd_pid_file, "w" )) != NULL )) {
-		fprintf( fp, "%d\n", (int) getpid() );
-		fclose( fp );
-	}
+		if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
+			Debug( LDAP_DEBUG_ANY, "daemon: bind(%d) failed errno %d (%s)\n",
+		    	tcps, errno,
+				errno > -1 && errno < sys_nerr
+					? sys_errlist[errno] : "unknown" );
+			exit( 1 );
+		}
+
+		if ( listen( tcps, 5 ) == -1 ) {
+			Debug( LDAP_DEBUG_ANY,
+				"daemon: listen(%d, 5) failed errno %d (%s)\n",
+			    tcps, errno,
+				errno > -1 && errno < sys_nerr
+					? sys_errlist[errno] : "unknown" );
+			exit( 1 );
+		}
+
+		slapd_add( tcps );
 
-	if (( slapd_args_file != NULL ) &&
-			(( fp = fopen( slapd_args_file, "w" )) != NULL )) {
-		for ( i = 0; i < g_argc; i++ ) {
-			fprintf( fp, "%s ", g_argv[i] );
+	} else {
+		if( connection_init( 0, NULL, NULL ) ) {
+			Debug( LDAP_DEBUG_ANY,
+				"connection_init(%d) failed.\n",
+				0, 0, 0 );
+
+			exit( 1 );
 		}
-		fprintf( fp, "\n" );
-		fclose( fp );
+
+		slapd_add( 0 );
 	}
 
 	while ( !slapd_shutdown ) {
+		int i, ns, nfds;
+
+		fd_set			readfds;
+		fd_set			writefds;
+
 		struct sockaddr_in	from;
 		struct hostent		*hp;
 		struct timeval		zero;
 		struct timeval		*tvp;
-		int			len;
-	   	int			data_ready;
 
 		char	*client_name;
 		char	*client_addr;
 
 		FD_ZERO( &writefds );
 		FD_ZERO( &readfds );
-		FD_SET( tcps, &readfds );
 
 		zero.tv_sec = 0;
 		zero.tv_usec = 0;
 
-		ldap_pvt_thread_mutex_lock( &active_threads_mutex );
-		Debug( LDAP_DEBUG_CONNS,
-		    "listening for connections on %d, activity on:",
-		    tcps, 0, 0 );
-	   
-	   	data_ready = 0;
+		ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
 
-		ldap_pvt_thread_mutex_lock( &new_conn_mutex );
-		for ( i = 0; i < dtblsize; i++ ) {
-			if ( (c[i].c_state != SLAP_C_INACTIVE)  
-				&& (c[i].c_state != SLAP_C_CLOSING) )
-			{
-				assert(lber_pvt_sb_in_use( &c[i].c_sb ));
-
-				FD_SET( lber_pvt_sb_get_desc(&c[i].c_sb),
-					&readfds );
-				if (lber_pvt_sb_data_ready(&c[i].c_sb))
-			     		data_ready = 1;
-				if ( c[i].c_writewaiter ) {
-					FD_SET( lber_pvt_sb_get_desc(&c[i].c_sb),
-						&writefds );
-				}
-				Debug( LDAP_DEBUG_CONNS, " %dr%s", i,
-				    c[i].c_writewaiter ? "w" : "", 0 );
+#ifdef FD_SET_MANUAL_COPY
+		for( s = 0; s < nfds; s++ ) {
+			if(FD_ISSET( &slap_sd_writers, s )) {
+				FD_SET( &writefds, s );
+			}
+			if(FD_ISSET( &slap_sd_writers, s )) {
+				FD_SET( &writefds, s );
 			}
 		}
+#else
+		memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
+		memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
+#endif
 
-		Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
-		ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+		FD_SET( tcps, &readfds );
+
+#ifndef HAVE_WINSOCK
+		nfds = slap_daemon.sd_nfds;
+#else
+		nfds = dtblsize;
+#endif
+
+		ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
 
-		Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
-		    active_threads, 0, 0 );
+		ldap_pvt_thread_mutex_lock( &active_threads_mutex );
 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
-		tvp = (data_ready) ? &zero : NULL;
+		tvp = NULL;
 #else
-		tvp = (active_threads || data_ready) ? &zero : NULL;
+		tvp = active_threads ? &zero : NULL;
 #endif
+
+		Debug( LDAP_DEBUG_CONNS,
+			"daemon: select: tcps=%d active_threads=%d tvp=%s\n",
+		    tcps, active_threads,
+			tvp == NULL ? "NULL" : "zero" );
+	   
+
 		ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
 
-		switch ( i = select( dtblsize, &readfds, &writefds, 0, tvp ) ) {
+		switch(ns = select( nfds, &readfds, &writefds, 0, tvp )) {
 		case -1:	/* failure - try again */
-			Debug( LDAP_DEBUG_CONNS,
-			    "select failed errno %d (%s)\n",
-			    errno, errno > -1 && errno < sys_nerr ?
-			    sys_errlist[errno] : "unknown", 0 );
+			if( errno != EINTR ) {
+				Debug( LDAP_DEBUG_CONNS,
+					"daemon: select failed (%d): %s\n",
+					errno,
+					errno >= 0 && errno < sys_nerr
+						? sys_errlist[errno] : "unknown",
+					0 );
+
+				slapd_shutdown = -1;
+			}
+			errno = 0;
 			continue;
 
 		case 0:		/* timeout - let threads run */
-			Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n",
+			Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
 			    0, 0, 0 );
-		   	if (!data_ready)
-		     		ldap_pvt_thread_yield();
+	     	ldap_pvt_thread_yield();
 			continue;
 
 		default:	/* something happened - deal with it */
-			Debug( LDAP_DEBUG_CONNS, "select activity on %d descriptors\n", i, 0, 0 );
-			;	/* FALL */
+			Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
+				ns, 0, 0 );
+			/* FALL THRU */
 		}
-		ldap_pvt_thread_mutex_lock( &currenttime_mutex );
-		time( &currenttime );
-		ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
 
-		/* new connection */
-		ldap_pvt_thread_mutex_lock( &new_conn_mutex );
+		slap_set_time();
+
 		if ( FD_ISSET( tcps, &readfds ) ) {
-			len = sizeof(from);
-			if ( (ns = accept( tcps, (struct sockaddr *) &from,
-			    &len )) == -1 ) {
+			int s;
+			int len = sizeof(from);
+			long id;
+
+			if ( (s = accept( tcps,
+				(struct sockaddr *) &from, &len )) == -1 )
+			{
 				Debug( LDAP_DEBUG_ANY,
-				    "accept() failed errno %d (%s)", errno,
-				    errno > -1 && errno < sys_nerr ?
-				    sys_errlist[errno] : "unknown", 0 );
-				ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+				    "daemon: accept(%d) failed errno %d (%s)", errno,
+				    tcps, errno >= 0 && errno < sys_nerr ?
+				    sys_errlist[errno] : "unknown");
 				continue;
 			}
 
+			assert( !FD_ISSET( 0, &slap_daemon.sd_actives) );
+			assert( !FD_ISSET( 0, &slap_daemon.sd_readers) );
+			assert( !FD_ISSET( 0, &slap_daemon.sd_writers) );
+
+#ifndef HAVE_WINSOCK
 			/* make sure descriptor number isn't too great */
-			if ( ns >= dtblsize ) {
+			if ( s >= dtblsize ) {
 				Debug( LDAP_DEBUG_ANY,
-					"new connection on %d beyond descriptor table size %d\n",
-					ns, dtblsize, 0 );
-				close(ns);
-				ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+					"daemon: %d beyond descriptor table size %d\n",
+					s, dtblsize, 0 );
+				close(s);
 				continue;
 			}
+#endif
 		   
-			Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
-			    0, 0 );
+			Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %d\n",
+				s, 0, 0 );
 
 			len = sizeof(from);
-
-			if ( getpeername( ns, (struct sockaddr *) &from, &len )
-			    == 0 ) {
-				char *s;
+			if ( getpeername( s, (struct sockaddr *) &from, &len ) == 0 ) {
 				client_addr = inet_ntoa( from.sin_addr );
 
 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
@@ -249,11 +351,12 @@ slapd_daemon(
 				    sizeof(from.sin_addr.s_addr), AF_INET );
 
 				if(hp) {
+					char *p;
 					client_name = hp->h_name;
 
 					/* normalize the domain */
-					for ( s = client_name; *s; s++ ) {
-						*s = TOLOWER( (unsigned char) *s );
+					for ( p = client_name; *p; p++ ) {
+						*p = TOLOWER( (unsigned char) *p );
 					}
 
 				} else {
@@ -277,72 +380,42 @@ slapd_daemon(
 				/* DENY ACCESS */
 				Statslog( LDAP_DEBUG_ANY,
 			   	 "fd=%d connection from %s (%s) denied.\n",
-			   	 	ns,
-						client_name == NULL ? "unknown" : client_name,
-						client_addr == NULL ? "unknown" : client_addr,
+			   	 	s,
+					client_name == NULL ? "unknown" : client_name,
+					client_addr == NULL ? "unknown" : client_addr,
 			   	  0, 0 );
 
-				ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+				close(s);
 				continue;
 			}
 #endif /* HAVE_TCPD */
 
-
-			ldap_pvt_thread_mutex_lock( &ops_mutex );
-			c[ns].c_connid = num_conns++;
-			ldap_pvt_thread_mutex_unlock( &ops_mutex );
-
-			Statslog( LDAP_DEBUG_STATS,
-			    "conn=%d fd=%d connection from %s (%s) accepted.\n",
-			    	c[ns].c_connid, ns,
+			if( (id = connection_init(s, client_name, client_addr)) < 0 ) {
+				Debug( LDAP_DEBUG_ANY,
+					"daemon: connection_init(%d, %s, %s) failed.\n",
+					s,
 					client_name == NULL ? "unknown" : client_name,
-					client_addr == NULL ? "unknown" : client_addr,
-			     0 );
-
-			if ( c[ns].c_addr != NULL ) {
-				free( c[ns].c_addr );
-			}
-			c[ns].c_addr = ch_strdup( client_addr );
-
-			if ( c[ns].c_domain != NULL ) {
-				free( c[ns].c_domain );
-			}
-
-			c[ns].c_domain = ch_strdup( client_name == NULL
-				? "" : client_name );
-
-			ldap_pvt_thread_mutex_lock( &c[ns].c_dnmutex );
-			if ( c[ns].c_dn != NULL ) {
-				free( c[ns].c_dn );
-				c[ns].c_dn = NULL;
-			}
-			if ( c[ns].c_cdn != NULL ) {
-				free( c[ns].c_cdn );
-				c[ns].c_cdn = NULL;
+					client_addr == NULL ? "unknown" : client_addr);
+				close(s);
+				continue;
 			}
-			ldap_pvt_thread_mutex_unlock( &c[ns].c_dnmutex );
 
-			c[ns].c_starttime = currenttime;
-			c[ns].c_ops_received = 0;
-			c[ns].c_ops_executing = 0;
-			c[ns].c_ops_pending = 0;
-			c[ns].c_ops_completed = 0;
-
-			lber_pvt_sb_set_desc( &c[ns].c_sb, ns );
-			lber_pvt_sb_set_io( &c[ns].c_sb, &lber_pvt_sb_io_tcp, NULL );
-		   
-			if (lber_pvt_sb_set_nonblock( &c[ns].c_sb, 1)<0) {			   
-				Debug( LDAP_DEBUG_ANY,
-				    "FIONBIO ioctl on %d failed\n", ns, 0, 0 );
-			}
+			Statslog( LDAP_DEBUG_STATS,
+				"daemon: conn=%d fd=%d connection from %s (%s) accepted.\n",
+				id, s,
+				client_name == NULL ? "unknown" : client_name,
+				client_addr == NULL ? "unknown" : client_addr,
+				0 );
 
-			c[ns].c_state = SLAP_C_ACTIVE;
+			slapd_add( s );
+			continue;
 		}
-		ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
 
-		Debug( LDAP_DEBUG_CONNS, "activity on:", 0, 0, 0 );
-		for ( i = 0; i < dtblsize; i++ ) {
-			int	r, w;
+#ifdef LDAP_DEBUG
+		Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
+
+		for ( i = 0; i < nfds; i++ ) {
+			int	a, r, w;
 
 			r = FD_ISSET( i, &readfds );
 			w = FD_ISSET( i, &writefds );
@@ -351,42 +424,70 @@ slapd_daemon(
 				    r ? "r" : "", w ? "w" : "" );
 			}
 		}
+
 		Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
+#endif
 
-		for ( i = 0; i < dtblsize; i++ ) {
-			if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
-			    ! FD_ISSET( i, &writefds )) ) {
+		/* loop through the writers */
+		for ( i = 0; i < nfds; i++ ) {
+			if ( i == tcps ) {
 				continue;
 			}
 
 			if ( FD_ISSET( i, &writefds ) ) {
 				Debug( LDAP_DEBUG_CONNS,
-				    "signaling write waiter on %d\n", i, 0, 0 );
+				    "daemon: signaling write waiter on %d\n", i, 0, 0 );
+
+				assert( FD_ISSET( 0, &slap_daemon.sd_actives) );
 
-				ldap_pvt_thread_mutex_lock( &active_threads_mutex );
-				active_threads++;
-				c[i].c_writewaiter = 0;
-				ldap_pvt_thread_cond_signal( &c[i].c_wcv );
-				ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
+				/* clear the write flag */
+				slapd_clr_write( i, 0 );
+				
+				if( connection_write( i ) < 0 ) { 
+					FD_CLR( i, &readfds );
+					slapd_close( i );
+				}
+			}
+		}
+
+		for ( i = 0; i < nfds; i++ ) {
+			if ( i == tcps ) {
+				continue;
 			}
 
-			if ( FD_ISSET( i, &readfds ) || 
-				lber_pvt_sb_data_ready( &c[i].c_sb ) ) {
+			if ( FD_ISSET( i, &readfds ) ) {
 				Debug( LDAP_DEBUG_CONNS,
-				    "read activity on %d\n", i, 0, 0 );
+				    "daemon: read activity on %d\n", i, 0, 0 );
+
+				assert( FD_ISSET( i, &slap_daemon.sd_actives) );
 
-				connection_activity( &c[i] );
+				if( connection_read( i ) < 0) {
+					slapd_close( i );
+				}
 			}
 		}
 
 		ldap_pvt_thread_yield();
 	}
 
-	Debug( LDAP_DEBUG_TRACE,
-	    "slapd shutdown: shutdown initiated.\n",
-	    0, 0, 0 );
+	if( slapd_shutdown > 0 ) {
+		Debug( LDAP_DEBUG_TRACE,
+			"daemon: shutdown requested and initiated.\n",
+			0, 0, 0 );
+
+	} else if ( slapd_shutdown < 0 ) {
+		Debug( LDAP_DEBUG_TRACE,
+			"daemon: abnormal condition, shutdown initiated.\n",
+			0, 0, 0 );
+	} else {
+		Debug( LDAP_DEBUG_TRACE,
+			"daemon: no active streams, shutdown initiated.\n",
+			0, 0, 0 );
+	}
 
-	close( tcps );
+	if( tcps >= 0 ) {
+		close( tcps );
+	}
 
 	ldap_pvt_thread_mutex_lock( &active_threads_mutex );
 	Debug( LDAP_DEBUG_ANY,
@@ -400,10 +501,28 @@ slapd_daemon(
 	return NULL;
 }
 
+int slapd_daemon( struct sockaddr_in *addr )
+{
+	int status;
+
+	status = ldap_pvt_thread_create( &listener_tid, 0,
+		 slapd_daemon_task, addr );
+
+	if ( status != 0 ) {
+		Debug( LDAP_DEBUG_ANY,
+		    "listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
+		return -1;
+	} else {
+		/* wait for the listener thread to complete */
+		ldap_pvt_thread_join( listener_tid, (void *) NULL );
+	}
+
+	return 0;
+}
+
 void
 slap_set_shutdown( int sig )
 {
-	Debug( LDAP_DEBUG_ANY, "slapd got shutdown signal %d\n", sig, 0, 0 );
 	slapd_shutdown = 1;
 	ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
 
@@ -414,8 +533,6 @@ slap_set_shutdown( int sig )
 void
 slap_do_nothing( int sig )
 {
-	Debug( LDAP_DEBUG_TRACE, "slapd got do_nothing signal %d\n", sig, 0, 0 );
-
 	/* reinstall self */
 	(void) SIGNAL( sig, slap_do_nothing );
 }
diff --git a/servers/slapd/init.c b/servers/slapd/init.c
index dca72737b5b6b507eb64a1fa02ae9f7fa9b490a4..f464c61e93d0c483dfea2f551a2e4e9941aef734 100644
--- a/servers/slapd/init.c
+++ b/servers/slapd/init.c
@@ -8,7 +8,6 @@
 #include <ac/string.h>
 #include <ac/time.h>
 
-#include "portable.h"
 #include "slap.h"
 
 /*
@@ -25,8 +24,6 @@ int		ldap_syslog;
 
 int		ldap_syslog_level = LOG_DEBUG;
 char		*default_referral;
-time_t		starttime;
-ldap_pvt_thread_t	listener_tid;
 int		g_argc;
 char		**g_argv;
 
@@ -37,11 +34,7 @@ int				active_threads;
 ldap_pvt_thread_mutex_t	active_threads_mutex;
 ldap_pvt_thread_cond_t	active_threads_cond;
 
-time_t			currenttime;
-ldap_pvt_thread_mutex_t	currenttime_mutex;
-
-ldap_pvt_thread_mutex_t	new_conn_mutex;
-
+ldap_pvt_thread_mutex_t	gmtime_mutex;
 #ifdef SLAPD_CRYPT
 ldap_pvt_thread_mutex_t	crypt_mutex;
 #endif
@@ -64,6 +57,9 @@ ldap_pvt_thread_mutex_t	replog_mutex;
 static char* slap_name;
 int slapMode = SLAP_UNDEFINED_MODE;
 
+static time_t			currenttime;
+static ldap_pvt_thread_mutex_t	currenttime_mutex;
+
 int
 slap_init( int mode, char *name )
 {
@@ -98,12 +94,13 @@ slap_init( int mode, char *name )
 			ldap_pvt_thread_mutex_init( &active_threads_mutex );
 			ldap_pvt_thread_cond_init( &active_threads_cond );
 
-			ldap_pvt_thread_mutex_init( &new_conn_mutex );
 			ldap_pvt_thread_mutex_init( &currenttime_mutex );
 			ldap_pvt_thread_mutex_init( &entry2str_mutex );
 			ldap_pvt_thread_mutex_init( &replog_mutex );
 			ldap_pvt_thread_mutex_init( &ops_mutex );
 			ldap_pvt_thread_mutex_init( &num_sent_mutex );
+
+			ldap_pvt_thread_mutex_init( &gmtime_mutex );
 #ifdef SLAPD_CRYPT
 			ldap_pvt_thread_mutex_init( &crypt_mutex );
 #endif
@@ -162,3 +159,20 @@ int slap_destroy(void)
 	return rc;
 }
 
+/* should create a utils.c for these */
+
+void slap_set_time(void)
+{
+	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
+	time( &currenttime );
+	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+}
+
+time_t slap_get_time(void)
+{
+	time_t t;
+	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
+	t = currenttime;
+	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+	return t;
+}
diff --git a/servers/slapd/main.c b/servers/slapd/main.c
index f7b446939072e727445bbd64dc8de1ab8cce477b..5cbe8101933410927a19947aea20e1c2239a3001 100644
--- a/servers/slapd/main.c
+++ b/servers/slapd/main.c
@@ -56,13 +56,15 @@ usage( char *name )
     fprintf( stderr, "\n" );
 }
 
+time_t starttime;
+
 int
 main( int argc, char **argv )
 {
 	int		i;
 	int		inetd = 0;
-	int		rc = 0;
-	struct sockaddr_in	bind_addr;
+	int		status, rc;
+	struct sockaddr_in	bind_addr, *slapd_addr;
 	int		udp;
 #ifdef LOG_LOCAL4
     int     syslogUser = DEFAULT_SYSLOG_USER;
@@ -207,130 +209,61 @@ main( int argc, char **argv )
 		goto destroy;
 	}
 
-	if ( slap_startup(-1)  != 0 ) {
-		rc = 1;
-		goto shutdown;
-	}
-
-	if ( ! inetd ) {
-		int		status;
-
-		(void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
-		(void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
+	(void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
+	(void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
 #ifdef SIGPIPE
-		(void) SIGNAL( SIGPIPE, SIG_IGN );
+	(void) SIGNAL( SIGPIPE, SIG_IGN );
 #endif
 #ifdef SIGHUP
-		(void) SIGNAL( SIGHUP, slap_set_shutdown );
+	(void) SIGNAL( SIGHUP, slap_set_shutdown );
 #endif
-		(void) SIGNAL( SIGINT, slap_set_shutdown );
-		(void) SIGNAL( SIGTERM, slap_set_shutdown );
+	(void) SIGNAL( SIGINT, slap_set_shutdown );
+	(void) SIGNAL( SIGTERM, slap_set_shutdown );
 
+	if(!inetd) {
 #ifdef LDAP_DEBUG
 		lutil_detach( ldap_debug, 0 );
 #else
 		lutil_detach( 0, 0 );
 #endif
+	}
 
-		time( &starttime );
+	if ( slap_startup(-1)  != 0 ) {
+		rc = 1;
+		goto shutdown;
+	}
 
-		status = ldap_pvt_thread_create( &listener_tid, 0,
-						 slapd_daemon, &bind_addr );
-		if ( status != 0 )
-		{
-			Debug( LDAP_DEBUG_ANY,
-			    "listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
+	if(!inetd) {
+		FILE *fp;
 
-			rc = 1;
+		slapd_addr = &bind_addr;
 
-		} else {
-			/* wait for the listener thread to complete */
-			ldap_pvt_thread_join( listener_tid, (void *) NULL );
-		}
+		Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
 
-	} else {
-		Connection		c;
-		BerElement		ber;
-		unsigned long		len, tag;
-		long			msgid;
-		int			flen;
-		struct sockaddr_in	from;
-		struct hostent		*hp;
-
-		c.c_dn = NULL;
-		c.c_cdn = NULL;
-		c.c_ops = NULL;
-	   
-		lber_pvt_sb_init( &c.c_sb );
-		lber_pvt_sb_set_desc( &c.c_sb, 0 );
-		lber_pvt_sb_set_io( &c.c_sb, 
-			(udp) ? &lber_pvt_sb_io_udp : &lber_pvt_sb_io_tcp, 
-			NULL );
-	   	/* FIXME: handle udp here */
-
-		ldap_pvt_thread_mutex_init( &c.c_dnmutex );
-		ldap_pvt_thread_mutex_init( &c.c_opsmutex );
-		ldap_pvt_thread_mutex_init( &c.c_pdumutex );
-#ifdef notdefcldap
-		c.c_sb.sb_addrs = (void **) saddrlist;
-		c.c_sb.sb_fromaddr = &faddr;
-		c.c_sb.sb_useaddr = saddrlist[ 0 ] = &saddr;
-#endif
-		flen = sizeof(from);
-		if ( getpeername( 0, (struct sockaddr *) &from, &flen ) == 0 ) {
-#ifdef SLAPD_RLOOKUPS
-			hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
-			    sizeof(from.sin_addr.s_addr), AF_INET );
-#else
-			hp = NULL;
-#endif
-
-			Debug( LDAP_DEBUG_ARGS, "connection from %s (%s)\n",
-			    hp == NULL ? "unknown" : hp->h_name,
-			    inet_ntoa( from.sin_addr ), 0 );
-
-			c.c_addr = inet_ntoa( from.sin_addr );
-			c.c_domain = ch_strdup( hp == NULL ? "" : hp->h_name );
-		} else {
-			Debug( LDAP_DEBUG_ARGS, "connection from unknown\n",
-			    0, 0, 0 );
+		if (( slapd_pid_file != NULL ) &&
+			(( fp = fopen( slapd_pid_file, "w" )) != NULL ))
+		{
+			fprintf( fp, "%d\n", (int) getpid() );
+			fclose( fp );
 		}
 
-		c.c_state = SLAP_C_ACTIVE;
-
-		ber_init_w_nullc( &ber, 0 );
-
-		while ( (tag = ber_get_next( &c.c_sb, &len, &ber ))
-		    == LDAP_TAG_MESSAGE ) {
-			ldap_pvt_thread_mutex_lock( &currenttime_mutex );
-			time( &currenttime );
-			ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
-
-			if ( (tag = ber_get_int( &ber, &msgid ))
-			    != LDAP_TAG_MSGID ) {
-				/* log and send error */
-				Debug( LDAP_DEBUG_ANY,
-				   "ber_get_int returns 0x%lx\n", tag, 0, 0 );
-				ber_free( &ber, 1 );
-				return 1;
+		if (( slapd_args_file != NULL ) &&
+			(( fp = fopen( slapd_args_file, "w" )) != NULL ))
+		{
+			for ( i = 0; i < g_argc; i++ ) {
+				fprintf( fp, "%s ", g_argv[i] );
 			}
+			fprintf( fp, "\n" );
+			fclose( fp );
+		}
 
-			if ( (tag = ber_peek_tag( &ber, &len ))
-			    == LBER_ERROR ) {
-				/* log, close and send error */
-				Debug( LDAP_DEBUG_ANY,
-				   "ber_peek_tag returns 0x%lx\n", tag, 0, 0 );
-				ber_free( &ber, 1 );
-			   	lber_pvt_sb_close( &c.c_sb );
-			   	lber_pvt_sb_destroy( &c.c_sb );
-				return 1;
-			}
+	} else {
+		slapd_addr = NULL;
+	}
 
-			connection_activity( &c );
+	time( &starttime );
 
-			ber_free( &ber, 1 );
-		}
-	}
+	rc = slapd_daemon( slapd_addr );
 
 shutdown:
 	/* remember an error during shutdown */
diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c
index 918c97a2787ab2a3b6752f1173bf3c4e7476da37..c3b5fc9cc84629c5d1f6961ddbb5bd2a8f45c56f 100644
--- a/servers/slapd/modify.c
+++ b/servers/slapd/modify.c
@@ -206,6 +206,7 @@ add_lastmods( Operation *op, LDAPModList **modlist )
 	LDAPModList		**m;
 	LDAPModList		*tmp;
 	struct tm	*ltm;
+	time_t		currenttime;
 
 	Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
 
@@ -249,7 +250,8 @@ add_lastmods( Operation *op, LDAPModList **modlist )
 	tmp->ml_next = *modlist;
 	*modlist = tmp;
 
-	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
+	currenttime = slap_get_time();
+	ldap_pvt_thread_mutex_lock( &gmtime_mutex );
 #ifndef LDAP_LOCALTIME
 	ltm = gmtime( &currenttime );
 	strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@@ -257,7 +259,8 @@ add_lastmods( Operation *op, LDAPModList **modlist )
 	ltm = localtime( &currenttime );
 	strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
 #endif
-	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+	ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
 	bv.bv_val = buf;
 	bv.bv_len = strlen( bv.bv_val );
 	tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
diff --git a/servers/slapd/monitor.c b/servers/slapd/monitor.c
index 5554d81c3db567b8f479abf007f539a08f911ca0..65594af1833076b6533f1125c4047d8c1fd08a19 100644
--- a/servers/slapd/monitor.c
+++ b/servers/slapd/monitor.c
@@ -10,13 +10,6 @@
  * is provided ``as is'' without express or implied warranty.
  */
 
-/* Revision history
- *
- * 5-Jun-96	jeff.hodges@stanford.edu
- *	Added locking of new_conn_mutex when traversing the c[] array.
- *	Added locking of currenttime_mutex to protect call(s) to localtime().
- */
-
 #include "portable.h"
 
 #include <stdio.h>
@@ -40,6 +33,8 @@ monitor_info( Connection *conn, Operation *op )
 	int		i, nconns, nwritewaiters, nreadwaiters;
 	struct tm	*ltm;
 	char		*p;
+	Connection *c;
+	time_t		currenttime;
 
 	vals[0] = &val;
 	vals[1] = NULL;
@@ -59,7 +54,9 @@ monitor_info( Connection *conn, Operation *op )
 	}
 	attr_merge( e, "version", vals );
 
+	ldap_pvt_thread_mutex_lock( &active_threads_mutex );
 	sprintf( buf, "%d", active_threads );
+	ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attr_merge( e, "threads", vals );
@@ -68,49 +65,49 @@ monitor_info( Connection *conn, Operation *op )
 	nwritewaiters = 0;
 	nreadwaiters = 0;
 
-	ldap_pvt_thread_mutex_lock( &new_conn_mutex );
-	for ( i = 0; i < dtblsize; i++ ) {
-		if ( lber_pvt_sb_in_use(&(c[i].c_sb)) ) {
-			nconns++;
-			if ( c[i].c_writewaiter ) {
-				nwritewaiters++;
-			}
-			if ( c[i].c_gettingber ) {
-				nreadwaiters++;
-			}
-			ldap_pvt_thread_mutex_lock( &currenttime_mutex );
+#ifdef LDAP_COUNTERS
+	/* loop through the connections */
+	for ( c = connection_first() ; c != NULL;  c = connection_next(c) ) {
+		nconns++;
+		if ( c->c_writewaiter ) {
+			nwritewaiters++;
+		}
+		if ( c->c_currentber != NULL ) {
+			nreadwaiters++;
+		}
+
+		ldap_pvt_thread_mutex_lock( &gmtime_mutex );
 #ifndef LDAP_LOCALTIME
-			ltm = gmtime( &c[i].c_starttime );
-			strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
+		ltm = gmtime( &c->c_starttime );
+		strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
 #else
-			ltm = localtime( &c[i].c_starttime );
-			strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
+		ltm = localtime( &c->.c_starttime );
+		strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
 #endif
-			ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
-
-			ldap_pvt_thread_mutex_lock( &c[i].c_dnmutex );
-			sprintf( buf, "%d : %s : %d : %d : %s : %s%s%s%s", i,
-			    buf2, c[i].c_ops_received, c[i].c_ops_completed,
-			    c[i].c_cdn ? c[i].c_cdn : "NULLDN",
-			    c[i].c_gettingber ? "r" : "",
-			    c[i].c_writewaiter ? "w" : "",
-			    c[i].c_ops_executing ? "x" : "",
-			    c[i].c_ops_pending ? "p" : ""
-			);
-			ldap_pvt_thread_mutex_unlock( &c[i].c_dnmutex );
-			val.bv_val = buf;
-			val.bv_len = strlen( buf );
-			attr_merge( e, "connection", vals );
-		}
+		ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
+		sprintf( buf, "%d : %s : %d : %d : %s : %s%s%s%s", i,
+		    buf2, c[i].c_ops_received, c[i].c_ops_completed,
+		    c[i].c_cdn ? c[i].c_cdn : "NULLDN",
+		    c[i].c_gettingber ? "r" : "",
+		    c[i].c_writewaiter ? "w" : "",
+		    c[i].c_ops_executing ? "x" : "",
+		    c[i].c_ops_pending ? "p" : ""
+		);
+
+		val.bv_val = buf;
+		val.bv_len = strlen( buf );
+		attr_merge( e, "connection", vals );
 	}
-	ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+	connection_done(c);
+#endif
 
 	sprintf( buf, "%d", nconns );
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attr_merge( e, "currentconnections", vals );
 
-	sprintf( buf, "%d", num_conns );
+	sprintf( buf, "%ld", connections_nextid() );
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attr_merge( e, "totalconnections", vals );
@@ -130,6 +127,7 @@ monitor_info( Connection *conn, Operation *op )
 	val.bv_len = strlen( buf );
 	attr_merge( e, "readwaiters", vals );
 
+#ifdef LDAP_COUNTERS
 	sprintf( buf, "%ld", ops_initiated );
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
@@ -149,8 +147,12 @@ monitor_info( Connection *conn, Operation *op )
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attr_merge( e, "bytessent", vals );
+#endif
 
-	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
+	slap_set_time();
+	currenttime = slap_get_time();
+
+	ldap_pvt_thread_mutex_lock( &gmtime_mutex );
 #ifndef LDAP_LOCALTIME
 	ltm = gmtime( &currenttime );
 	strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@@ -158,12 +160,10 @@ monitor_info( Connection *conn, Operation *op )
 	ltm = localtime( &currenttime );
 	strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
 #endif
-	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attr_merge( e, "currenttime", vals );
 
-	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
 #ifndef LDAP_LOCALTIME
 	ltm = gmtime( &starttime );
 	strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
@@ -171,7 +171,8 @@ monitor_info( Connection *conn, Operation *op )
 	ltm = localtime( &starttime );
 	strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
 #endif
-	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+	ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
+
 	val.bv_val = buf;
 	val.bv_len = strlen( buf );
 	attr_merge( e, "starttime", vals );
diff --git a/servers/slapd/operation.c b/servers/slapd/operation.c
index 7848357a935b8c7639437ff75346c3117a07f99e..44c821845ecbde47745c3dafbba682c736fcdae5 100644
--- a/servers/slapd/operation.c
+++ b/servers/slapd/operation.c
@@ -15,8 +15,6 @@ slap_op_free( Operation *op )
 {
 	assert( op->o_next == NULL );
 
-	ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
-
 	if ( op->o_ber != NULL ) {
 		ber_free( op->o_ber, 1 );
 	}
@@ -27,8 +25,8 @@ slap_op_free( Operation *op )
 		free( op->o_ndn );
 	}
 
-	ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
 	ldap_pvt_thread_mutex_destroy( &op->o_abandonmutex );
+
 	free( (char *) op );
 }
 
@@ -37,8 +35,7 @@ slap_op_alloc(
     BerElement		*ber,
     unsigned long	msgid,
     unsigned long	tag,
-    int				id,
-    int				connid
+    long			id
 )
 {
 	Operation	*op;
@@ -46,19 +43,17 @@ slap_op_alloc(
 	op = (Operation *) ch_calloc( 1, sizeof(Operation) );
 
 	ldap_pvt_thread_mutex_init( &op->o_abandonmutex );
+	op->o_abandon = 0;
+
 	op->o_ber = ber;
 	op->o_msgid = msgid;
 	op->o_tag = tag;
-	op->o_abandon = 0;
 
 	op->o_dn = NULL;
 	op->o_ndn = NULL;
 
-	ldap_pvt_thread_mutex_lock( &currenttime_mutex );
-	op->o_time = currenttime;
-	ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
+	op->o_time = slap_get_time();
 	op->o_opid = id;
-	op->o_connid = connid;
 	op->o_next = NULL;
 
 	return( op );
diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h
index 18fd25614be9f8ed5ab61a4a684daf76b137cbf2..e2876c74d7e55f5cb08f9f2a0567815ce66cd5d5 100644
--- a/servers/slapd/proto-slap.h
+++ b/servers/slapd/proto-slap.h
@@ -109,8 +109,20 @@ int read_config LDAP_P(( char *fname ));
 /*
  * connection.c
  */
+int connections_init LDAP_P((void));
 
-void connection_activity LDAP_P(( Connection *conn ));
+long connection_init LDAP_P((
+	int s,
+	const char* name, const char* addr));
+
+int connection_write LDAP_P((int s));
+int connection_read LDAP_P((int s));
+
+long connections_nextid(void);
+
+Connection* connection_first LDAP_P((void));
+Connection* connection_next LDAP_P((Connection *));
+void connection_done LDAP_P((Connection *));
 
 /*
  * dn.c
@@ -173,7 +185,7 @@ void monitor_info LDAP_P(( Connection *conn, Operation *op ));
 void slap_op_free LDAP_P(( Operation *op ));
 Operation * slap_op_alloc LDAP_P((
 	BerElement *ber, unsigned long msgid,
-	unsigned long tag, int id, int connid ));
+	unsigned long tag, long id ));
 
 int slap_op_add LDAP_P(( Operation **olist, Operation *op ));
 int slap_op_remove LDAP_P(( Operation **olist, Operation *op ));
@@ -202,7 +214,8 @@ void send_ldap_result LDAP_P(( Connection *conn, Operation *op, int err, char *m
 	char *text ));
 void send_ldap_search_result LDAP_P(( Connection *conn, Operation *op, int err,
 	char *matched, char *text, int nentries ));
-void close_connection LDAP_P(( Connection *conn, int opconnid, int opid ));
+
+void do_close( Connection *conn, long opid );
 
 /*
  * schema.c
@@ -244,7 +257,6 @@ char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be ));
  * Other...
  */
 
-extern char		**g_argv;
 extern char		*default_referral;
 extern char		*replogfile;
 extern char		Versionstr[];
@@ -257,35 +269,48 @@ extern int		global_lastmod;
 extern int		global_schemacheck;
 extern int		lber_debug;
 extern int		ldap_syslog;
-extern int		num_conns;
+
+#ifdef LDAP_COUNTERS
+extern ldap_pvt_thread_mutex_t	num_sent_mutex;
 extern long		num_bytes_sent;
+
 extern long		num_entries_sent;
+
+extern ldap_pvt_thread_mutex_t	ops_mutex;
 extern long		ops_completed;
 extern long		ops_initiated;
+#endif
+
+extern char   *slapd_pid_file;
+extern char   *slapd_args_file;
+extern char		**g_argv;
+extern time_t	starttime;
+
+time_t slap_get_time LDAP_P((void));
+void slap_set_time LDAP_P((void));
 
 extern ldap_pvt_thread_mutex_t	active_threads_mutex;
 extern ldap_pvt_thread_cond_t	active_threads_cond;
 
-extern ldap_pvt_thread_mutex_t	currenttime_mutex;
 extern ldap_pvt_thread_mutex_t	entry2str_mutex;
-extern ldap_pvt_thread_mutex_t	new_conn_mutex;
-extern ldap_pvt_thread_mutex_t	num_sent_mutex;
-extern ldap_pvt_thread_mutex_t	ops_mutex;
 extern ldap_pvt_thread_mutex_t	replog_mutex;
+
 #ifdef SLAPD_CRYPT
 extern ldap_pvt_thread_mutex_t	crypt_mutex;
 #endif
-extern ldap_pvt_thread_t	listener_tid;
+extern ldap_pvt_thread_mutex_t	gmtime_mutex;
+
 extern struct acl	*global_acl;
 extern struct objclass	*global_oc;
-extern time_t		currenttime;
 
 extern int	slap_init LDAP_P((int mode, char* name));
 extern int	slap_startup LDAP_P((int dbnum));
 extern int	slap_shutdown LDAP_P((int dbnum));
 extern int	slap_destroy LDAP_P((void));
 
-extern void * slapd_daemon LDAP_P((void *port));
+struct sockaddr_in;
+extern int slapd_daemon LDAP_P((struct sockaddr_in *addr));
+
 extern void	slap_set_shutdown LDAP_P((int sig));
 extern void	slap_do_nothing   LDAP_P((int sig));
 
@@ -303,11 +328,7 @@ extern void	do_unbind LDAP_P((Connection *conn, Operation *op));
 extern int send_search_entry LDAP_P((Backend *be, Connection *conn, Operation *op, Entry *e, char **attrs, int attrsonly));
 extern int str2result LDAP_P(( char *s, int *code, char **matched, char **info ));
 
-#if defined( SLAPD_MONITOR_DN )
-extern Connection	*c;
-extern int		dtblsize;
-extern time_t		starttime;
-#endif
+extern int dtblsize;
 
 #endif /* _proto_slap */
 
diff --git a/servers/slapd/repl.c b/servers/slapd/repl.c
index 773687a3d2f8771586a084003d5ffc47e5ae1ac7..f0e79084ad9594d703cbfa51d777c4e7542d23e3 100644
--- a/servers/slapd/repl.c
+++ b/servers/slapd/repl.c
@@ -46,7 +46,7 @@ replog(
 	    i++ ) {
 		fprintf( fp, "replica: %s\n", be->be_replica[i] );
 	}
-	fprintf( fp, "time: %ld\n", (long) currenttime );
+	fprintf( fp, "time: %ld\n", (long) slap_get_time() );
 	fprintf( fp, "dn: %s\n", dn );
 
 	switch ( optype ) {
diff --git a/servers/slapd/result.c b/servers/slapd/result.c
index 6d30c29b6d6ee054f4af4bed8534f39eba0a8fba..152af69f7f8648d219b6d474428f95a87bb16a68 100644
--- a/servers/slapd/result.c
+++ b/servers/slapd/result.c
@@ -13,7 +13,6 @@
 
 #include "slap.h"
 
-
 static void
 send_ldap_result2(
     Connection	*conn,
@@ -25,7 +24,7 @@ send_ldap_result2(
 )
 {
 	BerElement	*ber;
-	int		rc;
+	int		rc, tmp;
 	unsigned long	tag, bytes;
 
 	if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') )
@@ -52,12 +51,14 @@ send_ldap_result2(
 		break;
 	}
 
+
 #ifdef LDAP_COMPAT30
 	if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
-	    == NULLBER ) {
+	    == NULLBER )
 #else
-	if ( (ber = der_alloc()) == NULLBER ) {
+	if ( (ber = der_alloc()) == NULLBER )
 #endif
+	{
 		Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
 		return;
 	}
@@ -83,14 +84,15 @@ send_ldap_result2(
 	}
 
 	/* write only one pdu at a time - wait til it's our turn */
-	ldap_pvt_thread_mutex_lock( &conn->c_pdumutex );
+	ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
+
+	/* lock the connection */
+	ldap_pvt_thread_mutex_lock( &conn->c_mutex );
 
 	/* write the pdu */
 	bytes = ber->ber_ptr - ber->ber_buf;
-	ldap_pvt_thread_mutex_lock( &new_conn_mutex );
-	while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
-	    1 ) != 0 ) {
-		ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+
+	while ( ber_flush( &conn->c_sb, ber, 1 ) != 0 ) {
 		/*
 		 * we got an error.  if it's ewouldblock, we need to
 		 * wait on the socket being writable.  otherwise, figure
@@ -102,35 +104,29 @@ send_ldap_result2(
 		    : "unknown", 0 );
 
 		if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
-			close_connection( conn, op->o_connid, op->o_opid );
+			conn->c_conn_state = SLAP_C_CLOSING;
 
-			ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
+			ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+			ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 			return;
 		}
 
 		/* wait for socket to be write-ready */
-		ldap_pvt_thread_mutex_lock( &active_threads_mutex );
-		active_threads--;
 		conn->c_writewaiter = 1;
+		slapd_set_write( conn->c_sb.sb_sd, 1 );
 
-		ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
-
-		ldap_pvt_thread_cond_wait( &conn->c_wcv, &active_threads_mutex );
-
-		if( active_threads < 1 ) {
-			ldap_pvt_thread_cond_signal(&active_threads_cond);
-		}
-		ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
-
-		ldap_pvt_thread_yield();
-		ldap_pvt_thread_mutex_lock( &new_conn_mutex );
+		ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
+		conn->c_writewaiter = 0;
 	}
-	ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
-	ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
 
+	ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+	ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+
+#ifdef LDAP_COUNTERS
 	ldap_pvt_thread_mutex_lock( &num_sent_mutex );
 	num_bytes_sent += bytes;
 	ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
+#endif
 
 	Statslog( LDAP_DEBUG_STATS,
 	    "conn=%d op=%d RESULT err=%d tag=%lu nentries=%d\n", conn->c_connid,
@@ -186,7 +182,7 @@ send_search_entry(
 {
 	BerElement	*ber;
 	Attribute	*a;
-	int		i, rc, bytes;
+	int		i, rc=-1, bytes;
 	struct acl	*acl;
 	char            *edn;
 
@@ -261,7 +257,7 @@ send_search_entry(
 			continue;
 		}
 
-		if ( ber_printf( ber, "{s[", a->a_type ) == -1 ) {
+		if (( rc = ber_printf( ber, "{s[", a->a_type )) == -1 ) {
 			Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
 			ber_free( ber, 1 );
 			send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
@@ -278,9 +274,9 @@ send_search_entry(
 					continue;
 				}
 
-				if ( ber_printf( ber, "o",
+				if (( rc = ber_printf( ber, "o",
 				    a->a_vals[i]->bv_val,
-				    a->a_vals[i]->bv_len ) == -1 )
+				    a->a_vals[i]->bv_len )) == -1 )
 				{
 					Debug( LDAP_DEBUG_ANY,
 					    "ber_printf failed\n", 0, 0, 0 );
@@ -293,7 +289,7 @@ send_search_entry(
 			}
 		}
 
-		if ( ber_printf( ber, "]}" ) == -1 ) {
+		if (( rc = ber_printf( ber, "]}" )) == -1 ) {
 			Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
 			ber_free( ber, 1 );
 			send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
@@ -317,14 +313,16 @@ send_search_entry(
 		return( 1 );
 	}
 
+	bytes = ber->ber_ptr - ber->ber_buf;
+
 	/* write only one pdu at a time - wait til it's our turn */
-	ldap_pvt_thread_mutex_lock( &conn->c_pdumutex );
+	ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
 
-	bytes = ber->ber_ptr - ber->ber_buf;
-	ldap_pvt_thread_mutex_lock( &new_conn_mutex );
-	while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
-	    1 ) != 0 ) {
-		ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+	/* lock the connection */ 
+	ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+
+	/* write the pdu */
+	while ( ber_flush( &conn->c_sb, ber, 1 ) != 0 ) {
 		/*
 		 * we got an error.  if it's ewouldblock, we need to
 		 * wait on the socket being writable.  otherwise, figure
@@ -336,51 +334,40 @@ send_search_entry(
 		    : "unknown", 0 );
 
 		if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
-			close_connection( conn, op->o_connid, op->o_opid );
+			conn->c_conn_state = SLAP_C_CLOSING;
 
-			ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
+			ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+			ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
 			return( -1 );
 		}
 
 		/* wait for socket to be write-ready */
-		ldap_pvt_thread_mutex_lock( &active_threads_mutex );
-		active_threads--;
 		conn->c_writewaiter = 1;
-		ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
-		ldap_pvt_thread_cond_wait( &conn->c_wcv, &active_threads_mutex );
-
-		if( active_threads < 1 ) {
-			ldap_pvt_thread_cond_signal(&active_threads_cond);
-		}
-		ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
+		slapd_set_write( conn->c_sb.sb_sd, 1 );
 
-		ldap_pvt_thread_yield();
-		ldap_pvt_thread_mutex_lock( &new_conn_mutex );
+		ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
+		conn->c_writewaiter = 0;
 	}
-	ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
-	ldap_pvt_thread_mutex_unlock( &conn->c_pdumutex );
 
+	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+	ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+
+#ifdef LDAP_COUNTERS
 	ldap_pvt_thread_mutex_lock( &num_sent_mutex );
 	num_bytes_sent += bytes;
 	num_entries_sent++;
 	ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
+#endif
 
-	ldap_pvt_thread_mutex_lock( &new_conn_mutex );
-	if ( conn->c_connid == op->o_connid ) {
-		rc = 0;
-		Statslog( LDAP_DEBUG_STATS2, "conn=%d op=%d ENTRY dn=\"%s\"\n",
-		    conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
-	} else {
-		rc = -1;
-	}
-	ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
+	Statslog( LDAP_DEBUG_STATS2, "conn=%d op=%d ENTRY dn=\"%s\"\n",
+	    conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
 
 	Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
 
-	return( rc );
+	rc = 0;
 
 error_return:;
-	return( 1 );
+	return( rc );
 }
 
 int
@@ -436,26 +423,3 @@ str2result(
 
 	return( rc );
 }
-
-/*
- * close_connection - close a connection. takes the connection to close,
- * the connid associated with the operation generating the close (so we
- * don't accidentally close a connection that's not ours), and the opid
- * of the operation generating the close (for logging purposes).
- */
-void
-close_connection( Connection *conn, int opconnid, int opid )
-{
-	ldap_pvt_thread_mutex_lock( &new_conn_mutex );
-	if ( lber_pvt_sb_in_use(&conn->c_sb) && conn->c_connid == opconnid ) {
-		Statslog( LDAP_DEBUG_STATS,
-		    "conn=%d op=%d fd=%d closed errno=%d\n", conn->c_connid,
-		    opid, lber_pvt_sb_get_desc(&conn->c_sb), errno, 0 );
-	   	lber_pvt_sb_close( &conn->c_sb );
-	   	lber_pvt_sb_destroy( &conn->c_sb );
-		conn->c_version = 0;
-		conn->c_protocol = 0;
-		conn->c_state = SLAP_C_INACTIVE;
-	}
-	ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
-}
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 837de9025b67a202f61e37aa0089117be78b14f3..dabf8c7bec159ad75ea5fe168e462bdab9e2c979 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -380,27 +380,33 @@ struct backend_info {
  */
 
 typedef struct slap_op {
+	long	o_opid;		/* id of this operation		  */
+	long	o_msgid;	/* msgid of the request		  */
+
+	ldap_pvt_thread_t	o_tid;		/* thread handling this op	  */
+
 	BerElement	*o_ber;		/* ber of the request		  */
-	long		o_msgid;	/* msgid of the request		  */
+
 	unsigned long	o_tag;		/* tag of the request		  */
 	time_t		o_time;		/* time op was initiated	  */
 	char		*o_dn;		/* dn bound when op was initiated */
 	char		*o_ndn;		/* normalized dn bound when op was initiated */
-	int		o_authtype;	/* auth method used to bind dn	  */
+	int			o_authtype;	/* auth method used to bind dn	  */
 					/* values taken from ldap.h	  */
 					/* LDAP_AUTH_*			  */
-	int		o_opid;		/* id of this operation		  */
-	int		o_connid;	/* id of conn initiating this op  */
+
+/*	 long	o_connid;	*//* id of conn initiating this op  */
+
 #ifdef LDAP_CONNECTIONLESS
 	int		o_cldap;	/* != 0 if this came in via CLDAP */
 	struct sockaddr	o_clientaddr;	/* client address if via CLDAP	  */
 	char		o_searchbase;	/* search base if via CLDAP	  */
 #endif
-	struct slap_op	*o_next;	/* next operation in list	  */
-	ldap_pvt_thread_t	o_tid;		/* thread handling this op	  */
-	int		o_abandon;	/* signals op has been abandoned  */
-	ldap_pvt_thread_mutex_t	o_abandonmutex;	/* signals op has been abandoned  */
 
+	ldap_pvt_thread_mutex_t	o_abandonmutex; /* protects o_abandon  */
+	int		o_abandon;	/* abandon flag */
+
+	struct slap_op	*o_next;	/* next operation in list	  */
 	void	*o_private;	/* anything the backend needs	  */
 } Operation;
 
@@ -408,41 +414,56 @@ typedef struct slap_op {
  * represents a connection from an ldap client
  */
 
-#define SLAP_C_INACTIVE	0x0
-#define SLAP_C_ACTIVE	0x1
-#define SLAP_C_BINDING	0x2
-#define SLAP_C_CLOSING	0x3
+ 
+/* structure state (protected by connections_mutex) */
+#define SLAP_C_UNINITIALIZED	0x0	/* MUST BE ZERO (0) */
+#define SLAP_C_UNUSED			0x1
+#define SLAP_C_USED				0x2
+
+/* connection state (protected by c_mutex ) */
+#define SLAP_C_INVALID			0x0	/* MUST BE ZERO (0) */
+#define SLAP_C_INACTIVE			0x1	/* zero threads */
+#define SLAP_C_ACTIVE			0x2 /* one or more threads */
+#define SLAP_C_BINDING			0x3	/* binding */
+#define SLAP_C_CLOSING			0x4	/* closing */
 
 typedef struct slap_conn {
-	int			c_state;	/* connection state */
+	int			c_struct_state; /* structure management state */
+	int			c_conn_state;	/* connection state */
+
+	ldap_pvt_thread_mutex_t	c_mutex; /* protect the connection */
 	Sockbuf		c_sb;		/* ber connection stuff		  */
-	char		*c_cdn;		/* DN provided by the client */
-	char		*c_dn;		/* DN bound to this conn  */
-	ldap_pvt_thread_mutex_t	c_dnmutex;	/* mutex for c_dn field		  */
+
+	/* only can be changed by connect_init */
+	time_t		c_starttime;	/* when the connection was opened */
+	long		c_connid;	/* id of this connection for stats*/
+	char		*c_client_addr;	/* address of client */
+	char		*c_client_name;	/* name of client */
+
+	/* only can be changed by binding thread */
+	char	*c_cdn;		/* DN provided by the client */
+	char	*c_dn;		/* DN bound to this conn  */
 	int		c_protocol;	/* version of the LDAP protocol used by client */
 	int		c_authtype;	/* auth method used to bind c_dn  */
 #ifdef LDAP_COMPAT
 	int		c_version;	/* for compatibility w/2.0, 3.0	  */
 #endif
-	char		*c_addr;	/* address of client on this conn */
-	char		*c_domain;	/* domain of client on this conn  */
+
 	Operation	*c_ops;			/* list of operations being processed */
 	Operation	*c_pending_ops;	/* list of pending operations */
-	ldap_pvt_thread_mutex_t	c_opsmutex;	/* mutex for c_ops list & stats	  */
-	ldap_pvt_thread_mutex_t	c_pdumutex;	/* only one pdu written at a time */
-	ldap_pvt_thread_cond_t	c_wcv;		/* used to wait for sd write-ready*/
-	int		c_gettingber;	/* in the middle of ber_get_next  */
-	BerElement	*c_currentber;	/* ber we're getting              */
-	int		c_writewaiter;	/* signals write-ready sd waiter  */
-	int		c_pduwaiters;	/* signals threads waiting 4 pdu  */
-	time_t		c_starttime;	/* when the connection was opened */
 
-	long	c_connid;	/* id of this connection for stats*/
+	ldap_pvt_thread_mutex_t	c_write_mutex;	/* only one pdu written at a time */
+	ldap_pvt_thread_cond_t	c_write_cv;		/* used to wait for sd write-ready*/
 
-	long	c_ops_received;		/* num of ops received (next op_id) */
-	long	c_ops_executing;	/* num of ops currently executing */
-	long	c_ops_pending;		/* num of ops pending execution */
-	long	c_ops_completed;	/* num of ops completed */
+	BerElement	*c_currentber;	/* ber we're attempting to read */
+	int		c_writewaiter;	/* true if writer is waiting */
+
+	long	c_n_ops_received;		/* num of ops received (next op_id) */
+#ifdef LDAP_COUNTERS
+	long	c_n_ops_executing;	/* num of ops currently executing */
+	long	c_n_ops_pending;		/* num of ops pending execution */
+	long	c_n_ops_completed;	/* num of ops completed */
+#endif
 } Connection;
 
 #if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
diff --git a/servers/slapd/tools/Makefile.in b/servers/slapd/tools/Makefile.in
index f53ed416295b7e3dbf7d764f959b509c99e123c6..f8e8195e389be1138e266741ee800c37501a16e2 100644
--- a/servers/slapd/tools/Makefile.in
+++ b/servers/slapd/tools/Makefile.in
@@ -31,7 +31,8 @@ PROGRAMS2=ldif2index-bdb2 ldif2ldbm-bdb2 \
 	ldif2id2entry-bdb2 ldif2id2children-bdb2
 
 SRCS = centipede.c ldbmcat.c ldbmtest.c sizecount.c \
-	ldif.c ldif2id2children.c ldif2id2entry.c ldif2index.c ldif2ldbm.c
+	ldif.c ldif2id2children.c ldif2id2entry.c ldif2index.c ldif2ldbm.c \
+	mimic.c
 
 SRCS2 = ldif2id2children-bdb2.c ldif2id2entry-bdb2.c \
 	ldif2index-bdb2.c ldif2ldbm-bdb2.c
@@ -41,8 +42,9 @@ XSRCS = edb2-vers.c
 EDB2LDIFSRCS	= edb2ldif.c ldapsyntax.c
 EDB2LDIFOBJS	= edb2ldif.o ldapsyntax.o
 
-OBJS2	= ../config.o ../ch_malloc.o ../backend.o ../charray.o \
-		../aclparse.o ../schema.o ../result.o ../filterentry.o \
+OBJS2	= mimic.o \
+		../config.o ../ch_malloc.o ../backend.o ../charray.o \
+		../aclparse.o ../schema.o ../filterentry.o \
 		../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
 		../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
 		../schemaparse.o
diff --git a/servers/slapd/tools/mimic.c b/servers/slapd/tools/mimic.c
new file mode 100644
index 0000000000000000000000000000000000000000..87359d313677d49ef35e5613fbe1b09afc793dda
--- /dev/null
+++ b/servers/slapd/tools/mimic.c
@@ -0,0 +1,48 @@
+/*
+ * Mimic unused interfaces of slapd...
+ * needed for linking.
+ */
+#include "portable.h"
+
+#include <stdio.h>
+
+#include "../slap.h"
+
+void
+send_ldap_result(
+	Connection  *conn, 
+	Operation   *op,
+	int     err,
+	char    *matched,
+	char    *text
+)        
+{
+	assert(0);
+}
+
+void
+send_ldap_search_result(
+	Connection  *conn, 
+	Operation   *op,
+	int     err,
+	char    *matched,
+	char    *text,
+	int		nentries
+)        
+{
+	assert(0);
+}
+
+int
+send_search_entry(
+	Backend *be,
+	Connection  *conn, 
+	Operation   *op,
+	Entry	*e,
+	char	**attrs,
+	int		attrsonly
+)        
+{
+	assert(0);
+	return -1;
+}
diff --git a/servers/slapd/unbind.c b/servers/slapd/unbind.c
index 1416393343a1c4e395298ee0d0a6d73cf3c8e98e..f351e554099ecd8d24c883ed989640f627583023 100644
--- a/servers/slapd/unbind.c
+++ b/servers/slapd/unbind.c
@@ -41,7 +41,4 @@ do_unbind(
 
 	/* pass the unbind to all backends */
 	backend_unbind( conn, op );
-	
-	/* close the connection to the client */
-	close_connection( conn, op->o_connid, op->o_opid );
 }