Home | History | Annotate | Line # | Download | only in slapd
      1 /*	$NetBSD: connection.c,v 1.4 2025/09/05 21:16:25 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 The OpenLDAP Foundation.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted only as authorized by the OpenLDAP
     11  * Public License.
     12  *
     13  * A copy of this license is available in the file LICENSE in the
     14  * top-level directory of the distribution or, alternatively, at
     15  * <http://www.OpenLDAP.org/license.html>.
     16  */
     17 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
     18  * All rights reserved.
     19  *
     20  * Redistribution and use in source and binary forms are permitted
     21  * provided that this notice is preserved and that due credit is given
     22  * to the University of Michigan at Ann Arbor. The name of the University
     23  * may not be used to endorse or promote products derived from this
     24  * software without specific prior written permission. This software
     25  * is provided ``as is'' without express or implied warranty.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 __RCSID("$NetBSD: connection.c,v 1.4 2025/09/05 21:16:25 christos Exp $");
     30 
     31 #include "portable.h"
     32 
     33 #include <stdio.h>
     34 #ifdef HAVE_LIMITS_H
     35 #include <limits.h>
     36 #endif
     37 
     38 #include <ac/socket.h>
     39 #include <ac/errno.h>
     40 #include <ac/string.h>
     41 #include <ac/time.h>
     42 #include <ac/unistd.h>
     43 
     44 #include "lutil.h"
     45 #include "slap.h"
     46 
     47 #ifdef LDAP_CONNECTIONLESS
     48 #include "../../libraries/liblber/lber-int.h"	/* ber_int_sb_read() */
     49 #endif
     50 
     51 #ifdef LDAP_SLAPI
     52 #include "slapi/slapi.h"
     53 #endif
     54 
     55 static Connection *connections = NULL;
     56 
     57 static ldap_pvt_thread_mutex_t conn_nextid_mutex;
     58 static unsigned long conn_nextid = SLAPD_SYNC_SYNCCONN_OFFSET;
     59 
     60 static const char conn_lost_str[] = "connection lost";
     61 
     62 const char *
     63 connection_state2str( int state )
     64 {
     65 	switch( state ) {
     66 	case SLAP_C_INVALID:	return "!";
     67 	case SLAP_C_INACTIVE:	return "|";
     68 	case SLAP_C_CLOSING:	return "C";
     69 	case SLAP_C_ACTIVE:		return "";
     70 	case SLAP_C_BINDING:	return "B";
     71 	case SLAP_C_CLIENT:		return "L";
     72 	}
     73 
     74 	return "?";
     75 }
     76 
     77 static Connection* connection_get( ber_socket_t s );
     78 
     79 typedef struct conn_readinfo {
     80 	Operation *op;
     81 	ldap_pvt_thread_start_t *func;
     82 	void *arg;
     83 	void *ctx;
     84 	int nullop;
     85 } conn_readinfo;
     86 
     87 static int connection_input( Connection *c, conn_readinfo *cri );
     88 static void connection_close( Connection *c );
     89 
     90 static int connection_op_activate( Operation *op );
     91 static void connection_op_queue( Operation *op );
     92 static int connection_resched( Connection *conn );
     93 static void connection_abandon( Connection *conn );
     94 static void connection_destroy( Connection *c );
     95 
     96 static ldap_pvt_thread_start_t connection_operation;
     97 
     98 /*
     99  * Initialize connection management infrastructure.
    100  */
    101 int connections_init(void)
    102 {
    103 	int i;
    104 
    105 	assert( connections == NULL );
    106 
    107 	if( connections != NULL) {
    108 		Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n" );
    109 		return -1;
    110 	}
    111 
    112 	/* should check return of every call */
    113 	ldap_pvt_thread_mutex_init( &conn_nextid_mutex );
    114 
    115 	connections = (Connection *) ch_calloc( dtblsize, sizeof(Connection) );
    116 
    117 	if( connections == NULL ) {
    118 		Debug( LDAP_DEBUG_ANY, "connections_init: "
    119 			"allocation (%d*%ld) of connection array failed\n",
    120 			dtblsize, (long) sizeof(Connection) );
    121 		return -1;
    122 	}
    123 
    124 	for (i=0; i<dtblsize; i++) {
    125 		connections[i].c_conn_idx = i;
    126 		ldap_pvt_thread_mutex_init( &connections[i].c_mutex );
    127 		ldap_pvt_thread_mutex_init( &connections[i].c_write1_mutex );
    128 		ldap_pvt_thread_cond_init( &connections[i].c_write1_cv );
    129 	}
    130 
    131 
    132 	/*
    133 	 * per entry initialization of the Connection array initialization
    134 	 * will be done by connection_init()
    135 	 */
    136 
    137 	return 0;
    138 }
    139 
    140 /*
    141  * Destroy connection management infrastructure.
    142  */
    143 
    144 int connections_destroy(void)
    145 {
    146 	ber_socket_t i;
    147 
    148 	/* should check return of every call */
    149 
    150 	if( connections == NULL) {
    151 		Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n" );
    152 		return -1;
    153 	}
    154 
    155 	for ( i = 0; i < dtblsize; i++ ) {
    156 		ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex );
    157 		ldap_pvt_thread_mutex_destroy( &connections[i].c_write1_mutex );
    158 		ldap_pvt_thread_cond_destroy( &connections[i].c_write1_cv );
    159 		if( connections[i].c_sb ) {
    160 			ber_sockbuf_free( connections[i].c_sb );
    161 #ifdef LDAP_SLAPI
    162 			if ( slapi_plugins_used ) {
    163 				slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION,
    164 					&connections[i] );
    165 			}
    166 #endif
    167 		}
    168 	}
    169 
    170 	free( connections );
    171 	connections = NULL;
    172 
    173 	ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex );
    174 	return 0;
    175 }
    176 
    177 /*
    178  * shutdown all connections
    179  */
    180 int connections_shutdown(void)
    181 {
    182 	ber_socket_t i;
    183 
    184 	for ( i = 0; i < dtblsize; i++ ) {
    185 		ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
    186 		if( connections[i].c_conn_state > SLAP_C_INVALID ) {
    187 
    188 			/* give persistent clients a chance to cleanup */
    189 			if( connections[i].c_conn_state == SLAP_C_CLIENT ) {
    190 				ldap_pvt_thread_pool_submit( &connection_pool,
    191 				connections[i].c_clientfunc, connections[i].c_clientarg );
    192 			} else {
    193 				/* c_mutex is locked */
    194 				connection_closing( &connections[i], "slapd shutdown" );
    195 				connection_close( &connections[i] );
    196 			}
    197 		}
    198 		ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
    199 	}
    200 
    201 	return 0;
    202 }
    203 
    204 /*
    205  * Timeout idle connections.
    206  */
    207 int connections_timeout_idle(time_t now)
    208 {
    209 	int i = 0;
    210 	ber_socket_t connindex;
    211 	Connection* c;
    212 
    213 	for( c = connection_first( &connindex );
    214 		c != NULL;
    215 		c = connection_next( c, &connindex ) )
    216 	{
    217 		/* Don't timeout a slow-running request or a persistent
    218 		 * outbound connection.
    219 		 */
    220 		if( c->c_n_ops_executing || c->c_n_ops_async
    221 			|| c->c_conn_state == SLAP_C_CLIENT ) {
    222 			continue;
    223 		}
    224 
    225 		if( global_idletimeout &&
    226 			difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
    227 			/* close it */
    228 			connection_closing( c, "idletimeout" );
    229 			connection_close( c );
    230 			i++;
    231 			continue;
    232 		}
    233 	}
    234 	connection_done( c );
    235 
    236 	return i;
    237 }
    238 
    239 /* Drop all client connections */
    240 void connections_drop()
    241 {
    242 	Connection* c;
    243 	ber_socket_t connindex;
    244 
    245 	for( c = connection_first( &connindex );
    246 		c != NULL;
    247 		c = connection_next( c, &connindex ) )
    248 	{
    249 		/* Don't close a slow-running request or a persistent
    250 		 * outbound connection.
    251 		 */
    252 		if( c->c_n_ops_executing || c->c_n_ops_async
    253 			|| c->c_conn_state == SLAP_C_CLIENT ) {
    254 			continue;
    255 		}
    256 		connection_closing( c, "dropping" );
    257 		connection_close( c );
    258 	}
    259 	connection_done( c );
    260 }
    261 
    262 static Connection* connection_get( ber_socket_t s )
    263 {
    264 	Connection *c;
    265 
    266 	Debug( LDAP_DEBUG_ARGS,
    267 		"connection_get(%ld)\n",
    268 		(long) s );
    269 
    270 	assert( connections != NULL );
    271 
    272 	if(s == AC_SOCKET_INVALID) return NULL;
    273 
    274 	assert( s < dtblsize );
    275 	c = &connections[s];
    276 
    277 	if( c != NULL ) {
    278 		ldap_pvt_thread_mutex_lock( &c->c_mutex );
    279 
    280 		if( c->c_conn_state == SLAP_C_INVALID ) {
    281 			/* connection must have been closed due to resched */
    282 
    283 			Debug( LDAP_DEBUG_CONNS,
    284 				"connection_get(%d): connection not used\n",
    285 				s );
    286 			assert( c->c_sd == AC_SOCKET_INVALID );
    287 
    288 			ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    289 			return NULL;
    290 		}
    291 
    292 		Debug( LDAP_DEBUG_TRACE,
    293 			"connection_get(%d): got connid=%lu\n",
    294 			s, c->c_connid );
    295 
    296 		c->c_n_get++;
    297 
    298 		assert( c->c_conn_state != SLAP_C_INVALID );
    299 		assert( c->c_sd != AC_SOCKET_INVALID );
    300 
    301 		c->c_activitytime = slap_get_time();
    302 	}
    303 
    304 	return c;
    305 }
    306 
    307 static void connection_return( Connection *c )
    308 {
    309 	ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    310 }
    311 
    312 Connection * connection_init(
    313 	ber_socket_t s,
    314 	Listener *listener,
    315 	const char* dnsname,
    316 	const char* peername,
    317 	int flags,
    318 	slap_ssf_t ssf,
    319 	struct berval *authid
    320 	LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv))
    321 {
    322 	unsigned long id;
    323 	Connection *c;
    324 	ber_socket_t sfd = SLAP_FD2SOCK(s);
    325 
    326 	assert( connections != NULL );
    327 
    328 	assert( listener != NULL );
    329 	assert( dnsname != NULL );
    330 	assert( peername != NULL );
    331 
    332 #ifndef HAVE_TLS
    333 	assert( !( flags & CONN_IS_TLS ));
    334 #endif
    335 
    336 	if( s == AC_SOCKET_INVALID ) {
    337 		Debug( LDAP_DEBUG_ANY,
    338 			"connection_init: init of socket %ld invalid.\n", (long)s );
    339 		return NULL;
    340 	}
    341 
    342 	assert( s >= 0 );
    343 	assert( s < dtblsize );
    344 	c = &connections[s];
    345 
    346 	ldap_pvt_thread_mutex_lock( &c->c_mutex );
    347 
    348 	if( !c->c_sb ) {
    349 		c->c_send_ldap_result = slap_send_ldap_result;
    350 		c->c_send_search_entry = slap_send_search_entry;
    351 		c->c_send_search_reference = slap_send_search_reference;
    352 		c->c_send_ldap_extended = slap_send_ldap_extended;
    353 		c->c_send_ldap_intermediate = slap_send_ldap_intermediate;
    354 
    355 		BER_BVZERO( &c->c_authmech );
    356 		BER_BVZERO( &c->c_dn );
    357 		BER_BVZERO( &c->c_ndn );
    358 
    359 		c->c_listener = NULL;
    360 		BER_BVZERO( &c->c_peer_domain );
    361 		BER_BVZERO( &c->c_peer_name );
    362 
    363 		LDAP_STAILQ_INIT(&c->c_ops);
    364 		LDAP_STAILQ_INIT(&c->c_pending_ops);
    365 
    366 		c->c_txn = CONN_TXN_INACTIVE;
    367 		c->c_txn_backend = NULL;
    368 		LDAP_STAILQ_INIT(&c->c_txn_ops);
    369 
    370 		BER_BVZERO( &c->c_sasl_bind_mech );
    371 		c->c_sasl_done = 0;
    372 		c->c_sasl_authctx = NULL;
    373 		c->c_sasl_sockctx = NULL;
    374 		c->c_sasl_extra = NULL;
    375 		c->c_sasl_bindop = NULL;
    376 		c->c_sasl_cbind = NULL;
    377 
    378 		c->c_sb = ber_sockbuf_alloc( );
    379 
    380 		{
    381 			ber_len_t max = sockbuf_max_incoming;
    382 			ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
    383 		}
    384 
    385 		c->c_currentber = NULL;
    386 
    387 #ifdef LDAP_SLAPI
    388 		if ( slapi_plugins_used ) {
    389 			slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, c );
    390 		}
    391 #endif
    392 	}
    393 
    394 	assert( BER_BVISNULL( &c->c_authmech ) );
    395 	assert( BER_BVISNULL( &c->c_dn ) );
    396 	assert( BER_BVISNULL( &c->c_ndn ) );
    397 	assert( c->c_listener == NULL );
    398 	assert( BER_BVISNULL( &c->c_peer_domain ) );
    399 	assert( BER_BVISNULL( &c->c_peer_name ) );
    400 	assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
    401 	assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) );
    402 	assert( c->c_txn == CONN_TXN_INACTIVE );
    403 	assert( c->c_txn_backend == NULL );
    404 	assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) );
    405 	assert( BER_BVISNULL( &c->c_sasl_bind_mech ) );
    406 	assert( c->c_sasl_done == 0 );
    407 	assert( c->c_sasl_authctx == NULL );
    408 	assert( c->c_sasl_sockctx == NULL );
    409 	assert( c->c_sasl_extra == NULL );
    410 	assert( c->c_sasl_bindop == NULL );
    411 	assert( c->c_sasl_cbind == NULL );
    412 	assert( c->c_currentber == NULL );
    413 	assert( c->c_writewaiter == 0);
    414 	assert( c->c_writers == 0);
    415 
    416 	c->c_listener = listener;
    417 	c->c_sd = s;
    418 
    419 	if ( flags & CONN_IS_CLIENT ) {
    420 		c->c_connid = 0;
    421 		c->c_conn_state = SLAP_C_CLIENT;
    422 		c->c_close_reason = "?";			/* should never be needed */
    423 		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &sfd );
    424 		ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    425 
    426 		return c;
    427 	}
    428 
    429 	ber_str2bv( dnsname, 0, 1, &c->c_peer_domain );
    430 	ber_str2bv( peername, 0, 1, &c->c_peer_name );
    431 
    432 	c->c_n_ops_received = 0;
    433 	c->c_n_ops_executing = 0;
    434 	c->c_n_ops_pending = 0;
    435 	c->c_n_ops_completed = 0;
    436 	c->c_n_ops_async = 0;
    437 
    438 	c->c_n_get = 0;
    439 	c->c_n_read = 0;
    440 	c->c_n_write = 0;
    441 
    442 	/* set to zero until bind, implies LDAP_VERSION3 */
    443 	c->c_protocol = 0;
    444 
    445 	c->c_activitytime = c->c_starttime = slap_get_time();
    446 
    447 #ifdef LDAP_CONNECTIONLESS
    448 	c->c_is_udp = 0;
    449 	if( flags & CONN_IS_UDP ) {
    450 		c->c_is_udp = 1;
    451 #ifdef LDAP_DEBUG
    452 		ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
    453 			LBER_SBIOD_LEVEL_PROVIDER, (void*)"udp_" );
    454 #endif
    455 		ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_udp,
    456 			LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd );
    457 		ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
    458 			LBER_SBIOD_LEVEL_PROVIDER, NULL );
    459 	} else
    460 #endif /* LDAP_CONNECTIONLESS */
    461 #ifdef LDAP_PF_LOCAL
    462 	if ( flags & CONN_IS_IPC ) {
    463 #ifdef LDAP_DEBUG
    464 		ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
    465 			LBER_SBIOD_LEVEL_PROVIDER, (void*)"ipc_" );
    466 #endif
    467 		ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_fd,
    468 			LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd );
    469 #ifdef LDAP_PF_LOCAL_SENDMSG
    470 		if ( !BER_BVISEMPTY( peerbv ))
    471 			ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_UNGET_BUF, peerbv );
    472 #endif
    473 	} else
    474 #endif /* LDAP_PF_LOCAL */
    475 	{
    476 #ifdef LDAP_DEBUG
    477 		ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
    478 			LBER_SBIOD_LEVEL_PROVIDER, (void*)"tcp_" );
    479 #endif
    480 		ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_tcp,
    481 			LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd );
    482 	}
    483 
    484 #ifdef LDAP_DEBUG
    485 	ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
    486 		INT_MAX, (void*)"ldap_" );
    487 #endif
    488 
    489 	if( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_NONBLOCK,
    490 		c /* non-NULL */ ) < 0 )
    491 	{
    492 		Debug( LDAP_DEBUG_ANY,
    493 			"connection_init(%d, %s): set nonblocking failed\n",
    494 			s, c->c_peer_name.bv_val );
    495 
    496 		c->c_listener = NULL;
    497 		if(c->c_peer_domain.bv_val != NULL) {
    498 			free(c->c_peer_domain.bv_val);
    499 		}
    500 		BER_BVZERO( &c->c_peer_domain );
    501 		if(c->c_peer_name.bv_val != NULL) {
    502 			free(c->c_peer_name.bv_val);
    503 		}
    504 		BER_BVZERO( &c->c_peer_name );
    505 
    506 		ber_sockbuf_free( c->c_sb );
    507 		c->c_sb = ber_sockbuf_alloc( );
    508 		{
    509 			ber_len_t max = sockbuf_max_incoming;
    510 			ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
    511 		}
    512 
    513 		c->c_sd = AC_SOCKET_INVALID;
    514 		ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    515 
    516 		return NULL;
    517 	}
    518 
    519 	ldap_pvt_thread_mutex_lock( &conn_nextid_mutex );
    520 	id = c->c_connid = conn_nextid++;
    521 	ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex );
    522 
    523 	c->c_conn_state = SLAP_C_INACTIVE;
    524 	c->c_close_reason = "?";			/* should never be needed */
    525 
    526 	c->c_ssf = c->c_transport_ssf = ssf;
    527 	c->c_tls_ssf = c->c_sasl_ssf = 0;
    528 
    529 #ifdef HAVE_TLS
    530 	if ( flags & CONN_IS_TLS ) {
    531 		c->c_is_tls = 1;
    532 		c->c_needs_tls_accept = 1;
    533 	} else {
    534 		c->c_is_tls = 0;
    535 		c->c_needs_tls_accept = 0;
    536 	}
    537 #endif
    538 
    539 	slap_sasl_open( c, 0 );
    540 	slap_sasl_external( c, ssf, authid );
    541 
    542 	slapd_add_internal( s, 1 );
    543 
    544 	backend_connection_init(c);
    545 	ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    546 
    547 	if ( !(flags & CONN_IS_UDP ))
    548 		Debug( LDAP_DEBUG_STATS,
    549 			"conn=%ld fd=%ld ACCEPT from %s (%s)\n",
    550 			id, (long) s, peername, listener->sl_name.bv_val );
    551 
    552 	return c;
    553 }
    554 
    555 void connection2anonymous( Connection *c )
    556 {
    557 	assert( connections != NULL );
    558 	assert( c != NULL );
    559 
    560 	{
    561 		ber_len_t max = sockbuf_max_incoming;
    562 		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
    563 	}
    564 
    565 	if ( !BER_BVISNULL( &c->c_authmech ) ) {
    566 		ch_free(c->c_authmech.bv_val);
    567 	}
    568 	BER_BVZERO( &c->c_authmech );
    569 
    570 	if ( !BER_BVISNULL( &c->c_dn ) ) {
    571 		ch_free(c->c_dn.bv_val);
    572 	}
    573 	BER_BVZERO( &c->c_dn );
    574 
    575 	if ( !BER_BVISNULL( &c->c_ndn ) ) {
    576 		ch_free(c->c_ndn.bv_val);
    577 	}
    578 	BER_BVZERO( &c->c_ndn );
    579 
    580 	if ( !BER_BVISNULL( &c->c_sasl_authz_dn ) ) {
    581 		ber_memfree_x( c->c_sasl_authz_dn.bv_val, NULL );
    582 	}
    583 	BER_BVZERO( &c->c_sasl_authz_dn );
    584 
    585 	c->c_authz_backend = NULL;
    586 }
    587 
    588 static void
    589 connection_destroy( Connection *c )
    590 {
    591 	unsigned long	connid;
    592 	const char		*close_reason;
    593 	Sockbuf			*sb;
    594 	ber_socket_t	sd;
    595 
    596 	assert( connections != NULL );
    597 	assert( c != NULL );
    598 	assert( c->c_conn_state != SLAP_C_INVALID );
    599 	assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
    600 	assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) );
    601 	assert( c->c_txn == CONN_TXN_INACTIVE );
    602 	assert( c->c_txn_backend == NULL );
    603 	assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) );
    604 	assert( c->c_writewaiter == 0);
    605 	assert( c->c_writers == 0);
    606 
    607 	/* only for stats (print -1 as "%lu" may give unexpected results ;) */
    608 	connid = c->c_connid;
    609 	close_reason = c->c_close_reason;
    610 
    611 	backend_connection_destroy(c);
    612 
    613 	c->c_protocol = 0;
    614 	c->c_connid = -1;
    615 
    616 	c->c_activitytime = c->c_starttime = 0;
    617 
    618 	connection2anonymous( c );
    619 	c->c_listener = NULL;
    620 
    621 	if(c->c_peer_domain.bv_val != NULL) {
    622 		free(c->c_peer_domain.bv_val);
    623 	}
    624 	BER_BVZERO( &c->c_peer_domain );
    625 	if(c->c_peer_name.bv_val != NULL) {
    626 		free(c->c_peer_name.bv_val);
    627 	}
    628 	BER_BVZERO( &c->c_peer_name );
    629 
    630 	c->c_sasl_bind_in_progress = 0;
    631 	if(c->c_sasl_bind_mech.bv_val != NULL) {
    632 		free(c->c_sasl_bind_mech.bv_val);
    633 	}
    634 	BER_BVZERO( &c->c_sasl_bind_mech );
    635 
    636 	slap_sasl_close( c );
    637 
    638 	if ( c->c_currentber != NULL ) {
    639 		ber_free( c->c_currentber, 1 );
    640 		c->c_currentber = NULL;
    641 	}
    642 
    643 
    644 #ifdef LDAP_SLAPI
    645 	/* call destructors, then constructors; avoids unnecessary allocation */
    646 	if ( slapi_plugins_used ) {
    647 		slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
    648 	}
    649 #endif
    650 
    651 	sd = c->c_sd;
    652 	c->c_sd = AC_SOCKET_INVALID;
    653 	c->c_close_reason = "?";			/* should never be needed */
    654 
    655 	sb = c->c_sb;
    656 	c->c_sb = ber_sockbuf_alloc( );
    657 	{
    658 		ber_len_t max = sockbuf_max_incoming;
    659 		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
    660 	}
    661 	c->c_conn_state = SLAP_C_INVALID;
    662 
    663 	/* c must be fully reset by this point; when we call slapd_remove
    664 	 * it may get immediately reused by a new connection.
    665 	 */
    666 	if ( sd != AC_SOCKET_INVALID ) {
    667 		slapd_remove( sd, sb, 1, 0, 0 );
    668 
    669 		if ( close_reason == NULL ) {
    670 			Debug( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed\n",
    671 				connid, (long) sd );
    672 		} else {
    673 			Debug( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed (%s)\n",
    674 				connid, (long) sd, close_reason );
    675 		}
    676 	}
    677 }
    678 
    679 int connection_is_active( ber_socket_t s )
    680 {
    681 	Connection *c;
    682 
    683 	assert( s < dtblsize );
    684 	c = &connections[s];
    685 	return c->c_conn_state == SLAP_C_CLOSING ||
    686 		c->c_conn_state == SLAP_C_BINDING ||
    687 		c->c_conn_state == SLAP_C_ACTIVE ;
    688 }
    689 
    690 int connection_valid( Connection *c )
    691 {
    692 	/* c_mutex must be locked by caller */
    693 
    694 	assert( c != NULL );
    695 
    696 	return c->c_conn_state >= SLAP_C_ACTIVE &&
    697 		c->c_conn_state <= SLAP_C_CLIENT;
    698 }
    699 
    700 static void connection_abandon( Connection *c )
    701 {
    702 	/* c_mutex must be locked by caller */
    703 
    704 	Operation *o, *next, op = {0};
    705 	Opheader ohdr = {0};
    706 
    707 	op.o_hdr = &ohdr;
    708 	op.o_conn = c;
    709 	op.o_connid = c->c_connid;
    710 	op.o_tag = LDAP_REQ_ABANDON;
    711 
    712 	for ( o = LDAP_STAILQ_FIRST( &c->c_ops ); o; o=next ) {
    713 		SlapReply rs = {REP_RESULT};
    714 
    715 		next = LDAP_STAILQ_NEXT( o, o_next );
    716 		/* don't abandon an op twice */
    717 		if ( o->o_abandon )
    718 			continue;
    719 		op.orn_msgid = o->o_msgid;
    720 		o->o_abandon = 1;
    721 		op.o_bd = frontendDB;
    722 		frontendDB->be_abandon( &op, &rs );
    723 	}
    724 
    725 	/* remove operations in pending transaction */
    726 	while ( (o = LDAP_STAILQ_FIRST( &c->c_txn_ops )) != NULL) {
    727 		LDAP_STAILQ_REMOVE_HEAD( &c->c_txn_ops, o_next );
    728 		LDAP_STAILQ_NEXT(o, o_next) = NULL;
    729 		slap_op_free( o, NULL );
    730 	}
    731 
    732 	/* clear transaction */
    733 	c->c_txn_backend = NULL;
    734 	c->c_txn = CONN_TXN_INACTIVE;
    735 
    736 	/* remove pending operations */
    737 	while ( (o = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
    738 		LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
    739 		LDAP_STAILQ_NEXT(o, o_next) = NULL;
    740 		slap_op_free( o, NULL );
    741 	}
    742 	c->c_n_ops_pending = 0;
    743 }
    744 
    745 static void
    746 connection_wake_writers( Connection *c )
    747 {
    748 	/* wake write blocked operations */
    749 	ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
    750 	if ( c->c_writers > 0 ) {
    751 		c->c_writers = -c->c_writers;
    752 		ldap_pvt_thread_cond_broadcast( &c->c_write1_cv );
    753 		ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
    754 		if ( c->c_writewaiter ) {
    755 			slapd_shutsock( c->c_sd );
    756 		}
    757 		ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
    758 		while ( c->c_writers ) {
    759 			ldap_pvt_thread_cond_wait( &c->c_write1_cv, &c->c_write1_mutex );
    760 		}
    761 		ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
    762 	} else {
    763 		ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
    764 		slapd_clr_write( c->c_sd, 1 );
    765 	}
    766 }
    767 
    768 void connection_closing( Connection *c, const char *why )
    769 {
    770 	assert( connections != NULL );
    771 	assert( c != NULL );
    772 
    773 	if( c->c_conn_state == SLAP_C_INVALID )
    774 		return;
    775 
    776 	/* c_mutex must be locked by caller */
    777 
    778 	if( c->c_conn_state != SLAP_C_CLOSING ) {
    779 		Debug( LDAP_DEBUG_CONNS,
    780 			"connection_closing: readying conn=%lu sd=%d for close\n",
    781 			c->c_connid, c->c_sd );
    782 		/* update state to closing */
    783 		c->c_conn_state = SLAP_C_CLOSING;
    784 		c->c_close_reason = why;
    785 
    786 		/* don't listen on this port anymore */
    787 		slapd_clr_read( c->c_sd, 0 );
    788 
    789 		/* abandon active operations */
    790 		connection_abandon( c );
    791 
    792 		/* wake write blocked operations */
    793 		connection_wake_writers( c );
    794 
    795 	} else if( why == NULL && c->c_close_reason == conn_lost_str ) {
    796 		/* Client closed connection after doing Unbind. */
    797 		c->c_close_reason = NULL;
    798 	}
    799 }
    800 
    801 static void
    802 connection_close( Connection *c )
    803 {
    804 	assert( connections != NULL );
    805 	assert( c != NULL );
    806 
    807 	if ( c->c_conn_state != SLAP_C_CLOSING )
    808 		return;
    809 
    810 	/* NOTE: c_mutex should be locked by caller */
    811 
    812 	if ( !LDAP_STAILQ_EMPTY(&c->c_ops) ||
    813 		!LDAP_STAILQ_EMPTY(&c->c_pending_ops) )
    814 	{
    815 		Debug( LDAP_DEBUG_CONNS,
    816 			"connection_close: deferring conn=%lu sd=%d\n",
    817 			c->c_connid, c->c_sd );
    818 		return;
    819 	}
    820 
    821 	Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%lu sd=%d\n",
    822 		c->c_connid, c->c_sd );
    823 
    824 	connection_destroy( c );
    825 }
    826 
    827 unsigned long connections_nextid(void)
    828 {
    829 	unsigned long id;
    830 	assert( connections != NULL );
    831 
    832 	ldap_pvt_thread_mutex_lock( &conn_nextid_mutex );
    833 
    834 	id = conn_nextid;
    835 
    836 	ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex );
    837 
    838 	return id;
    839 }
    840 
    841 /*
    842  * Loop through the connections:
    843  *
    844  *	for (c = connection_first(&i); c; c = connection_next(c, &i)) ...;
    845  *	connection_done(c);
    846  *
    847  * 'i' is the cursor, initialized by connection_first().
    848  * 'c_mutex' is locked in the returned connection.  The functions must
    849  * be passed the previous return value so they can unlock it again.
    850  */
    851 
    852 Connection* connection_first( ber_socket_t *index )
    853 {
    854 	assert( connections != NULL );
    855 	assert( index != NULL );
    856 
    857 	for( *index = 0; *index < dtblsize; (*index)++) {
    858 		if( connections[*index].c_sb ) {
    859 			break;
    860 		}
    861 	}
    862 
    863 	return connection_next(NULL, index);
    864 }
    865 
    866 /* Next connection in loop, see connection_first() */
    867 Connection* connection_next( Connection *c, ber_socket_t *index )
    868 {
    869 	assert( connections != NULL );
    870 	assert( index != NULL );
    871 	assert( *index <= dtblsize );
    872 
    873 	if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    874 
    875 	c = NULL;
    876 
    877 	for(; *index < dtblsize; (*index)++) {
    878 		if( connections[*index].c_sb ) {
    879 			c = &connections[*index];
    880 			ldap_pvt_thread_mutex_lock( &c->c_mutex );
    881 			if ( c->c_conn_state == SLAP_C_INVALID ) {
    882 				ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    883 				c = NULL;
    884 				continue;
    885 			}
    886 			(*index)++;
    887 			break;
    888 		}
    889 	}
    890 
    891 	return c;
    892 }
    893 
    894 /* End connection loop, see connection_first() */
    895 void connection_done( Connection *c )
    896 {
    897 	assert( connections != NULL );
    898 
    899 	if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
    900 }
    901 
    902 /*
    903  * connection_activity - handle the request operation op on connection
    904  * conn.  This routine figures out what kind of operation it is and
    905  * calls the appropriate stub to handle it.
    906  */
    907 
    908 /* FIXME: returns 0 in case of failure */
    909 #define INCR_OP_INITIATED(index) \
    910 	do { \
    911 		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
    912 		ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated_[(index)], 1); \
    913 		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
    914 	} while (0)
    915 #define INCR_OP_COMPLETED(index) \
    916 	do { \
    917 		ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
    918 		ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed, 1); \
    919 		ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed_[(index)], 1); \
    920 		ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
    921 	} while (0)
    922 
    923 /*
    924  * NOTE: keep in sync with enum in slapd.h
    925  */
    926 static BI_op_func *opfun[] = {
    927 	do_bind,
    928 	do_unbind,
    929 	do_search,
    930 	do_compare,
    931 	do_modify,
    932 	do_modrdn,
    933 	do_add,
    934 	do_delete,
    935 	do_abandon,
    936 	do_extended,
    937 	NULL
    938 };
    939 
    940 /* Counters are per-thread, not per-connection.
    941  */
    942 static void
    943 conn_counter_destroy( void *key, void *data )
    944 {
    945 	slap_counters_t **prev, *sc;
    946 
    947 	ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
    948 	for ( prev = &slap_counters.sc_next, sc = slap_counters.sc_next; sc;
    949 		prev = &sc->sc_next, sc = sc->sc_next ) {
    950 		if ( sc == data ) {
    951 			int i;
    952 
    953 			*prev = sc->sc_next;
    954 			/* Copy data to main counter */
    955 			ldap_pvt_mp_add( slap_counters.sc_bytes, sc->sc_bytes );
    956 			ldap_pvt_mp_add( slap_counters.sc_pdu, sc->sc_pdu );
    957 			ldap_pvt_mp_add( slap_counters.sc_entries, sc->sc_entries );
    958 			ldap_pvt_mp_add( slap_counters.sc_refs, sc->sc_refs );
    959 			ldap_pvt_mp_add( slap_counters.sc_ops_initiated, sc->sc_ops_initiated );
    960 			ldap_pvt_mp_add( slap_counters.sc_ops_completed, sc->sc_ops_completed );
    961 			for ( i = 0; i < SLAP_OP_LAST; i++ ) {
    962 				ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_initiated_[ i ] );
    963 				ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_completed_[ i ] );
    964 			}
    965 			slap_counters_destroy( sc );
    966 			ber_memfree_x( data, NULL );
    967 			break;
    968 		}
    969 	}
    970 	ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
    971 }
    972 
    973 void
    974 operation_counter_init( Operation *op, void *ctx )
    975 {
    976 	slap_counters_t *sc;
    977 	void *vsc = NULL;
    978 
    979 	if ( ldap_pvt_thread_pool_getkey(
    980 			ctx, (void *)operation_counter_init, &vsc, NULL ) || !vsc ) {
    981 		vsc = ch_malloc( sizeof( slap_counters_t ));
    982 		sc = vsc;
    983 		slap_counters_init( sc );
    984 		ldap_pvt_thread_pool_setkey( ctx, (void*)operation_counter_init, vsc,
    985 			conn_counter_destroy, NULL, NULL );
    986 
    987 		ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
    988 		sc->sc_next = slap_counters.sc_next;
    989 		slap_counters.sc_next = sc;
    990 		ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
    991 	}
    992 	op->o_counters = vsc;
    993 }
    994 
    995 void
    996 connection_op_finish( Operation *op, int lock )
    997 {
    998 	Connection *conn = op->o_conn;
    999 	void *memctx_null = NULL;
   1000 	slap_op_t opidx = slap_req2op( op->o_tag );
   1001 	assert( opidx != SLAP_OP_LAST );
   1002 
   1003 	INCR_OP_COMPLETED( opidx );
   1004 
   1005 	if ( lock )
   1006 		ldap_pvt_thread_mutex_lock( &conn->c_mutex );
   1007 
   1008 	if ( op->o_tag == LDAP_REQ_BIND && conn->c_conn_state == SLAP_C_BINDING )
   1009 		conn->c_conn_state = SLAP_C_ACTIVE;
   1010 
   1011 	ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null );
   1012 
   1013 	LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next);
   1014 	LDAP_STAILQ_NEXT(op, o_next) = NULL;
   1015 	conn->c_n_ops_async--;
   1016 	conn->c_n_ops_completed++;
   1017 	connection_resched( conn );
   1018 	if ( lock )
   1019 		ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
   1020 }
   1021 
   1022 static void *
   1023 connection_operation( void *ctx, void *arg_v )
   1024 {
   1025 	int rc = LDAP_OTHER, cancel;
   1026 	Operation *op = arg_v;
   1027 	SlapReply rs = {REP_RESULT};
   1028 	ber_tag_t tag = op->o_tag;
   1029 	slap_op_t opidx = SLAP_OP_LAST;
   1030 	Connection *conn = op->o_conn;
   1031 	void *memctx = NULL;
   1032 	void *memctx_null = NULL;
   1033 	ber_len_t memsiz;
   1034 
   1035 	gettimeofday( &op->o_qtime, NULL );
   1036 	op->o_qtime.tv_usec -= op->o_tusec;
   1037 	if ( op->o_qtime.tv_usec < 0 ) {
   1038 		op->o_qtime.tv_usec += 1000000;
   1039 		op->o_qtime.tv_sec--;
   1040 	}
   1041 	op->o_qtime.tv_sec -= op->o_time;
   1042 	operation_counter_init( op, ctx );
   1043 	ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
   1044 	/* FIXME: returns 0 in case of failure */
   1045 	ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated, 1);
   1046 	ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
   1047 
   1048 	op->o_threadctx = ctx;
   1049 	op->o_tid = ldap_pvt_thread_pool_tid( ctx );
   1050 
   1051 	switch ( tag ) {
   1052 	case LDAP_REQ_BIND:
   1053 	case LDAP_REQ_UNBIND:
   1054 	case LDAP_REQ_ADD:
   1055 	case LDAP_REQ_DELETE:
   1056 	case LDAP_REQ_MODDN:
   1057 	case LDAP_REQ_MODIFY:
   1058 	case LDAP_REQ_COMPARE:
   1059 	case LDAP_REQ_SEARCH:
   1060 	case LDAP_REQ_ABANDON:
   1061 	case LDAP_REQ_EXTENDED:
   1062 		break;
   1063 	default:
   1064 		Debug( LDAP_DEBUG_ANY, "connection_operation: "
   1065 			"conn %lu unknown LDAP request 0x%lx\n",
   1066 			conn->c_connid, tag );
   1067 		op->o_tag = LBER_ERROR;
   1068 		rs.sr_err = LDAP_PROTOCOL_ERROR;
   1069 		rs.sr_text = "unknown LDAP request";
   1070 		send_ldap_disconnect( op, &rs );
   1071 		rc = SLAPD_DISCONNECT;
   1072 		goto operations_error;
   1073 	}
   1074 
   1075 	if( conn->c_sasl_bind_in_progress && tag != LDAP_REQ_BIND ) {
   1076 		Debug( LDAP_DEBUG_ANY, "connection_operation: "
   1077 			"error: SASL bind in progress (tag=%ld).\n",
   1078 			(long) tag );
   1079 		send_ldap_error( op, &rs, LDAP_OPERATIONS_ERROR,
   1080 			"SASL bind in progress" );
   1081 		rc = LDAP_OPERATIONS_ERROR;
   1082 		goto operations_error;
   1083 	}
   1084 
   1085 	if (( conn->c_txn == CONN_TXN_SPECIFY ) && (
   1086 		( tag == LDAP_REQ_ADD ) ||
   1087 		( tag == LDAP_REQ_DELETE ) ||
   1088 		( tag == LDAP_REQ_MODIFY ) ||
   1089 		( tag == LDAP_REQ_MODRDN )))
   1090 	{
   1091 		/* Disable SLAB allocator for all update operations
   1092 			issued inside of a transaction */
   1093 		op->o_tmpmemctx = NULL;
   1094 		op->o_tmpmfuncs = &ch_mfuncs;
   1095 	} else {
   1096 	/* We can use Thread-Local storage for most mallocs. We can
   1097 	 * also use TL for ber parsing, but not on Add or Modify.
   1098 	 */
   1099 #if 0
   1100 	memsiz = ber_len( op->o_ber ) * 64;
   1101 	if ( SLAP_SLAB_SIZE > memsiz ) memsiz = SLAP_SLAB_SIZE;
   1102 #endif
   1103 	memsiz = SLAP_SLAB_SIZE;
   1104 
   1105 	memctx = slap_sl_mem_create( memsiz, SLAP_SLAB_STACK, ctx, 1 );
   1106 	op->o_tmpmemctx = memctx;
   1107 	op->o_tmpmfuncs = &slap_sl_mfuncs;
   1108 	if ( tag != LDAP_REQ_ADD && tag != LDAP_REQ_MODIFY ) {
   1109 		/* Note - the ber and its buffer are already allocated from
   1110 		 * regular memory; this only affects subsequent mallocs that
   1111 		 * ber_scanf may invoke.
   1112 		 */
   1113 		ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx );
   1114 	}
   1115 	}
   1116 
   1117 	opidx = slap_req2op( tag );
   1118 	assert( opidx != SLAP_OP_LAST );
   1119 	INCR_OP_INITIATED( opidx );
   1120 	rc = (*(opfun[opidx]))( op, &rs );
   1121 
   1122 operations_error:
   1123 	if ( rc == SLAPD_DISCONNECT ) {
   1124 		tag = LBER_ERROR;
   1125 
   1126     } else if ( rc == SLAPD_ASYNCOP ) {
   1127 		/* someone has claimed ownership of the op
   1128 		 * to complete it later. Don't do anything
   1129 		 * else with it now. Detach memctx too.
   1130 		 */
   1131 		slap_sl_mem_setctx( ctx, NULL );
   1132 		ldap_pvt_thread_mutex_lock( &conn->c_mutex );
   1133 		conn->c_n_ops_executing--;
   1134 		conn->c_n_ops_async++;
   1135 		connection_resched( conn );
   1136 		ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
   1137 		return NULL;
   1138 
   1139 	} else if ( opidx != SLAP_OP_LAST ) {
   1140 		/* increment completed operations count
   1141 		 * only if operation was initiated
   1142 		 * and rc != SLAPD_DISCONNECT */
   1143 		INCR_OP_COMPLETED( opidx );
   1144 	}
   1145 
   1146 	ldap_pvt_thread_mutex_lock( &conn->c_mutex );
   1147 
   1148 	if ( opidx == SLAP_OP_BIND && conn->c_conn_state == SLAP_C_BINDING )
   1149 		conn->c_conn_state = SLAP_C_ACTIVE;
   1150 
   1151 	cancel = op->o_cancel;
   1152 	if ( cancel != SLAP_CANCEL_NONE && cancel != SLAP_CANCEL_DONE ) {
   1153 		if ( cancel == SLAP_CANCEL_REQ ) {
   1154 			op->o_cancel = rc == SLAPD_ABANDON
   1155 				? SLAP_CANCEL_ACK : LDAP_TOO_LATE;
   1156 		}
   1157 
   1158 		do {
   1159 			/* Fake a cond_wait with thread_yield, then
   1160 			 * verify the result properly mutex-protected.
   1161 			 */
   1162 			ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
   1163 			do {
   1164 				ldap_pvt_thread_yield();
   1165 			} while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE
   1166 					&& cancel != SLAP_CANCEL_DONE );
   1167 			ldap_pvt_thread_mutex_lock( &conn->c_mutex );
   1168 		} while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE
   1169 				&& cancel != SLAP_CANCEL_DONE );
   1170 	}
   1171 
   1172 	ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null );
   1173 
   1174 	if ( rc != LDAP_TXN_SPECIFY_OKAY ) {
   1175 		LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next);
   1176 		LDAP_STAILQ_NEXT(op, o_next) = NULL;
   1177 	}
   1178 	conn->c_n_ops_executing--;
   1179 	conn->c_n_ops_completed++;
   1180 
   1181 	switch( tag ) {
   1182 	case LBER_ERROR:
   1183 	case LDAP_REQ_UNBIND:
   1184 		/* c_mutex is locked */
   1185 		connection_closing( conn,
   1186 			tag == LDAP_REQ_UNBIND ? NULL : "operations error" );
   1187 		break;
   1188 	}
   1189 
   1190 	connection_resched( conn );
   1191 	ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
   1192 	if ( rc != LDAP_TXN_SPECIFY_OKAY ) {
   1193 		slap_op_free( op, ctx );
   1194 	}
   1195 	return NULL;
   1196 }
   1197 
   1198 static const Listener dummy_list = { BER_BVC(""), BER_BVC("") };
   1199 
   1200 Connection *connection_client_setup(
   1201 	ber_socket_t s,
   1202 	ldap_pvt_thread_start_t *func,
   1203 	void *arg )
   1204 {
   1205 	Connection *c;
   1206 	ber_socket_t sfd = SLAP_SOCKNEW( s );
   1207 
   1208 	c = connection_init( sfd, (Listener *)&dummy_list, "", "",
   1209 		CONN_IS_CLIENT, 0, NULL
   1210 		LDAP_PF_LOCAL_SENDMSG_ARG(NULL));
   1211 	if ( c ) {
   1212 		c->c_clientfunc = func;
   1213 		c->c_clientarg = arg;
   1214 
   1215 		slapd_add_internal( sfd, 0 );
   1216 	}
   1217 	return c;
   1218 }
   1219 
   1220 void connection_client_enable(
   1221 	Connection *c )
   1222 {
   1223 	slapd_set_read( c->c_sd, 1 );
   1224 }
   1225 
   1226 void connection_client_stop(
   1227 	Connection *c )
   1228 {
   1229 	Sockbuf *sb;
   1230 	ber_socket_t s = c->c_sd;
   1231 
   1232 	/* get (locked) connection */
   1233 	c = connection_get( s );
   1234 
   1235 	assert( c->c_conn_state == SLAP_C_CLIENT );
   1236 
   1237 	c->c_listener = NULL;
   1238 	c->c_sd = AC_SOCKET_INVALID;
   1239 	c->c_close_reason = "?";			/* should never be needed */
   1240 	sb = c->c_sb;
   1241 	c->c_sb = ber_sockbuf_alloc( );
   1242 	{
   1243 		ber_len_t max = sockbuf_max_incoming;
   1244 		ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
   1245 	}
   1246 	c->c_conn_state = SLAP_C_INVALID;
   1247 	slapd_remove( s, sb, 0, 1, 0 );
   1248 
   1249 	connection_return( c );
   1250 }
   1251 
   1252 static int connection_read( ber_socket_t s, conn_readinfo *cri );
   1253 
   1254 static void* connection_read_thread( void* ctx, void* argv )
   1255 {
   1256 	int rc ;
   1257 	conn_readinfo cri = { NULL, NULL, NULL, NULL, 0 };
   1258 	ber_socket_t s = (long)argv;
   1259 
   1260 	/*
   1261 	 * read incoming LDAP requests. If there is more than one,
   1262 	 * the first one is returned with new_op
   1263 	 */
   1264 	cri.ctx = ctx;
   1265 	if( ( rc = connection_read( s, &cri ) ) < 0 ) {
   1266 		Debug( LDAP_DEBUG_CONNS, "connection_read(%d) error\n", s );
   1267 		return (void*)(long)rc;
   1268 	}
   1269 
   1270 	/* execute a single queued request in the same thread */
   1271 	if( cri.op && !cri.nullop ) {
   1272 		rc = (long)connection_operation( ctx, cri.op );
   1273 	} else if ( cri.func ) {
   1274 		rc = (long)cri.func( ctx, cri.arg );
   1275 	}
   1276 
   1277 	return (void*)(long)rc;
   1278 }
   1279 
   1280 int connection_read_activate( ber_socket_t s )
   1281 {
   1282 	int rc;
   1283 
   1284 	/*
   1285 	 * suspend reading on this file descriptor until a connection processing
   1286 	 * thread reads data on it. Otherwise the listener thread will repeatedly
   1287 	 * submit the same event on it to the pool.
   1288 	 */
   1289 	rc = slapd_clr_read( s, 0 );
   1290 	if ( rc )
   1291 		return rc;
   1292 
   1293 	rc = ldap_pvt_thread_pool_submit( &connection_pool,
   1294 		connection_read_thread, (void *)(long)s );
   1295 
   1296 	if( rc != 0 ) {
   1297 		Debug( LDAP_DEBUG_ANY,
   1298 			"connection_read_activate(%d): submit failed (%d)\n",
   1299 			s, rc );
   1300 	}
   1301 
   1302 	return rc;
   1303 }
   1304 
   1305 static int
   1306 connection_read( ber_socket_t s, conn_readinfo *cri )
   1307 {
   1308 	int rc = 0;
   1309 	Connection *c;
   1310 
   1311 	assert( connections != NULL );
   1312 
   1313 	/* get (locked) connection */
   1314 	c = connection_get( s );
   1315 
   1316 	if( c == NULL ) {
   1317 		Debug( LDAP_DEBUG_ANY,
   1318 			"connection_read(%ld): no connection!\n",
   1319 			(long) s );
   1320 
   1321 		return -1;
   1322 	}
   1323 
   1324 	c->c_n_read++;
   1325 
   1326 	if( c->c_conn_state == SLAP_C_CLOSING ) {
   1327 		Debug( LDAP_DEBUG_CONNS,
   1328 			"connection_read(%d): closing, ignoring input for id=%lu\n",
   1329 			s, c->c_connid );
   1330 		connection_return( c );
   1331 		return 0;
   1332 	}
   1333 
   1334 	if ( c->c_conn_state == SLAP_C_CLIENT ) {
   1335 		cri->func = c->c_clientfunc;
   1336 		cri->arg = c->c_clientarg;
   1337 		/* read should already be cleared */
   1338 		connection_return( c );
   1339 		return 0;
   1340 	}
   1341 
   1342 	Debug( LDAP_DEBUG_TRACE,
   1343 		"connection_read(%d): checking for input on id=%lu\n",
   1344 		s, c->c_connid );
   1345 
   1346 #ifdef HAVE_TLS
   1347 	if ( c->c_is_tls && c->c_needs_tls_accept ) {
   1348 		rc = ldap_pvt_tls_accept( c->c_sb, slap_tls_ctx );
   1349 		if ( rc < 0 ) {
   1350 			Debug( LDAP_DEBUG_TRACE,
   1351 				"connection_read(%d): TLS accept failure "
   1352 				"error=%d id=%lu, closing\n",
   1353 				s, rc, c->c_connid );
   1354 
   1355 			c->c_needs_tls_accept = 0;
   1356 			/* c_mutex is locked */
   1357 			connection_closing( c, "TLS negotiation failure" );
   1358 			connection_close( c );
   1359 			connection_return( c );
   1360 			return 0;
   1361 
   1362 		} else if ( rc == 0 ) {
   1363 			void *ssl;
   1364 			struct berval authid = BER_BVNULL;
   1365 			char msgbuf[32];
   1366 
   1367 			c->c_needs_tls_accept = 0;
   1368 
   1369 			/* we need to let SASL know */
   1370 			ssl = ldap_pvt_tls_sb_ctx( c->c_sb );
   1371 
   1372 			c->c_tls_ssf = (slap_ssf_t) ldap_pvt_tls_get_strength( ssl );
   1373 			if( c->c_tls_ssf > c->c_ssf ) {
   1374 				c->c_ssf = c->c_tls_ssf;
   1375 			}
   1376 
   1377 			rc = dnX509peerNormalize( ssl, &authid );
   1378 			if ( rc != LDAP_SUCCESS ) {
   1379 				Debug( LDAP_DEBUG_TRACE, "connection_read(%d): "
   1380 					"unable to get TLS client DN, error=%d id=%lu\n",
   1381 					s, rc, c->c_connid );
   1382 			}
   1383 			sprintf(msgbuf, "tls_ssf=%u ssf=%u", c->c_tls_ssf, c->c_ssf);
   1384 			Debug( LDAP_DEBUG_STATS,
   1385 				"conn=%lu fd=%d TLS established %s tls_proto=%s tls_cipher=%s\n",
   1386 			    c->c_connid, (int) s,
   1387 				msgbuf, ldap_pvt_tls_get_version( ssl ), ldap_pvt_tls_get_cipher( ssl ));
   1388 			slap_sasl_external( c, c->c_tls_ssf, &authid );
   1389 			if ( authid.bv_val ) free( authid.bv_val );
   1390 
   1391 			slap_sasl_cbinding( c, ssl );
   1392 
   1393 		} else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb,
   1394 			LBER_SB_OPT_NEEDS_WRITE, NULL )) {	/* need to retry */
   1395 			slapd_set_write( s, 1 );
   1396 			connection_return( c );
   1397 			return 0;
   1398 		}
   1399 
   1400 		/* if success and data is ready, fall thru to data input loop */
   1401 		if( !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
   1402 		{
   1403 			slapd_set_read( s, 1 );
   1404 			connection_return( c );
   1405 			return 0;
   1406 		}
   1407 	}
   1408 #endif
   1409 
   1410 #ifdef HAVE_CYRUS_SASL
   1411 	if ( c->c_sasl_layers ) {
   1412 		/* If previous layer is not removed yet, give up for now */
   1413 		if ( !c->c_sasl_sockctx ) {
   1414 			slapd_set_read( s, 1 );
   1415 			connection_return( c );
   1416 			return 0;
   1417 		}
   1418 
   1419 		c->c_sasl_layers = 0;
   1420 
   1421 		rc = ldap_pvt_sasl_install( c->c_sb, c->c_sasl_sockctx );
   1422 		if( rc != LDAP_SUCCESS ) {
   1423 			Debug( LDAP_DEBUG_TRACE,
   1424 				"connection_read(%d): SASL install error "
   1425 				"error=%d id=%lu, closing\n",
   1426 				s, rc, c->c_connid );
   1427 
   1428 			/* c_mutex is locked */
   1429 			connection_closing( c, "SASL layer install failure" );
   1430 			connection_close( c );
   1431 			connection_return( c );
   1432 			return 0;
   1433 		}
   1434 	}
   1435 #endif
   1436 
   1437 #define CONNECTION_INPUT_LOOP 1
   1438 /* #define	DATA_READY_LOOP 1 */
   1439 
   1440 	do {
   1441 		/* How do we do this without getting into a busy loop ? */
   1442 		rc = connection_input( c, cri );
   1443 	}
   1444 #ifdef DATA_READY_LOOP
   1445 	while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ));
   1446 #elif defined CONNECTION_INPUT_LOOP
   1447 	while(!rc);
   1448 #else
   1449 	while(0);
   1450 #endif
   1451 
   1452 	if( rc < 0 ) {
   1453 		Debug( LDAP_DEBUG_CONNS,
   1454 			"connection_read(%d): input error=%d id=%lu, closing.\n",
   1455 			s, rc, c->c_connid );
   1456 
   1457 		/* c_mutex is locked */
   1458 		connection_closing( c, conn_lost_str );
   1459 		connection_close( c );
   1460 		connection_return( c );
   1461 		return 0;
   1462 	}
   1463 
   1464 	if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
   1465 		slapd_set_write( s, 0 );
   1466 	}
   1467 
   1468 	slapd_set_read( s, 1 );
   1469 	connection_return( c );
   1470 
   1471 	return 0;
   1472 }
   1473 
   1474 static int
   1475 connection_input( Connection *conn , conn_readinfo *cri )
   1476 {
   1477 	Operation *op;
   1478 	ber_tag_t	tag;
   1479 	ber_len_t	len;
   1480 	ber_int_t	msgid;
   1481 	BerElement	*ber;
   1482 	int 		rc;
   1483 #ifdef LDAP_CONNECTIONLESS
   1484 	Sockaddr	peeraddr;
   1485 	char 		*cdn = NULL;
   1486 #endif
   1487 	char *defer = NULL;
   1488 	void *ctx;
   1489 
   1490 	if ( conn->c_currentber == NULL &&
   1491 		( conn->c_currentber = ber_alloc()) == NULL )
   1492 	{
   1493 		Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n" );
   1494 		return -1;
   1495 	}
   1496 
   1497 	sock_errset(0);
   1498 
   1499 #ifdef LDAP_CONNECTIONLESS
   1500 	if ( conn->c_is_udp ) {
   1501 #if defined(LDAP_PF_INET6)
   1502 		char peername[sizeof("IP=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535")];
   1503 		char addr[INET6_ADDRSTRLEN];
   1504 #else
   1505 		char peername[sizeof("IP=255.255.255.255:65336")];
   1506 		char addr[INET_ADDRSTRLEN];
   1507 #endif
   1508 		const char *peeraddr_string = NULL;
   1509 
   1510 		len = ber_int_sb_read(conn->c_sb, &peeraddr, sizeof(Sockaddr));
   1511 		if (len != sizeof(Sockaddr)) return 1;
   1512 
   1513 #if defined(LDAP_PF_INET6)
   1514 		if (peeraddr.sa_addr.sa_family == AF_INET6) {
   1515 			if ( IN6_IS_ADDR_V4MAPPED(&peeraddr.sa_in6_addr.sin6_addr) ) {
   1516 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
   1517 				peeraddr_string = inet_ntop( AF_INET,
   1518 				   ((struct in_addr *)&peeraddr.sa_in6_addr.sin6_addr.s6_addr[12]),
   1519 				   addr, sizeof(addr) );
   1520 #else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
   1521 				peeraddr_string = inet_ntoa( *((struct in_addr *)
   1522 					&peeraddr.sa_in6_addr.sin6_addr.s6_addr[12]) );
   1523 #endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
   1524 				if ( !peeraddr_string ) peeraddr_string = SLAP_STRING_UNKNOWN;
   1525 				sprintf( peername, "IP=%s:%d", peeraddr_string,
   1526 					(unsigned) ntohs( peeraddr.sa_in6_addr.sin6_port ) );
   1527 			} else {
   1528 				peeraddr_string = inet_ntop( AF_INET6,
   1529 				      &peeraddr.sa_in6_addr.sin6_addr,
   1530 				      addr, sizeof addr );
   1531 				if ( !peeraddr_string ) peeraddr_string = SLAP_STRING_UNKNOWN;
   1532 				sprintf( peername, "IP=[%s]:%d", peeraddr_string,
   1533 					 (unsigned) ntohs( peeraddr.sa_in6_addr.sin6_port ) );
   1534 			}
   1535 		} else
   1536 #endif
   1537 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
   1538 		{
   1539 			peeraddr_string = inet_ntop( AF_INET, &peeraddr.sa_in_addr.sin_addr,
   1540 			   addr, sizeof(addr) );
   1541 #else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
   1542 			peeraddr_string = inet_ntoa( peeraddr.sa_in_addr.sin_addr );
   1543 #endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
   1544 			sprintf( peername, "IP=%s:%d",
   1545 				 peeraddr_string,
   1546 				(unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) );
   1547 		}
   1548 		Debug( LDAP_DEBUG_STATS,
   1549 			"conn=%lu UDP request from %s (%s) accepted.\n",
   1550 			conn->c_connid, peername, conn->c_sock_name.bv_val );
   1551 	}
   1552 #endif
   1553 
   1554 	tag = ber_get_next( conn->c_sb, &len, conn->c_currentber );
   1555 	if ( tag != LDAP_TAG_MESSAGE ) {
   1556 		int err = sock_errno();
   1557 
   1558 		if ( err != EWOULDBLOCK && err != EAGAIN ) {
   1559 			char ebuf[128];
   1560 			/* log, close and send error */
   1561 			Debug( LDAP_DEBUG_TRACE,
   1562 				"ber_get_next on fd %d failed errno=%d (%s)\n",
   1563 			conn->c_sd, err, sock_errstr(err, ebuf, sizeof(ebuf)) );
   1564 			ber_free( conn->c_currentber, 1 );
   1565 			conn->c_currentber = NULL;
   1566 
   1567 			return -2;
   1568 		}
   1569 		return 1;
   1570 	}
   1571 
   1572 	ber = conn->c_currentber;
   1573 	conn->c_currentber = NULL;
   1574 
   1575 	if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
   1576 		/* log, close and send error */
   1577 		Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag );
   1578 		ber_free( ber, 1 );
   1579 		return -1;
   1580 	}
   1581 
   1582 	if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
   1583 		/* log, close and send error */
   1584 		Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag );
   1585 		ber_free( ber, 1 );
   1586 
   1587 		return -1;
   1588 	}
   1589 
   1590 #ifdef LDAP_CONNECTIONLESS
   1591 	if( conn->c_is_udp ) {
   1592 		if( tag == LBER_OCTETSTRING ) {
   1593 			if ( (tag = ber_get_stringa( ber, &cdn )) != LBER_ERROR )
   1594 				tag = ber_peek_tag( ber, &len );
   1595 		}
   1596 		if( tag != LDAP_REQ_ABANDON && tag != LDAP_REQ_SEARCH ) {
   1597 			Debug( LDAP_DEBUG_ANY, "invalid req for UDP 0x%lx\n", tag );
   1598 			ber_free( ber, 1 );
   1599 			return 0;
   1600 		}
   1601 	}
   1602 #endif
   1603 
   1604 	if(tag == LDAP_REQ_BIND) {
   1605 		/* immediately abandon all existing operations upon BIND */
   1606 		connection_abandon( conn );
   1607 	}
   1608 
   1609 	ctx = cri->ctx;
   1610 	op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++, ctx );
   1611 
   1612 	Debug( LDAP_DEBUG_TRACE, "op tag 0x%lx, time %ld\n", tag,
   1613 		(long) op->o_time );
   1614 
   1615 	op->o_conn = conn;
   1616 	/* clear state if the connection is being reused from inactive */
   1617 	if ( conn->c_conn_state == SLAP_C_INACTIVE ) {
   1618 		memset( &conn->c_pagedresults_state, 0,
   1619 			sizeof( conn->c_pagedresults_state ) );
   1620 	}
   1621 
   1622 	op->o_res_ber = NULL;
   1623 
   1624 #ifdef LDAP_CONNECTIONLESS
   1625 	if (conn->c_is_udp) {
   1626 		if ( cdn ) {
   1627 			ber_str2bv( cdn, 0, 1, &op->o_dn );
   1628 			op->o_protocol = LDAP_VERSION2;
   1629 		}
   1630 		op->o_res_ber = ber_alloc_t( LBER_USE_DER );
   1631 		if (op->o_res_ber == NULL) return 1;
   1632 
   1633 		rc = ber_write( op->o_res_ber, (char *)&peeraddr,
   1634 			sizeof(struct sockaddr), 0 );
   1635 
   1636 		if (rc != sizeof(struct sockaddr)) {
   1637 			Debug( LDAP_DEBUG_ANY, "ber_write failed\n" );
   1638 			return 1;
   1639 		}
   1640 
   1641 		if (op->o_protocol == LDAP_VERSION2) {
   1642 			rc = ber_printf(op->o_res_ber, "{is{" /*}}*/, op->o_msgid, "");
   1643 			if (rc == -1) {
   1644 				Debug( LDAP_DEBUG_ANY, "ber_write failed\n" );
   1645 				return rc;
   1646 			}
   1647 		}
   1648 	}
   1649 #endif /* LDAP_CONNECTIONLESS */
   1650 
   1651 	rc = 0;
   1652 
   1653 	/* Don't process requests when the conn is in the middle of a
   1654 	 * Bind, or if it's closing. Also, don't let any single conn
   1655 	 * use up all the available threads, and don't execute if we're
   1656 	 * currently blocked on output. And don't execute if there are
   1657 	 * already pending ops, let them go first.  Abandon operations
   1658 	 * get exceptions to some, but not all, cases.
   1659 	 */
   1660 	switch( tag ){
   1661 	default:
   1662 		/* Abandon and Unbind are exempt from these checks */
   1663 		if (conn->c_conn_state == SLAP_C_CLOSING) {
   1664 			defer = "closing";
   1665 			break;
   1666 		} else if (conn->c_writewaiter) {
   1667 			defer = "awaiting write";
   1668 			break;
   1669 		} else if (conn->c_n_ops_pending) {
   1670 			defer = "pending operations";
   1671 			break;
   1672 		}
   1673 		/* FALLTHRU */
   1674 	case LDAP_REQ_ABANDON:
   1675 		/* Unbind is exempt from these checks */
   1676 		if (conn->c_n_ops_executing >= connection_pool_max/2) {
   1677 			defer = "too many executing";
   1678 			break;
   1679 		} else if (conn->c_conn_state == SLAP_C_BINDING) {
   1680 			defer = "binding";
   1681 			break;
   1682 		}
   1683 		/* FALLTHRU */
   1684 	case LDAP_REQ_UNBIND:
   1685 		break;
   1686 	}
   1687 
   1688 	if( defer ) {
   1689 		int max = conn->c_dn.bv_len
   1690 			? slap_conn_max_pending_auth
   1691 			: slap_conn_max_pending;
   1692 
   1693 		Debug( LDAP_DEBUG_ANY,
   1694 			"connection_input: conn=%lu deferring operation: %s\n",
   1695 			conn->c_connid, defer );
   1696 		conn->c_n_ops_pending++;
   1697 		LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next );
   1698 		rc = ( conn->c_n_ops_pending > max ) ? -1 : 0;
   1699 
   1700 	} else {
   1701 		conn->c_n_ops_executing++;
   1702 
   1703 		/*
   1704 		 * The first op will be processed in the same thread context,
   1705 		 * as long as there is only one op total.
   1706 		 * Subsequent ops will be submitted to the pool by
   1707 		 * calling connection_op_activate()
   1708 		 */
   1709 		if ( cri->op == NULL ) {
   1710 			/* the first incoming request */
   1711 			connection_op_queue( op );
   1712 			cri->op = op;
   1713 		} else {
   1714 			if ( !cri->nullop ) {
   1715 				cri->nullop = 1;
   1716 				rc = ldap_pvt_thread_pool_submit( &connection_pool,
   1717 					connection_operation, (void *) cri->op );
   1718 			}
   1719 			connection_op_activate( op );
   1720 		}
   1721 	}
   1722 
   1723 	return rc;
   1724 }
   1725 
   1726 static int
   1727 connection_resched( Connection *conn )
   1728 {
   1729 	Operation *op;
   1730 
   1731 	if( conn->c_writewaiter )
   1732 		return 0;
   1733 
   1734 	if( conn->c_conn_state == SLAP_C_CLOSING ) {
   1735 		Debug( LDAP_DEBUG_CONNS, "connection_resched: "
   1736 			"attempting closing conn=%lu sd=%d\n",
   1737 			conn->c_connid, conn->c_sd );
   1738 		connection_close( conn );
   1739 		return 0;
   1740 	}
   1741 
   1742 	if( conn->c_conn_state != SLAP_C_ACTIVE ) {
   1743 		/* other states need different handling */
   1744 		return 0;
   1745 	}
   1746 
   1747 	while ((op = LDAP_STAILQ_FIRST( &conn->c_pending_ops )) != NULL) {
   1748 		if ( conn->c_n_ops_executing > connection_pool_max/2 ) break;
   1749 
   1750 		LDAP_STAILQ_REMOVE_HEAD( &conn->c_pending_ops, o_next );
   1751 		LDAP_STAILQ_NEXT(op, o_next) = NULL;
   1752 
   1753 		/* pending operations should not be marked for abandonment */
   1754 		assert(!op->o_abandon);
   1755 
   1756 		conn->c_n_ops_pending--;
   1757 		conn->c_n_ops_executing++;
   1758 
   1759 		connection_op_activate( op );
   1760 
   1761 		if ( conn->c_conn_state == SLAP_C_BINDING ) break;
   1762 	}
   1763 	return 0;
   1764 }
   1765 
   1766 static void
   1767 connection_init_log_prefix( Operation *op )
   1768 {
   1769 	if ( op->o_connid == (unsigned long)(-1) ) {
   1770 		snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ),
   1771 			"conn=-1 op=%lu", op->o_opid );
   1772 
   1773 	} else {
   1774 		snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ),
   1775 			"conn=%lu op=%lu", op->o_connid, op->o_opid );
   1776 	}
   1777 }
   1778 
   1779 static int connection_bind_cleanup_cb( Operation *op, SlapReply *rs )
   1780 {
   1781 	op->o_conn->c_sasl_bindop = NULL;
   1782 
   1783 	ch_free( op->o_callback );
   1784 	op->o_callback = NULL;
   1785 
   1786 	return SLAP_CB_CONTINUE;
   1787 }
   1788 
   1789 static int connection_bind_cb( Operation *op, SlapReply *rs )
   1790 {
   1791 	ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
   1792 	op->o_conn->c_sasl_bind_in_progress =
   1793 		( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS );
   1794 
   1795 	/* Moved here from bind.c due to ITS#4158 */
   1796 	op->o_conn->c_sasl_bindop = NULL;
   1797 	if ( op->orb_method == LDAP_AUTH_SASL ) {
   1798 		if( rs->sr_err == LDAP_SUCCESS ) {
   1799 			ber_dupbv(&op->o_conn->c_dn, &op->orb_edn);
   1800 			if( !BER_BVISEMPTY( &op->orb_edn ) ) {
   1801 				/* edn is always normalized already */
   1802 				ber_dupbv( &op->o_conn->c_ndn, &op->o_conn->c_dn );
   1803 			}
   1804 			op->o_tmpfree( op->orb_edn.bv_val, op->o_tmpmemctx );
   1805 			BER_BVZERO( &op->orb_edn );
   1806 			op->o_conn->c_authmech = op->o_conn->c_sasl_bind_mech;
   1807 			BER_BVZERO( &op->o_conn->c_sasl_bind_mech );
   1808 
   1809 			op->o_conn->c_sasl_ssf = op->orb_ssf;
   1810 			if( op->orb_ssf > op->o_conn->c_ssf ) {
   1811 				op->o_conn->c_ssf = op->orb_ssf;
   1812 			}
   1813 
   1814 			if( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
   1815 				ber_len_t max = sockbuf_max_incoming_auth;
   1816 				ber_sockbuf_ctrl( op->o_conn->c_sb,
   1817 					LBER_SB_OPT_SET_MAX_INCOMING, &max );
   1818 			}
   1819 
   1820 			/* log authorization identity */
   1821 			Debug( LDAP_DEBUG_STATS,
   1822 				"%s BIND dn=\"%s\" mech=%s bind_ssf=%d ssf=%d\n",
   1823 				op->o_log_prefix,
   1824 				BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
   1825 				op->o_conn->c_authmech.bv_val,
   1826 				op->orb_ssf, op->o_conn->c_ssf );
   1827 
   1828 			Debug( LDAP_DEBUG_TRACE,
   1829 				"do_bind: SASL/%s bind: dn=\"%s\" bind_ssf=%d\n",
   1830 				op->o_conn->c_authmech.bv_val,
   1831 				BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
   1832 				op->orb_ssf );
   1833 
   1834 		} else if ( rs->sr_err != LDAP_SASL_BIND_IN_PROGRESS ) {
   1835 			if ( !BER_BVISNULL( &op->o_conn->c_sasl_bind_mech ) ) {
   1836 				free( op->o_conn->c_sasl_bind_mech.bv_val );
   1837 				BER_BVZERO( &op->o_conn->c_sasl_bind_mech );
   1838 			}
   1839 		}
   1840 	}
   1841 	ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
   1842 
   1843 	ch_free( op->o_callback );
   1844 	op->o_callback = NULL;
   1845 
   1846 	return SLAP_CB_CONTINUE;
   1847 }
   1848 
   1849 static void connection_op_queue( Operation *op )
   1850 {
   1851 	ber_tag_t tag = op->o_tag;
   1852 
   1853 	if (tag == LDAP_REQ_BIND) {
   1854 		slap_callback *sc = ch_calloc( 1, sizeof( slap_callback ));
   1855 		sc->sc_response = connection_bind_cb;
   1856 		sc->sc_cleanup = connection_bind_cleanup_cb;
   1857 		sc->sc_next = op->o_callback;
   1858 		op->o_callback = sc;
   1859 		op->o_conn->c_conn_state = SLAP_C_BINDING;
   1860 	}
   1861 
   1862 	if (!op->o_dn.bv_len) {
   1863 		op->o_authz = op->o_conn->c_authz;
   1864 		if ( BER_BVISNULL( &op->o_conn->c_sasl_authz_dn )) {
   1865 			ber_dupbv( &op->o_dn, &op->o_conn->c_dn );
   1866 			ber_dupbv( &op->o_ndn, &op->o_conn->c_ndn );
   1867 		} else {
   1868 			ber_dupbv( &op->o_dn, &op->o_conn->c_sasl_authz_dn );
   1869 			ber_dupbv( &op->o_ndn, &op->o_conn->c_sasl_authz_dn );
   1870 		}
   1871 	}
   1872 
   1873 	op->o_authtype = op->o_conn->c_authtype;
   1874 	ber_dupbv( &op->o_authmech, &op->o_conn->c_authmech );
   1875 
   1876 	if (!op->o_protocol) {
   1877 		op->o_protocol = op->o_conn->c_protocol
   1878 			? op->o_conn->c_protocol : LDAP_VERSION3;
   1879 	}
   1880 
   1881 	if (op->o_conn->c_conn_state == SLAP_C_INACTIVE &&
   1882 		op->o_protocol > LDAP_VERSION2)
   1883 	{
   1884 		op->o_conn->c_conn_state = SLAP_C_ACTIVE;
   1885 	}
   1886 
   1887 	op->o_connid = op->o_conn->c_connid;
   1888 	connection_init_log_prefix( op );
   1889 
   1890 	LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next );
   1891 }
   1892 
   1893 static int connection_op_activate( Operation *op )
   1894 {
   1895 	int rc;
   1896 
   1897 	connection_op_queue( op );
   1898 
   1899 	rc = ldap_pvt_thread_pool_submit( &connection_pool,
   1900 		connection_operation, (void *) op );
   1901 
   1902 	if ( rc != 0 ) {
   1903 		Debug( LDAP_DEBUG_ANY,
   1904 			"connection_op_activate: submit failed (%d) for conn=%lu\n",
   1905 			rc, op->o_connid );
   1906 		/* should move op to pending list */
   1907 	}
   1908 
   1909 	return rc;
   1910 }
   1911 
   1912 int connection_write(ber_socket_t s)
   1913 {
   1914 	Connection *c;
   1915 	Operation *op;
   1916 	int wantwrite;
   1917 
   1918 	assert( connections != NULL );
   1919 
   1920 	c = connection_get( s );
   1921 	if( c == NULL ) {
   1922 		Debug( LDAP_DEBUG_ANY,
   1923 			"connection_write(%ld): no connection!\n",
   1924 			(long)s );
   1925 		return -1;
   1926 	}
   1927 
   1928 	slapd_clr_write( s, 0 );
   1929 
   1930 #ifdef HAVE_TLS
   1931 	if ( c->c_is_tls && c->c_needs_tls_accept ) {
   1932 		connection_return( c );
   1933 		connection_read_activate( s );
   1934 		return 0;
   1935 	}
   1936 #endif
   1937 
   1938 	c->c_n_write++;
   1939 
   1940 	Debug( LDAP_DEBUG_TRACE,
   1941 		"connection_write(%d): waking output for id=%lu\n",
   1942 		s, c->c_connid );
   1943 
   1944 	wantwrite = ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL );
   1945 	if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL )) {
   1946 		/* don't wakeup twice */
   1947 		slapd_set_read( s, !wantwrite );
   1948 	}
   1949 	if ( wantwrite ) {
   1950 		slapd_set_write( s, 1 );
   1951 	}
   1952 
   1953 	/* If there are ops pending because of a writewaiter,
   1954 	 * start one up.
   1955 	 */
   1956 	while ((op = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
   1957 		if ( !c->c_writewaiter ) break;
   1958 		if ( c->c_n_ops_executing > connection_pool_max/2 ) break;
   1959 
   1960 		LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
   1961 		LDAP_STAILQ_NEXT(op, o_next) = NULL;
   1962 
   1963 		/* pending operations should not be marked for abandonment */
   1964 		assert(!op->o_abandon);
   1965 
   1966 		c->c_n_ops_pending--;
   1967 		c->c_n_ops_executing++;
   1968 
   1969 		connection_op_activate( op );
   1970 
   1971 		break;
   1972 	}
   1973 
   1974 	connection_return( c );
   1975 	return 0;
   1976 }
   1977 
   1978 void connection_write_resume( Connection *c )
   1979 {
   1980 	Operation *op;
   1981 
   1982 	ldap_pvt_thread_mutex_lock( &c->c_mutex );
   1983 	/* If there are ops pending because of a writewaiter,
   1984 	 * start one up.
   1985 	 */
   1986 	while ((op = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
   1987 		if ( c->c_n_ops_executing > connection_pool_max/2 ) break;
   1988 
   1989 		LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
   1990 		LDAP_STAILQ_NEXT(op, o_next) = NULL;
   1991 
   1992 		/* pending operations should not be marked for abandonment */
   1993 		assert(!op->o_abandon);
   1994 
   1995 		c->c_n_ops_pending--;
   1996 		c->c_n_ops_executing++;
   1997 
   1998 		connection_op_activate( op );
   1999 
   2000 		break;
   2001 	}
   2002 
   2003 	connection_return( c );
   2004 }
   2005 
   2006 #ifdef LDAP_SLAPI
   2007 typedef struct conn_fake_extblock {
   2008 	void *eb_conn;
   2009 	void *eb_op;
   2010 } conn_fake_extblock;
   2011 
   2012 static void
   2013 connection_fake_destroy(
   2014 	void *key,
   2015 	void *data )
   2016 {
   2017 	Connection conn = {0};
   2018 	Operation op = {0};
   2019 	Opheader ohdr = {0};
   2020 
   2021 	conn_fake_extblock *eb = data;
   2022 
   2023 	op.o_hdr = &ohdr;
   2024 	op.o_hdr->oh_extensions = eb->eb_op;
   2025 	conn.c_extensions = eb->eb_conn;
   2026 	op.o_conn = &conn;
   2027 	conn.c_connid = -1;
   2028 	op.o_connid = -1;
   2029 
   2030 	ber_memfree_x( eb, NULL );
   2031 	slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, &op );
   2032 	slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, &conn );
   2033 }
   2034 #endif
   2035 
   2036 void
   2037 connection_fake_init(
   2038 	Connection *conn,
   2039 	OperationBuffer *opbuf,
   2040 	void *ctx )
   2041 {
   2042 	connection_fake_init2( conn, opbuf, ctx, 1 );
   2043 }
   2044 
   2045 void
   2046 operation_fake_init(
   2047 	Connection *conn,
   2048 	Operation *op,
   2049 	void *ctx,
   2050 	int newmem )
   2051 {
   2052 	/* set memory context */
   2053 	op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx,
   2054 		newmem );
   2055 	op->o_tmpmfuncs = &slap_sl_mfuncs;
   2056 	op->o_threadctx = ctx;
   2057 	op->o_tid = ldap_pvt_thread_pool_tid( ctx );
   2058 
   2059 	op->o_counters = &slap_counters;
   2060 	op->o_conn = conn;
   2061 	op->o_connid = op->o_conn->c_connid;
   2062 	connection_init_log_prefix( op );
   2063 }
   2064 
   2065 
   2066 void
   2067 connection_fake_init2(
   2068 	Connection *conn,
   2069 	OperationBuffer *opbuf,
   2070 	void *ctx,
   2071 	int newmem )
   2072 {
   2073 	Operation *op = (Operation *) opbuf;
   2074 
   2075 	conn->c_connid = -1;
   2076 	conn->c_conn_idx = -1;
   2077 	conn->c_send_ldap_result = slap_send_ldap_result;
   2078 	conn->c_send_search_entry = slap_send_search_entry;
   2079 	conn->c_send_search_reference = slap_send_search_reference;
   2080 	conn->c_send_ldap_extended = slap_send_ldap_extended;
   2081 	conn->c_send_ldap_intermediate = slap_send_ldap_intermediate;
   2082 	conn->c_listener = (Listener *)&dummy_list;
   2083 	conn->c_peer_domain = slap_empty_bv;
   2084 	conn->c_peer_name = slap_empty_bv;
   2085 
   2086 	memset( opbuf, 0, sizeof( *opbuf ));
   2087 	op->o_hdr = &opbuf->ob_hdr;
   2088 	op->o_controls = opbuf->ob_controls;
   2089 
   2090 	operation_fake_init( conn, op, ctx, newmem );
   2091 
   2092 #ifdef LDAP_SLAPI
   2093 	if ( slapi_plugins_used ) {
   2094 		conn_fake_extblock *eb;
   2095 		void *ebx = NULL;
   2096 
   2097 		/* Use thread keys to make sure these eventually get cleaned up */
   2098 		if ( ldap_pvt_thread_pool_getkey( ctx, (void *)connection_fake_init,
   2099 				&ebx, NULL )) {
   2100 			eb = ch_malloc( sizeof( *eb ));
   2101 			slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
   2102 			slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op );
   2103 			eb->eb_conn = conn->c_extensions;
   2104 			eb->eb_op = op->o_hdr->oh_extensions;
   2105 			ldap_pvt_thread_pool_setkey( ctx, (void *)connection_fake_init,
   2106 				eb, connection_fake_destroy, NULL, NULL );
   2107 		} else {
   2108 			eb = ebx;
   2109 			conn->c_extensions = eb->eb_conn;
   2110 			op->o_hdr->oh_extensions = eb->eb_op;
   2111 		}
   2112 	}
   2113 #endif /* LDAP_SLAPI */
   2114 
   2115 	slap_op_time( &op->o_time, &op->o_tincr );
   2116 }
   2117 
   2118 void
   2119 connection_assign_nextid( Connection *conn )
   2120 {
   2121 	ldap_pvt_thread_mutex_lock( &conn_nextid_mutex );
   2122 	conn->c_connid = conn_nextid++;
   2123 	ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex );
   2124 }
   2125