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