]> git.sur5r.net Git - openldap/blob - servers/slapd/connection.c
ITS#2959: provide reason for deferring operation in log message
[openldap] / servers / slapd / connection.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2004 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms are permitted
19  * provided that this notice is preserved and that due credit is given
20  * to the University of Michigan at Ann Arbor. The name of the University
21  * may not be used to endorse or promote products derived from this
22  * software without specific prior written permission. This software
23  * is provided ``as is'' without express or implied warranty.
24  */
25
26 #include "portable.h"
27
28 #include <stdio.h>
29 #include <limits.h>
30
31 #include <ac/socket.h>
32 #include <ac/errno.h>
33 #include <ac/string.h>
34 #include <ac/time.h>
35 #include <ac/unistd.h>
36
37 #include "ldap_pvt.h"
38 #include "lutil.h"
39 #include "slap.h"
40
41 #ifdef LDAP_SLAPI
42 #include "slapi/slapi.h"
43 #endif
44
45 /* protected by connections_mutex */
46 static ldap_pvt_thread_mutex_t connections_mutex;
47 static Connection *connections = NULL;
48 static unsigned long conn_nextid = 0;
49
50 /* structure state (protected by connections_mutex) */
51 #define SLAP_C_UNINITIALIZED    0x00    /* MUST BE ZERO (0) */
52 #define SLAP_C_UNUSED                   0x01
53 #define SLAP_C_USED                             0x02
54
55 /* connection state (protected by c_mutex ) */
56 #define SLAP_C_INVALID                  0x00    /* MUST BE ZERO (0) */
57 #define SLAP_C_INACTIVE                 0x01    /* zero threads */
58 #define SLAP_C_ACTIVE                   0x02    /* one or more threads */
59 #define SLAP_C_BINDING                  0x03    /* binding */
60 #define SLAP_C_CLOSING                  0x04    /* closing */
61 #define SLAP_C_CLIENT                   0x05    /* outbound client conn */
62
63 const char *
64 connection_state2str( int state )
65 {
66         switch( state ) {
67         case SLAP_C_INVALID:    return "!";
68         case SLAP_C_INACTIVE:   return "|";
69         case SLAP_C_ACTIVE:             return "";
70         case SLAP_C_BINDING:    return "B";
71         case SLAP_C_CLOSING:    return "C";
72         case SLAP_C_CLIENT:             return "L";
73         }
74
75         return "?";
76 }
77
78 static Connection* connection_get( ber_socket_t s );
79
80 static int connection_input( Connection *c );
81 static void connection_close( Connection *c );
82
83 static int connection_op_activate( Operation *op );
84 static int connection_resched( Connection *conn );
85 static void connection_abandon( Connection *conn );
86 static void connection_destroy( Connection *c );
87
88 static ldap_pvt_thread_start_t connection_operation;
89
90 /*
91  * Initialize connection management infrastructure.
92  */
93 int connections_init(void)
94 {
95         assert( connections == NULL );
96
97         if( connections != NULL) {
98 #ifdef NEW_LOGGING
99                 LDAP_LOG( CONNECTION, INFO,
100                         "connections_init: already initialized.\n", 0, 0, 0 );
101 #else
102                 Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
103                         0, 0, 0 );
104 #endif
105                 return -1;
106         }
107
108         /* should check return of every call */
109         ldap_pvt_thread_mutex_init( &connections_mutex );
110
111         connections = (Connection *) ch_calloc( dtblsize, sizeof(Connection) );
112
113         if( connections == NULL ) {
114 #ifdef NEW_LOGGING
115                 LDAP_LOG( CONNECTION, ERR,
116                         "connections_init: allocation (%d * %ld) of connection "
117                         "array failed\n", dtblsize, (long) sizeof(Connection), 0 );
118 #else
119                 Debug( LDAP_DEBUG_ANY,
120                         "connections_init: allocation (%d*%ld) of connection array failed\n",
121                         dtblsize, (long) sizeof(Connection), 0 );
122 #endif
123                 return -1;
124         }
125
126         assert( connections[0].c_struct_state == SLAP_C_UNINITIALIZED );
127         assert( connections[dtblsize-1].c_struct_state == SLAP_C_UNINITIALIZED );
128
129         /*
130          * per entry initialization of the Connection array initialization
131          * will be done by connection_init()
132          */ 
133
134         return 0;
135 }
136
137 /*
138  * Destroy connection management infrastructure.
139  */
140 int connections_destroy(void)
141 {
142         ber_socket_t i;
143
144         /* should check return of every call */
145
146         if( connections == NULL) {
147 #ifdef NEW_LOGGING
148                 LDAP_LOG( CONNECTION, INFO,
149                         "connections_destroy: nothing to destroy.\n", 0, 0, 0 );
150 #else
151                 Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n",
152                         0, 0, 0 );
153 #endif
154                 return -1;
155         }
156
157         for ( i = 0; i < dtblsize; i++ ) {
158                 if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) {
159                         ber_sockbuf_free( connections[i].c_sb );
160                         ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex );
161                         ldap_pvt_thread_mutex_destroy( &connections[i].c_write_mutex );
162                         ldap_pvt_thread_cond_destroy( &connections[i].c_write_cv );
163 #ifdef LDAP_SLAPI
164                         if ( slapi_plugins_used ) {
165                                 slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, &connections[i] );
166                         }
167 #endif
168                 }
169         }
170
171         free( connections );
172         connections = NULL;
173
174         ldap_pvt_thread_mutex_destroy( &connections_mutex );
175         return 0;
176 }
177
178 /*
179  * shutdown all connections
180  */
181 int connections_shutdown(void)
182 {
183         ber_socket_t i;
184
185         ldap_pvt_thread_mutex_lock( &connections_mutex );
186
187         for ( i = 0; i < dtblsize; i++ ) {
188                 if( connections[i].c_struct_state != SLAP_C_USED ) {
189                         continue;
190                 }
191                 /* give persistent clients a chance to cleanup */
192                 if( connections[i].c_conn_state == SLAP_C_CLIENT ) {
193                         ldap_pvt_thread_pool_submit( &connection_pool,
194                         connections[i].c_clientfunc, connections[i].c_clientarg );
195                         continue;
196                 }
197
198                 ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
199
200                 /* connections_mutex and c_mutex are locked */
201                 connection_closing( &connections[i] );
202                 connection_close( &connections[i] );
203
204                 ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
205         }
206
207         ldap_pvt_thread_mutex_unlock( &connections_mutex );
208
209         return 0;
210 }
211
212 /*
213  * Timeout idle connections.
214  */
215 int connections_timeout_idle(time_t now)
216 {
217         int i = 0;
218         int connindex;
219         Connection* c;
220
221         for( c = connection_first( &connindex );
222                 c != NULL;
223                 c = connection_next( c, &connindex ) )
224         {
225                 /* Don't timeout a slow-running request or a persistent
226                  * outbound connection */
227                 if( c->c_n_ops_executing ||
228                         c->c_conn_state == SLAP_C_CLIENT ) continue;
229
230                 if( difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
231                         /* close it */
232                         connection_closing( c );
233                         connection_close( c );
234                         i++;
235                 }
236         }
237         connection_done( c );
238
239         return i;
240 }
241
242 static Connection* connection_get( ber_socket_t s )
243 {
244         /* connections_mutex should be locked by caller */
245
246         Connection *c;
247
248 #ifdef NEW_LOGGING
249         LDAP_LOG( CONNECTION, ENTRY, "connection_get: socket %ld\n", (long)s, 0, 0 );
250 #else
251         Debug( LDAP_DEBUG_ARGS,
252                 "connection_get(%ld)\n",
253                 (long) s, 0, 0 );
254 #endif
255
256         assert( connections != NULL );
257
258         if(s == AC_SOCKET_INVALID) {
259                 return NULL;
260         }
261
262 #ifndef HAVE_WINSOCK
263         c = &connections[s];
264
265         assert( c->c_struct_state != SLAP_C_UNINITIALIZED );
266
267 #else
268         c = NULL;
269         {
270                 ber_socket_t i, sd;
271
272                 for(i=0; i<dtblsize; i++) {
273                         if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
274                                 assert( connections[i].c_conn_state == SLAP_C_INVALID );
275                                 assert( connections[i].c_sb == 0 );
276                                 break;
277                         }
278
279                         ber_sockbuf_ctrl( connections[i].c_sb,
280                                 LBER_SB_OPT_GET_FD, &sd );
281
282                         if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
283                                 assert( connections[i].c_conn_state == SLAP_C_INVALID );
284                                 assert( sd == AC_SOCKET_INVALID );
285                                 continue;
286                         }
287
288                         /* state can actually change from used -> unused by resched,
289                          * so don't assert details here.
290                          */
291
292                         if( sd == s ) {
293                                 c = &connections[i];
294                                 break;
295                         }
296                 }
297         }
298 #endif
299
300         if( c != NULL ) {
301                 ber_socket_t    sd;
302
303                 ldap_pvt_thread_mutex_lock( &c->c_mutex );
304
305                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
306                 if( c->c_struct_state != SLAP_C_USED ) {
307                         /* connection must have been closed due to resched */
308
309                         assert( c->c_conn_state == SLAP_C_INVALID );
310                         assert( sd == AC_SOCKET_INVALID );
311
312 #ifdef NEW_LOGGING
313                         LDAP_LOG( CONNECTION, ARGS, 
314                                 "connection_get: connection %d not used\n", s, 0, 0 );
315 #else
316                         Debug( LDAP_DEBUG_TRACE,
317                                 "connection_get(%d): connection not used\n",
318                                 s, 0, 0 );
319 #endif
320
321                         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
322                         return NULL;
323                 }
324
325 #ifdef NEW_LOGGING
326                 LDAP_LOG( CONNECTION, RESULTS, 
327                         "connection_get: get for %d got connid %lu\n", s, c->c_connid, 0 );
328 #else
329                 Debug( LDAP_DEBUG_TRACE,
330                         "connection_get(%d): got connid=%lu\n",
331                         s, c->c_connid, 0 );
332 #endif
333
334                 c->c_n_get++;
335
336                 assert( c->c_struct_state == SLAP_C_USED );
337                 assert( c->c_conn_state != SLAP_C_INVALID );
338                 assert( sd != AC_SOCKET_INVALID );
339
340 #ifdef SLAPD_MONITOR
341                 c->c_activitytime = slap_get_time();
342 #else
343                 if( global_idletimeout > 0 ) {
344                         c->c_activitytime = slap_get_time();
345                 }
346 #endif
347         }
348
349         return c;
350 }
351
352 static void connection_return( Connection *c )
353 {
354         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
355 }
356
357 long connection_init(
358         ber_socket_t s,
359         Listener *listener,
360         const char* dnsname,
361         const char* peername,
362         int flags,
363         slap_ssf_t ssf,
364         struct berval *authid )
365 {
366         unsigned long id;
367         Connection *c;
368
369         assert( connections != NULL );
370
371         assert( listener != NULL );
372         assert( dnsname != NULL );
373         assert( peername != NULL );
374
375 #ifndef HAVE_TLS
376         assert( flags != CONN_IS_TLS );
377 #endif
378
379         if( s == AC_SOCKET_INVALID ) {
380 #ifdef NEW_LOGGING
381                 LDAP_LOG( CONNECTION, INFO, 
382                         "connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 );
383 #else
384                 Debug( LDAP_DEBUG_ANY,
385                         "connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 );
386 #endif
387                 return -1;
388         }
389
390         assert( s >= 0 );
391 #ifndef HAVE_WINSOCK
392         assert( s < dtblsize );
393 #endif
394
395         ldap_pvt_thread_mutex_lock( &connections_mutex );
396
397 #ifndef HAVE_WINSOCK
398         c = &connections[s];
399
400 #else
401         {
402                 ber_socket_t i;
403                 c = NULL;
404
405                 for( i=0; i < dtblsize; i++) {
406                         ber_socket_t    sd;
407
408                         if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
409                                 assert( connections[i].c_sb == 0 );
410                                 c = &connections[i];
411                                 break;
412                         }
413
414                         sd = AC_SOCKET_INVALID;
415                         if (connections[i].c_sb != NULL) {
416                                 ber_sockbuf_ctrl( connections[i].c_sb,
417                                         LBER_SB_OPT_GET_FD, &sd );
418                         }
419
420                         if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
421                                 assert( sd == AC_SOCKET_INVALID );
422                                 c = &connections[i];
423                                 break;
424                         }
425
426                         if( connections[i].c_conn_state == SLAP_C_CLIENT ) {
427                                 continue;
428                         }
429
430                         assert( connections[i].c_struct_state == SLAP_C_USED );
431                         assert( connections[i].c_conn_state != SLAP_C_INVALID );
432                         assert( sd != AC_SOCKET_INVALID );
433                 }
434
435                 if( c == NULL ) {
436 #ifdef NEW_LOGGING
437                         LDAP_LOG( CONNECTION, INFO, 
438                                 "connection_init(%d): connection table full "
439                                 "(%d/%d)\n", s, i, dtblsize );
440 #else
441                         Debug( LDAP_DEBUG_ANY,
442                                 "connection_init(%d): connection table full "
443                                 "(%d/%d)\n", s, i, dtblsize);
444 #endif
445                         ldap_pvt_thread_mutex_unlock( &connections_mutex );
446                         return -1;
447                 }
448         }
449 #endif
450
451         assert( c != NULL );
452
453         if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
454                 c->c_send_ldap_result = slap_send_ldap_result;
455                 c->c_send_search_entry = slap_send_search_entry;
456                 c->c_send_search_reference = slap_send_search_reference;
457                 c->c_send_ldap_extended = slap_send_ldap_extended;
458 #ifdef LDAP_RES_INTERMEDIATE
459                 c->c_send_ldap_intermediate = slap_send_ldap_intermediate;
460 #endif
461
462                 c->c_authmech.bv_val = NULL;
463                 c->c_authmech.bv_len = 0;
464                 c->c_dn.bv_val = NULL;
465                 c->c_dn.bv_len = 0;
466                 c->c_ndn.bv_val = NULL;
467                 c->c_ndn.bv_len = 0;
468
469                 c->c_listener = NULL;
470                 c->c_peer_domain.bv_val = NULL;
471                 c->c_peer_domain.bv_len = 0;
472                 c->c_peer_name.bv_val = NULL;
473                 c->c_peer_name.bv_len = 0;
474
475                 LDAP_STAILQ_INIT(&c->c_ops);
476                 LDAP_STAILQ_INIT(&c->c_pending_ops);
477
478                 c->c_sasl_bind_mech.bv_val = NULL;
479                 c->c_sasl_bind_mech.bv_len = 0;
480                 c->c_sasl_done = 0;
481                 c->c_sasl_authctx = NULL;
482                 c->c_sasl_sockctx = NULL;
483                 c->c_sasl_extra = NULL;
484                 c->c_sasl_bindop = NULL;
485
486                 c->c_sb = ber_sockbuf_alloc( );
487
488                 {
489                         ber_len_t max = sockbuf_max_incoming;
490                         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
491                 }
492
493                 c->c_currentber = NULL;
494
495                 /* should check status of thread calls */
496                 ldap_pvt_thread_mutex_init( &c->c_mutex );
497                 ldap_pvt_thread_mutex_init( &c->c_write_mutex );
498                 ldap_pvt_thread_cond_init( &c->c_write_cv );
499
500 #ifdef LDAP_SLAPI
501                 if ( slapi_plugins_used ) {
502                         slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, c );
503                 }
504 #endif
505
506                 c->c_struct_state = SLAP_C_UNUSED;
507         }
508
509         ldap_pvt_thread_mutex_lock( &c->c_mutex );
510
511         assert( c->c_struct_state == SLAP_C_UNUSED );
512         assert( c->c_authmech.bv_val == NULL );
513         assert( c->c_dn.bv_val == NULL );
514         assert( c->c_ndn.bv_val == NULL );
515         assert( c->c_listener == NULL );
516         assert( c->c_peer_domain.bv_val == NULL );
517         assert( c->c_peer_name.bv_val == NULL );
518         assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
519         assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) );
520         assert( c->c_sasl_bind_mech.bv_val == NULL );
521         assert( c->c_sasl_done == 0 );
522         assert( c->c_sasl_authctx == NULL );
523         assert( c->c_sasl_sockctx == NULL );
524         assert( c->c_sasl_extra == NULL );
525         assert( c->c_sasl_bindop == NULL );
526         assert( c->c_currentber == NULL );
527         assert( c->c_writewaiter == 0);
528
529         c->c_listener = listener;
530
531         if ( flags == CONN_IS_CLIENT ) {
532                 c->c_conn_state = SLAP_C_CLIENT;
533                 c->c_struct_state = SLAP_C_USED;
534                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &s );
535                 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
536                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
537
538                 return 0;
539         }
540
541         ber_str2bv( dnsname, 0, 1, &c->c_peer_domain );
542         ber_str2bv( peername, 0, 1, &c->c_peer_name );
543
544         c->c_n_ops_received = 0;
545         c->c_n_ops_executing = 0;
546         c->c_n_ops_pending = 0;
547         c->c_n_ops_completed = 0;
548
549         c->c_n_get = 0;
550         c->c_n_read = 0;
551         c->c_n_write = 0;
552
553         /* set to zero until bind, implies LDAP_VERSION3 */
554         c->c_protocol = 0;
555
556 #ifdef SLAPD_MONITOR
557         c->c_activitytime = c->c_starttime = slap_get_time();
558 #else
559         if( global_idletimeout > 0 ) {
560                 c->c_activitytime = c->c_starttime = slap_get_time();
561         }
562 #endif
563
564 #ifdef LDAP_CONNECTIONLESS
565         c->c_is_udp = 0;
566         if( flags == CONN_IS_UDP ) {
567                 c->c_is_udp = 1;
568 #ifdef LDAP_DEBUG
569                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
570                         LBER_SBIOD_LEVEL_PROVIDER, (void*)"udp_" );
571 #endif
572                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_udp,
573                         LBER_SBIOD_LEVEL_PROVIDER, (void *)&s );
574                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
575                         LBER_SBIOD_LEVEL_PROVIDER, NULL );
576         } else
577 #endif
578         {
579 #ifdef LDAP_DEBUG
580                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
581                         LBER_SBIOD_LEVEL_PROVIDER, (void*)"tcp_" );
582 #endif
583                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_tcp,
584                         LBER_SBIOD_LEVEL_PROVIDER, (void *)&s );
585         }
586
587 #ifdef LDAP_DEBUG
588         ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
589                 INT_MAX, (void*)"ldap_" );
590 #endif
591
592         if( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_NONBLOCK,
593                 c /* non-NULL */ ) < 0 )
594         {
595 #ifdef NEW_LOGGING
596                 LDAP_LOG( CONNECTION, INFO, 
597                         "connection_init: conn %lu set nonblocking failed\n",
598                         c->c_connid, 0, 0 );
599 #else
600                 Debug( LDAP_DEBUG_ANY,
601                         "connection_init(%d, %s): set nonblocking failed\n",
602                         s, c->c_peer_name.bv_val, 0 );
603 #endif
604         }
605
606         id = c->c_connid = conn_nextid++;
607
608         c->c_conn_state = SLAP_C_INACTIVE;
609         c->c_struct_state = SLAP_C_USED;
610
611         c->c_ssf = c->c_transport_ssf = ssf;
612         c->c_tls_ssf = 0;
613
614 #ifdef HAVE_TLS
615         if ( flags == CONN_IS_TLS ) {
616                 c->c_is_tls = 1;
617                 c->c_needs_tls_accept = 1;
618         } else {
619                 c->c_is_tls = 0;
620                 c->c_needs_tls_accept = 0;
621         }
622 #endif
623
624         slap_sasl_open( c, 0 );
625         slap_sasl_external( c, ssf, authid );
626
627         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
628         ldap_pvt_thread_mutex_unlock( &connections_mutex );
629
630         backend_connection_init(c);
631
632         return id;
633 }
634
635 void connection2anonymous( Connection *c )
636 {
637         assert( connections != NULL );
638         assert( c != NULL );
639
640         {
641                 ber_len_t max = sockbuf_max_incoming;
642                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
643         }
644
645         if(c->c_authmech.bv_val != NULL ) {
646                 free(c->c_authmech.bv_val);
647                 c->c_authmech.bv_val = NULL;
648         }
649         c->c_authmech.bv_len = 0;
650
651         if(c->c_dn.bv_val != NULL) {
652                 free(c->c_dn.bv_val);
653                 c->c_dn.bv_val = NULL;
654         }
655         c->c_dn.bv_len = 0;
656         if(c->c_ndn.bv_val != NULL) {
657                 free(c->c_ndn.bv_val);
658                 c->c_ndn.bv_val = NULL;
659         }
660         c->c_ndn.bv_len = 0;
661
662         c->c_authz_backend = NULL;
663 }
664
665 static void
666 connection_destroy( Connection *c )
667 {
668         /* note: connections_mutex should be locked by caller */
669         ber_socket_t    sd;
670         unsigned long   connid;
671
672         assert( connections != NULL );
673         assert( c != NULL );
674         assert( c->c_struct_state != SLAP_C_UNUSED );
675         assert( c->c_conn_state != SLAP_C_INVALID );
676         assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
677         assert( c->c_writewaiter == 0);
678
679         /* only for stats (print -1 as "%lu" may give unexpected results ;) */
680         connid = c->c_connid;
681
682         backend_connection_destroy(c);
683
684         c->c_protocol = 0;
685         c->c_connid = -1;
686
687         c->c_activitytime = c->c_starttime = 0;
688
689         connection2anonymous( c );
690         c->c_listener = NULL;
691
692         if(c->c_peer_domain.bv_val != NULL) {
693                 free(c->c_peer_domain.bv_val);
694                 c->c_peer_domain.bv_val = NULL;
695         }
696         c->c_peer_domain.bv_len = 0;
697         if(c->c_peer_name.bv_val != NULL) {
698                 free(c->c_peer_name.bv_val);
699                 c->c_peer_name.bv_val = NULL;
700         }
701         c->c_peer_name.bv_len = 0;
702
703         c->c_sasl_bind_in_progress = 0;
704         if(c->c_sasl_bind_mech.bv_val != NULL) {
705                 free(c->c_sasl_bind_mech.bv_val);
706                 c->c_sasl_bind_mech.bv_val = NULL;
707         }
708         c->c_sasl_bind_mech.bv_len = 0;
709
710         slap_sasl_close( c );
711
712         if ( c->c_currentber != NULL ) {
713                 ber_free( c->c_currentber, 1 );
714                 c->c_currentber = NULL;
715         }
716
717         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
718         if ( sd != AC_SOCKET_INVALID ) {
719                 slapd_remove( sd, 1, 0 );
720
721                 Statslog( LDAP_DEBUG_STATS,
722                         "conn=%lu fd=%ld closed\n",
723                         connid, (long) sd, 0, 0, 0 );
724         }
725
726         ber_sockbuf_free( c->c_sb );
727
728         c->c_sb = ber_sockbuf_alloc( );
729
730         {
731                 ber_len_t max = sockbuf_max_incoming;
732                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
733         }
734
735         c->c_conn_state = SLAP_C_INVALID;
736         c->c_struct_state = SLAP_C_UNUSED;
737
738 #ifdef LDAP_SLAPI
739         /* call destructors, then constructors; avoids unnecessary allocation */
740         if ( slapi_plugins_used ) {
741                 slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
742         }
743 #endif
744 }
745
746 int connection_state_closing( Connection *c )
747 {
748         /* c_mutex must be locked by caller */
749
750         int state;
751         assert( c != NULL );
752         assert( c->c_struct_state == SLAP_C_USED );
753
754         state = c->c_conn_state;
755
756         assert( state != SLAP_C_INVALID );
757
758         return state == SLAP_C_CLOSING;
759 }
760
761 static void connection_abandon( Connection *c )
762 {
763         /* c_mutex must be locked by caller */
764
765         Operation *o;
766
767         LDAP_STAILQ_FOREACH(o, &c->c_ops, o_next) {
768                 o->o_abandon = 1;
769         }
770
771         /* remove pending operations */
772         while ( (o = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
773                 LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
774                 LDAP_STAILQ_NEXT(o, o_next) = NULL;
775                 slap_op_free( o );
776         }
777 }
778
779 void connection_closing( Connection *c )
780 {
781         assert( connections != NULL );
782         assert( c != NULL );
783         assert( c->c_struct_state == SLAP_C_USED );
784         assert( c->c_conn_state != SLAP_C_INVALID );
785
786         /* c_mutex must be locked by caller */
787
788         if( c->c_conn_state != SLAP_C_CLOSING ) {
789                 ber_socket_t    sd;
790
791                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
792 #ifdef NEW_LOGGING
793                 LDAP_LOG( CONNECTION, DETAIL1, 
794                         "connection_closing: conn %lu readying socket %d for close.\n",
795                         c->c_connid, sd, 0 );
796 #else
797                 Debug( LDAP_DEBUG_TRACE,
798                         "connection_closing: readying conn=%lu sd=%d for close\n",
799                         c->c_connid, sd, 0 );
800 #endif
801                 /* update state to closing */
802                 c->c_conn_state = SLAP_C_CLOSING;
803
804                 /* don't listen on this port anymore */
805                 slapd_clr_read( sd, 1 );
806
807                 /* abandon active operations */
808                 connection_abandon( c );
809
810                 /* wake write blocked operations */
811                 slapd_clr_write( sd, 1 );
812                 ldap_pvt_thread_cond_signal( &c->c_write_cv );
813         }
814 }
815
816 static void connection_close( Connection *c )
817 {
818         ber_socket_t    sd;
819
820         assert( connections != NULL );
821         assert( c != NULL );
822         assert( c->c_struct_state == SLAP_C_USED );
823         assert( c->c_conn_state == SLAP_C_CLOSING );
824
825         /* note: connections_mutex and c_mutex should be locked by caller */
826
827         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
828         if( !LDAP_STAILQ_EMPTY(&c->c_ops) ) {
829 #ifdef NEW_LOGGING
830                 LDAP_LOG( CONNECTION, DETAIL1, 
831                         "connection_close: conn %lu deferring sd %d\n",
832                                 c->c_connid, sd, 0 );
833 #else
834                 Debug( LDAP_DEBUG_TRACE,
835                         "connection_close: deferring conn=%lu sd=%d\n",
836                         c->c_connid, sd, 0 );
837 #endif
838                 return;
839         }
840
841 #ifdef NEW_LOGGING
842         LDAP_LOG( CONNECTION, RESULTS, 
843                 "connection_close: conn %lu sd %d\n", c->c_connid, sd, 0 );
844 #else
845         Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%lu sd=%d\n",
846                 c->c_connid, sd, 0 );
847 #endif
848         connection_destroy( c );
849 }
850
851 unsigned long connections_nextid(void)
852 {
853         unsigned long id;
854         assert( connections != NULL );
855
856         ldap_pvt_thread_mutex_lock( &connections_mutex );
857
858         id = conn_nextid;
859
860         ldap_pvt_thread_mutex_unlock( &connections_mutex );
861
862         return id;
863 }
864
865 Connection* connection_first( ber_socket_t *index )
866 {
867         assert( connections != NULL );
868         assert( index != NULL );
869
870         ldap_pvt_thread_mutex_lock( &connections_mutex );
871
872         *index = 0;
873
874         return connection_next(NULL, index);
875 }
876
877 Connection* connection_next( Connection *c, ber_socket_t *index )
878 {
879         assert( connections != NULL );
880         assert( index != NULL );
881         assert( *index <= dtblsize );
882
883         if( c != NULL ) {
884                 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
885         }
886
887         c = NULL;
888
889         for(; *index < dtblsize; (*index)++) {
890                 if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) {
891                         assert( connections[*index].c_conn_state == SLAP_C_INVALID );
892 #ifndef HAVE_WINSOCK
893                         continue;
894 #else
895                         break;
896 #endif
897                 }
898
899                 if( connections[*index].c_struct_state == SLAP_C_USED ) {
900                         assert( connections[*index].c_conn_state != SLAP_C_INVALID );
901                         c = &connections[(*index)++];
902                         break;
903                 }
904
905                 assert( connections[*index].c_struct_state == SLAP_C_UNUSED );
906                 assert( connections[*index].c_conn_state == SLAP_C_INVALID );
907         }
908
909         if( c != NULL ) {
910                 ldap_pvt_thread_mutex_lock( &c->c_mutex );
911         }
912
913         return c;
914 }
915
916 void connection_done( Connection *c )
917 {
918         assert( connections != NULL );
919
920         if( c != NULL ) {
921                 ldap_pvt_thread_mutex_unlock( &c->c_mutex );
922         }
923
924         ldap_pvt_thread_mutex_unlock( &connections_mutex );
925 }
926
927 /*
928  * connection_activity - handle the request operation op on connection
929  * conn.  This routine figures out what kind of operation it is and
930  * calls the appropriate stub to handle it.
931  */
932
933 #ifdef SLAPD_MONITOR
934 #define INCR_OP(var,index) \
935         do { \
936                 ldap_pvt_thread_mutex_lock( &num_ops_mutex ); \
937                 (var)[(index)]++; \
938                 ldap_pvt_thread_mutex_unlock( &num_ops_mutex ); \
939         } while (0)
940 #else /* !SLAPD_MONITOR */
941 #define INCR_OP(var,index) 
942 #endif /* !SLAPD_MONITOR */
943
944 static void *
945 connection_operation( void *ctx, void *arg_v )
946 {
947         int rc = SLAPD_DISCONNECT;
948         Operation *op = arg_v;
949         SlapReply rs = {REP_RESULT};
950         ber_tag_t tag = op->o_tag;
951 #ifdef SLAPD_MONITOR
952         ber_tag_t oldtag = tag;
953 #endif /* SLAPD_MONITOR */
954         Connection *conn = op->o_conn;
955         void *memctx = NULL;
956         void *memctx_null = NULL;
957         ber_len_t memsiz;
958
959         ldap_pvt_thread_mutex_lock( &num_ops_mutex );
960         num_ops_initiated++;
961         ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
962
963         op->o_threadctx = ctx;
964
965         if( conn->c_sasl_bind_in_progress && tag != LDAP_REQ_BIND ) {
966 #ifdef NEW_LOGGING
967                 LDAP_LOG( CONNECTION, ERR, 
968                         "connection_operation: conn %lu SASL bind in progress (tag=%ld).\n",
969                         conn->c_connid, (long)tag, 0 );
970 #else
971                 Debug( LDAP_DEBUG_ANY, "connection_operation: "
972                         "error: SASL bind in progress (tag=%ld).\n",
973                         (long) tag, 0, 0 );
974 #endif
975                 send_ldap_error( op, &rs, LDAP_OPERATIONS_ERROR,
976                         "SASL bind in progress" );
977                 goto operations_error;
978         }
979
980         /* We can use Thread-Local storage for most mallocs. We can
981          * also use TL for ber parsing, but not on Add or Modify.
982          */
983 #if 0
984         memsiz = ber_len( op->o_ber ) * 64;
985         if ( SLMALLOC_SLAB_SIZE > memsiz ) memsiz = SLMALLOC_SLAB_SIZE;
986 #endif
987         memsiz = SLMALLOC_SLAB_SIZE;
988
989         memctx = sl_mem_create( memsiz, ctx );
990         op->o_tmpmemctx = memctx;
991         op->o_tmpmfuncs = &sl_mfuncs;
992         if ( tag != LDAP_REQ_ADD && tag != LDAP_REQ_MODIFY ) {
993                 /* Note - the ber and its buffer are already allocated from
994                  * regular memory; this only affects subsequent mallocs that
995                  * ber_scanf may invoke.
996                  */
997                 ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx );
998         }
999
1000         switch ( tag ) {
1001         case LDAP_REQ_BIND:
1002                 INCR_OP(num_ops_initiated_, SLAP_OP_BIND);
1003                 rc = do_bind( op, &rs );
1004                 break;
1005
1006         case LDAP_REQ_UNBIND:
1007                 INCR_OP(num_ops_initiated_, SLAP_OP_UNBIND);
1008                 rc = do_unbind( op, &rs );
1009                 break;
1010
1011         case LDAP_REQ_ADD:
1012                 INCR_OP(num_ops_initiated_, SLAP_OP_ADD);
1013                 rc = do_add( op, &rs );
1014                 break;
1015
1016         case LDAP_REQ_DELETE:
1017                 INCR_OP(num_ops_initiated_, SLAP_OP_DELETE);
1018                 rc = do_delete( op, &rs );
1019                 break;
1020
1021         case LDAP_REQ_MODRDN:
1022                 INCR_OP(num_ops_initiated_, SLAP_OP_MODRDN);
1023                 rc = do_modrdn( op, &rs );
1024                 break;
1025
1026         case LDAP_REQ_MODIFY:
1027                 INCR_OP(num_ops_initiated_, SLAP_OP_MODIFY);
1028                 rc = do_modify( op, &rs );
1029                 break;
1030
1031         case LDAP_REQ_COMPARE:
1032                 INCR_OP(num_ops_initiated_, SLAP_OP_COMPARE);
1033                 rc = do_compare( op, &rs );
1034                 break;
1035
1036         case LDAP_REQ_SEARCH:
1037                 INCR_OP(num_ops_initiated_, SLAP_OP_SEARCH);
1038                 rc = do_search( op, &rs );
1039                 break;
1040
1041         case LDAP_REQ_ABANDON:
1042                 INCR_OP(num_ops_initiated_, SLAP_OP_ABANDON);
1043                 rc = do_abandon( op, &rs );
1044                 break;
1045
1046         case LDAP_REQ_EXTENDED:
1047                 INCR_OP(num_ops_initiated_, SLAP_OP_EXTENDED);
1048                 rc = do_extended( op, &rs );
1049                 break;
1050
1051         default:
1052 #ifdef NEW_LOGGING
1053                 LDAP_LOG( CONNECTION, INFO, 
1054                         "connection_operation: conn %lu unknown LDAP request 0x%lx\n",
1055                         conn->c_connid, tag, 0 );
1056 #else
1057                 Debug( LDAP_DEBUG_ANY, "unknown LDAP request 0x%lx\n",
1058                         tag, 0, 0 );
1059 #endif
1060                 op->o_tag = LBER_ERROR;
1061                 rs.sr_err = LDAP_PROTOCOL_ERROR;
1062                 rs.sr_text = "unknown LDAP request";
1063                 send_ldap_disconnect( op, &rs );
1064                 rc = -1;
1065                 break;
1066         }
1067
1068 #ifdef SLAPD_MONITOR
1069         oldtag = tag;
1070 #endif /* SLAPD_MONITOR */
1071         if( rc == SLAPD_DISCONNECT ) tag = LBER_ERROR;
1072
1073 operations_error:
1074         ldap_pvt_thread_mutex_lock( &num_ops_mutex );
1075         num_ops_completed++;
1076 #ifdef SLAPD_MONITOR
1077         switch (oldtag) {
1078         case LDAP_REQ_BIND:
1079                 num_ops_completed_[SLAP_OP_BIND]++;
1080                 break;
1081         case LDAP_REQ_UNBIND:
1082                 num_ops_completed_[SLAP_OP_UNBIND]++;
1083                 break;
1084         case LDAP_REQ_ADD:
1085                 num_ops_completed_[SLAP_OP_ADD]++;
1086                 break;
1087         case LDAP_REQ_DELETE:
1088                 num_ops_completed_[SLAP_OP_DELETE]++;
1089                 break;
1090         case LDAP_REQ_MODRDN:
1091                 num_ops_completed_[SLAP_OP_MODRDN]++;
1092                 break;
1093         case LDAP_REQ_MODIFY:
1094                 num_ops_completed_[SLAP_OP_MODIFY]++;
1095                 break;
1096         case LDAP_REQ_COMPARE:
1097                 num_ops_completed_[SLAP_OP_COMPARE]++;
1098                 break;
1099         case LDAP_REQ_SEARCH:
1100                 num_ops_completed_[SLAP_OP_SEARCH]++;
1101                 break;
1102         case LDAP_REQ_ABANDON:
1103                 num_ops_completed_[SLAP_OP_ABANDON]++;
1104                 break;
1105         case LDAP_REQ_EXTENDED:
1106                 num_ops_completed_[SLAP_OP_EXTENDED]++;
1107                 break;
1108         }
1109 #endif /* SLAPD_MONITOR */
1110         ldap_pvt_thread_mutex_unlock( &num_ops_mutex );
1111
1112         if ( op->o_cancel == SLAP_CANCEL_REQ ) {
1113                 op->o_cancel = LDAP_TOO_LATE;
1114         }
1115
1116         while ( op->o_cancel != SLAP_CANCEL_NONE &&
1117                 op->o_cancel != SLAP_CANCEL_DONE )
1118         {
1119                 ldap_pvt_thread_yield();
1120         }
1121
1122         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
1123
1124         ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null );
1125
1126         if ( op->o_cancel != SLAP_CANCEL_ACK &&
1127                                 ( op->o_sync_mode & SLAP_SYNC_PERSIST ) ) {
1128                 sl_mem_detach( ctx, memctx );
1129         } else if (( op->o_sync_slog_size != -1 )) {
1130                 sl_mem_detach( ctx, memctx );
1131                 LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next);
1132                 LDAP_STAILQ_NEXT(op, o_next) = NULL;
1133                 conn->c_n_ops_executing--;
1134                 conn->c_n_ops_completed++;
1135         } else {
1136                 LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next);
1137                 LDAP_STAILQ_NEXT(op, o_next) = NULL;
1138                 slap_op_free( op );
1139                 conn->c_n_ops_executing--;
1140                 conn->c_n_ops_completed++;
1141         }
1142
1143         switch( tag ) {
1144         case LBER_ERROR:
1145         case LDAP_REQ_UNBIND:
1146                 /* c_mutex is locked */
1147                 connection_closing( conn );
1148                 break;
1149
1150         case LDAP_REQ_BIND:
1151                 conn->c_sasl_bind_in_progress =
1152                         rc == LDAP_SASL_BIND_IN_PROGRESS ? 1 : 0;
1153
1154                 if( conn->c_conn_state == SLAP_C_BINDING) {
1155                         conn->c_conn_state = SLAP_C_ACTIVE;
1156                 }
1157         }
1158
1159         connection_resched( conn );
1160
1161         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
1162
1163         return NULL;
1164 }
1165
1166 int connection_client_setup(
1167         ber_socket_t s,
1168         Listener *l,
1169         ldap_pvt_thread_start_t *func,
1170         void *arg )
1171 {
1172         Connection *c;
1173
1174         if ( connection_init( s, l, "", "", CONN_IS_CLIENT, 0, NULL ) < 0 ) {
1175                 return -1;
1176         }
1177
1178         c = connection_get( s );
1179         c->c_clientfunc = func;
1180         c->c_clientarg = arg;
1181         connection_return( c );
1182         slapd_add_internal( s, 0 );
1183         slapd_set_read( s, 1 );
1184         return 0;
1185 }
1186
1187 void connection_client_enable(
1188         ber_socket_t s
1189 )
1190 {
1191         slapd_set_read( s, 1 );
1192 }
1193
1194 void connection_client_stop(
1195         ber_socket_t s
1196 )
1197 {
1198         Connection *c;
1199
1200         /* get (locked) connection */
1201         c = connection_get( s );
1202         
1203         assert( c->c_conn_state == SLAP_C_CLIENT );
1204
1205         c->c_listener = NULL;
1206         c->c_conn_state = SLAP_C_INVALID;
1207         c->c_struct_state = SLAP_C_UNUSED;
1208         connection_return( c );
1209         slapd_remove( s, 0, 1 );
1210 }
1211
1212 int connection_read(ber_socket_t s)
1213 {
1214         int rc = 0;
1215         Connection *c;
1216
1217         assert( connections != NULL );
1218
1219         ldap_pvt_thread_mutex_lock( &connections_mutex );
1220
1221         /* get (locked) connection */
1222         c = connection_get( s );
1223
1224         if( c == NULL ) {
1225 #ifdef NEW_LOGGING
1226                 LDAP_LOG( CONNECTION, INFO, 
1227                         "connection_read: sock %ld no connection\n", (long)s, 0, 0 );
1228 #else
1229                 Debug( LDAP_DEBUG_ANY,
1230                         "connection_read(%ld): no connection!\n",
1231                         (long) s, 0, 0 );
1232 #endif
1233                 slapd_remove(s, 1, 0);
1234
1235                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1236                 return -1;
1237         }
1238
1239         c->c_n_read++;
1240
1241         if( c->c_conn_state == SLAP_C_CLOSING ) {
1242 #ifdef NEW_LOGGING
1243                 LDAP_LOG( CONNECTION, INFO, 
1244                         "connection_read: conn %lu connection closing, ignoring input\n",
1245                         c->c_connid, 0, 0 );
1246 #else
1247                 Debug( LDAP_DEBUG_TRACE,
1248                         "connection_read(%d): closing, ignoring input for id=%lu\n",
1249                         s, c->c_connid, 0 );
1250 #endif
1251                 connection_return( c );
1252                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1253                 return 0;
1254         }
1255
1256         if ( c->c_conn_state == SLAP_C_CLIENT ) {
1257                 slapd_clr_read( s, 0 );
1258                 ldap_pvt_thread_pool_submit( &connection_pool,
1259                         c->c_clientfunc, c->c_clientarg );
1260                 connection_return( c );
1261                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1262                 return 0;
1263         }
1264
1265 #ifdef NEW_LOGGING
1266         LDAP_LOG( CONNECTION, DETAIL1, 
1267                 "connection_read: conn %lu checking for input.\n", 
1268                         c->c_connid, 0, 0 );
1269 #else
1270         Debug( LDAP_DEBUG_TRACE,
1271                 "connection_read(%d): checking for input on id=%lu\n",
1272                 s, c->c_connid, 0 );
1273 #endif
1274
1275 #ifdef HAVE_TLS
1276         if ( c->c_is_tls && c->c_needs_tls_accept ) {
1277                 rc = ldap_pvt_tls_accept( c->c_sb, NULL );
1278                 if ( rc < 0 ) {
1279 #if 0 /* required by next #if 0 */
1280                         struct timeval tv;
1281                         fd_set rfd;
1282 #endif
1283
1284 #ifdef NEW_LOGGING
1285                         LDAP_LOG( CONNECTION, ERR, 
1286                                 "connection_read: conn %lu TLS accept error, error %d\n",
1287                                 c->c_connid, rc, 0 );
1288 #else
1289                         Debug( LDAP_DEBUG_TRACE,
1290                                 "connection_read(%d): TLS accept error "
1291                                 "error=%d id=%lu, closing\n",
1292                                 s, rc, c->c_connid );
1293 #endif
1294                         c->c_needs_tls_accept = 0;
1295                         /* connections_mutex and c_mutex are locked */
1296                         connection_closing( c );
1297
1298 #if 0
1299                         /* Drain input before close, to allow SSL error codes
1300                          * to propagate to client. */
1301                         FD_ZERO(&rfd);
1302                         FD_SET(s, &rfd);
1303                         for (rc=1; rc>0;) {
1304                                 tv.tv_sec = 1;
1305                                 tv.tv_usec = 0;
1306                                 rc = select(s+1, &rfd, NULL, NULL, &tv);
1307                                 if (rc == 1) {
1308                                         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DRAIN, NULL);
1309                                 }
1310                         }
1311 #endif
1312                         connection_close( c );
1313
1314                 } else if ( rc == 0 ) {
1315                         void *ssl;
1316                         struct berval authid = { 0, NULL };
1317
1318                         c->c_needs_tls_accept = 0;
1319
1320                         /* we need to let SASL know */
1321                         ssl = ldap_pvt_tls_sb_ctx( c->c_sb );
1322
1323                         c->c_tls_ssf = (slap_ssf_t) ldap_pvt_tls_get_strength( ssl );
1324                         if( c->c_tls_ssf > c->c_ssf ) {
1325                                 c->c_ssf = c->c_tls_ssf;
1326                         }
1327
1328                         rc = dnX509peerNormalize( ssl, &authid );
1329                         if ( rc != LDAP_SUCCESS ) {
1330 #ifdef NEW_LOGGING
1331                                 LDAP_LOG( CONNECTION, INFO, 
1332                                         "connection_read: conn %lu unable to get TLS client DN, "
1333                                         "error %d\n", c->c_connid, rc, 0 );
1334 #else
1335                                 Debug( LDAP_DEBUG_TRACE,
1336                                 "connection_read(%d): unable to get TLS client DN "
1337                                 "error=%d id=%lu\n",
1338                                 s, rc, c->c_connid );
1339 #endif
1340                         }
1341                         slap_sasl_external( c, c->c_tls_ssf, &authid );
1342                         if ( authid.bv_val ) free( authid.bv_val );
1343                 }
1344
1345                 /* if success and data is ready, fall thru to data input loop */
1346                 if( rc != 0 ||
1347                         !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
1348                 {
1349                         connection_return( c );
1350                         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1351                         return 0;
1352                 }
1353         }
1354 #endif
1355
1356 #ifdef HAVE_CYRUS_SASL
1357         if ( c->c_sasl_layers ) {
1358                 /* If previous layer is not removed yet, give up for now */
1359                 if ( !c->c_sasl_sockctx ) {
1360                         connection_return( c );
1361                         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1362                         return 0;
1363                 }
1364
1365                 c->c_sasl_layers = 0;
1366
1367                 rc = ldap_pvt_sasl_install( c->c_sb, c->c_sasl_sockctx );
1368
1369                 if( rc != LDAP_SUCCESS ) {
1370 #ifdef NEW_LOGGING
1371                         LDAP_LOG( CONNECTION, ERR, 
1372                                 "connection_read: conn %lu SASL install error %d, closing\n",
1373                                 c->c_connid, rc, 0 );
1374 #else
1375                         Debug( LDAP_DEBUG_TRACE,
1376                                 "connection_read(%d): SASL install error "
1377                                 "error=%d id=%lu, closing\n",
1378                                 s, rc, c->c_connid );
1379 #endif
1380                         /* connections_mutex and c_mutex are locked */
1381                         connection_closing( c );
1382                         connection_close( c );
1383                         connection_return( c );
1384                         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1385                         return 0;
1386                 }
1387         }
1388 #endif
1389
1390 #define CONNECTION_INPUT_LOOP 1
1391 /* #define      DATA_READY_LOOP 1 */
1392
1393         do {
1394                 /* How do we do this without getting into a busy loop ? */
1395                 rc = connection_input( c );
1396         }
1397 #ifdef DATA_READY_LOOP
1398         while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ));
1399 #elif CONNECTION_INPUT_LOOP
1400         while(!rc);
1401 #else
1402         while(0);
1403 #endif
1404
1405         if( rc < 0 ) {
1406 #ifdef NEW_LOGGING
1407                 LDAP_LOG( CONNECTION, ERR, 
1408                         "connection_read: conn %lu input error %d, closing.\n",
1409                         c->c_connid, rc, 0 );
1410 #else
1411                 Debug( LDAP_DEBUG_TRACE,
1412                         "connection_read(%d): input error=%d id=%lu, closing.\n",
1413                         s, rc, c->c_connid );
1414 #endif
1415                 /* connections_mutex and c_mutex are locked */
1416                 connection_closing( c );
1417                 connection_close( c );
1418                 connection_return( c );
1419                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1420                 return 0;
1421         }
1422
1423         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
1424                 slapd_set_read( s, 1 );
1425         }
1426
1427         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
1428                 slapd_set_write( s, 1 );
1429         }
1430
1431         connection_return( c );
1432         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1433         return 0;
1434 }
1435
1436 static int
1437 connection_input(
1438         Connection *conn )
1439 {
1440         Operation *op;
1441         ber_tag_t       tag;
1442         ber_len_t       len;
1443         ber_int_t       msgid;
1444         BerElement      *ber;
1445         int             rc;
1446 #ifdef LDAP_CONNECTIONLESS
1447         Sockaddr        peeraddr;
1448         char            *cdn = NULL;
1449 #endif
1450         char *defer = NULL;
1451
1452         if ( conn->c_currentber == NULL &&
1453                 ( conn->c_currentber = ber_alloc()) == NULL )
1454         {
1455 #ifdef NEW_LOGGING
1456                 LDAP_LOG( CONNECTION, ERR, 
1457                         "connection_input: conn %lu ber_alloc failed.\n", 
1458                         conn->c_connid, 0, 0 );
1459 #else
1460                 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
1461 #endif
1462                 return -1;
1463         }
1464
1465         errno = 0;
1466
1467 #ifdef LDAP_CONNECTIONLESS
1468         if ( conn->c_is_udp ) {
1469                 char    peername[sizeof("IP=255.255.255.255:65336")];
1470                 len = ber_int_sb_read(conn->c_sb, &peeraddr,
1471                         sizeof(struct sockaddr));
1472                 if (len != sizeof(struct sockaddr))
1473                         return 1;
1474                 sprintf( peername, "IP=%s:%d",
1475                         inet_ntoa( peeraddr.sa_in_addr.sin_addr ),
1476                         (unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) );
1477                 Statslog( LDAP_DEBUG_STATS,
1478                         "conn=%lu UDP request from %s (%s) accepted.\n",
1479                         conn->c_connid, peername, conn->c_sock_name.bv_val, 0, 0 );
1480         }
1481 #endif
1482         tag = ber_get_next( conn->c_sb, &len, conn->c_currentber );
1483         if ( tag != LDAP_TAG_MESSAGE ) {
1484                 int err = errno;
1485                 ber_socket_t    sd;
1486
1487                 ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
1488
1489 #ifdef NEW_LOGGING
1490                 LDAP_LOG( CONNECTION, ERR, 
1491                         "connection_input: conn %lu ber_get_next failed, errno %d (%s).\n",
1492                         conn->c_connid, err, sock_errstr(err) );
1493 #else
1494                 Debug( LDAP_DEBUG_TRACE,
1495                         "ber_get_next on fd %d failed errno=%d (%s)\n",
1496                         sd, err, sock_errstr(err) );
1497 #endif
1498                 if ( err != EWOULDBLOCK && err != EAGAIN ) {
1499                         /* log, close and send error */
1500                         ber_free( conn->c_currentber, 1 );
1501                         conn->c_currentber = NULL;
1502
1503                         return -2;
1504                 }
1505                 return 1;
1506         }
1507
1508         ber = conn->c_currentber;
1509         conn->c_currentber = NULL;
1510
1511         if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
1512                 /* log, close and send error */
1513 #ifdef NEW_LOGGING
1514                 LDAP_LOG( CONNECTION, ERR, 
1515                         "connection_input: conn %lu ber_get_int returns 0x%lx.\n",
1516                         conn->c_connid, tag, 0 );
1517 #else
1518                 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n",
1519                         tag, 0, 0 );
1520 #endif
1521                 ber_free( ber, 1 );
1522                 return -1;
1523         }
1524
1525         if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
1526                 /* log, close and send error */
1527 #ifdef NEW_LOGGING
1528                 LDAP_LOG( CONNECTION, ERR, 
1529                         "connection_input: conn %lu ber_peek_tag returns 0x%lx.\n",
1530                         conn->c_connid, tag, 0 );
1531 #else
1532                 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n",
1533                         tag, 0, 0 );
1534 #endif
1535                 ber_free( ber, 1 );
1536
1537                 return -1;
1538         }
1539
1540 #ifdef LDAP_CONNECTIONLESS
1541         if( conn->c_is_udp ) {
1542                 if( tag == LBER_OCTETSTRING ) {
1543                         ber_get_stringa( ber, &cdn );
1544                         tag = ber_peek_tag(ber, &len);
1545                 }
1546                 if( tag != LDAP_REQ_ABANDON && tag != LDAP_REQ_SEARCH ) {
1547 #ifdef NEW_LOGGING
1548                         LDAP_LOG( CONNECTION, ERR, 
1549                                 "connection_input: conn %lu invalid req for UDP 0x%lx.\n",
1550                                 conn->c_connid, tag, 0 );
1551 #else
1552                         Debug( LDAP_DEBUG_ANY, "invalid req for UDP 0x%lx\n", tag, 0, 0 );
1553 #endif
1554                         ber_free( ber, 1 );
1555                         return 0;
1556                 }
1557         }
1558 #endif
1559         if(tag == LDAP_REQ_BIND) {
1560                 /* immediately abandon all exiting operations upon BIND */
1561                 connection_abandon( conn );
1562         }
1563
1564         op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
1565
1566         op->o_conn = conn;
1567         op->o_assertion = NULL;
1568         op->o_preread_attrs = NULL;
1569         op->o_postread_attrs = NULL;
1570         op->o_vrFilter = NULL;
1571         op->o_pagedresults_state = conn->c_pagedresults_state;
1572
1573         op->o_res_ber = NULL;
1574
1575 #ifdef LDAP_CONNECTIONLESS
1576         if (conn->c_is_udp) {
1577                 if ( cdn ) {
1578                         ber_str2bv( cdn, 0, 1, &op->o_dn );
1579                         op->o_protocol = LDAP_VERSION2;
1580                 }
1581                 op->o_res_ber = ber_alloc_t( LBER_USE_DER );
1582                 if (op->o_res_ber == NULL) return 1;
1583
1584                 rc = ber_write( op->o_res_ber, (char *)&peeraddr,
1585                         sizeof(struct sockaddr), 0 );
1586
1587                 if (rc != sizeof(struct sockaddr)) {
1588 #ifdef NEW_LOGGING
1589                         LDAP_LOG( CONNECTION, INFO, 
1590                                 "connection_input: conn %lu ber_write failed\n",
1591                                 conn->c_connid, 0, 0 );
1592 #else
1593                         Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
1594 #endif
1595                         return 1;
1596                 }
1597
1598                 if (op->o_protocol == LDAP_VERSION2) {
1599                         rc = ber_printf(op->o_res_ber, "{is{" /*}}*/, op->o_msgid, "");
1600                         if (rc == -1) {
1601 #ifdef NEW_LOGGING
1602                                 LDAP_LOG( CONNECTION, INFO, 
1603                                         "connection_input: conn %lu put outer sequence failed\n",
1604                                         conn->c_connid, 0, 0 );
1605 #else
1606                                 Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
1607 #endif
1608                                 return rc;
1609                         }
1610                 }
1611         }
1612 #endif /* LDAP_CONNECTIONLESS */
1613
1614         rc = 0;
1615
1616         /* Don't process requests when the conn is in the middle of a
1617          * Bind, or if it's closing. Also, don't let any single conn
1618          * use up all the available threads, and don't execute if we're
1619          * currently blocked on output. And don't execute if there are
1620          * already pending ops, let them go first.  Abandon operations
1621          * get exceptions to some, but not all, cases.
1622          */
1623         if (tag != LDAP_REQ_ABANDON && conn->c_conn_state == SLAP_C_CLOSING) {
1624                 defer = "closing";
1625         } else if (tag != LDAP_REQ_ABANDON && conn->c_writewaiter) {
1626                 defer = "awaiting write";
1627         } else if (conn->c_n_ops_executing >= connection_pool_max/2) {
1628                 defer = "too many executing";
1629         } else if (conn->c_conn_state == SLAP_C_BINDING ) {
1630                 defer = "binding";
1631         } else if (conn->c_n_ops_pending) {
1632                 defer = "pending operations";
1633         }
1634
1635         if( defer ) {
1636                 int max = conn->c_dn.bv_len
1637                         ? slap_conn_max_pending_auth
1638                         : slap_conn_max_pending;
1639
1640 #ifdef NEW_LOGGING
1641                 LDAP_LOG( CONNECTION, INFO, 
1642                         "connection_input: conn %lu deferring operation: %s\n",
1643                         conn->c_connid, defer, 0 );
1644 #else
1645                 Debug( LDAP_DEBUG_ANY,
1646                         "connection_input: conn=%lu deferring operation: %s\n",
1647                         conn->c_connid, defer, 0 );
1648 #endif
1649                 conn->c_n_ops_pending++;
1650                 LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next );
1651                 if ( conn->c_n_ops_pending > max ) {
1652                         rc = -1;
1653                 } else {
1654                         rc = 1;
1655                 }
1656         } else {
1657                 conn->c_n_ops_executing++;
1658                 connection_op_activate( op );
1659         }
1660
1661 #ifdef NO_THREADS
1662         if ( conn->c_struct_state != SLAP_C_USED ) {
1663                 /* connection must have got closed underneath us */
1664                 return 1;
1665         }
1666 #endif
1667         assert( conn->c_struct_state == SLAP_C_USED );
1668
1669         return rc;
1670 }
1671
1672 static int
1673 connection_resched( Connection *conn )
1674 {
1675         Operation *op;
1676
1677         if( conn->c_conn_state == SLAP_C_CLOSING ) {
1678                 int rc;
1679                 ber_socket_t    sd;
1680                 ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
1681
1682                 /* us trylock to avoid possible deadlock */
1683                 rc = ldap_pvt_thread_mutex_trylock( &connections_mutex );
1684
1685                 if( rc ) {
1686 #ifdef NEW_LOGGING
1687                         LDAP_LOG( CONNECTION, DETAIL1, 
1688                                 "connection_resched: conn %lu reaquiring locks.\n",
1689                                 conn->c_connid, 0, 0 );
1690 #else
1691                         Debug( LDAP_DEBUG_TRACE,
1692                                 "connection_resched: reaquiring locks conn=%lu sd=%d\n",
1693                                 conn->c_connid, sd, 0 );
1694 #endif
1695                         /*
1696                          * reaquire locks in the right order...
1697                          * this may allow another thread to close this connection,
1698                          * so recheck state below.
1699                          */
1700                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
1701                         ldap_pvt_thread_mutex_lock( &connections_mutex );
1702                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
1703                 }
1704
1705                 if( conn->c_conn_state != SLAP_C_CLOSING ) {
1706 #ifdef NEW_LOGGING
1707                         LDAP_LOG( CONNECTION, INFO, 
1708                                 "connection_resched: conn %lu closed by other thread.\n",
1709                                 conn->c_connid, 0, 0 );
1710 #else
1711                         Debug( LDAP_DEBUG_TRACE, "connection_resched: "
1712                                 "closed by other thread conn=%lu sd=%d\n",
1713                                 conn->c_connid, sd, 0 );
1714 #endif
1715                 } else {
1716 #ifdef NEW_LOGGING
1717                         LDAP_LOG( CONNECTION, DETAIL1, 
1718                                 "connection_resched: conn %lu attempting closing.\n",
1719                                 conn->c_connid, 0, 0 );
1720 #else
1721                         Debug( LDAP_DEBUG_TRACE, "connection_resched: "
1722                                 "attempting closing conn=%lu sd=%d\n",
1723                                 conn->c_connid, sd, 0 );
1724 #endif
1725                         connection_close( conn );
1726                 }
1727
1728                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1729                 return 0;
1730         }
1731
1732         if( conn->c_conn_state != SLAP_C_ACTIVE || conn->c_writewaiter ) {
1733                 /* other states need different handling */
1734                 return 0;
1735         }
1736
1737         while ((op = LDAP_STAILQ_FIRST( &conn->c_pending_ops )) != NULL) {
1738                 if ( conn->c_n_ops_executing > connection_pool_max/2 ) {
1739                         break;
1740                 }
1741                 LDAP_STAILQ_REMOVE_HEAD( &conn->c_pending_ops, o_next );
1742                 LDAP_STAILQ_NEXT(op, o_next) = NULL;
1743                 /* pending operations should not be marked for abandonment */
1744                 assert(!op->o_abandon);
1745
1746                 conn->c_n_ops_pending--;
1747                 conn->c_n_ops_executing++;
1748
1749                 connection_op_activate( op );
1750
1751                 if ( conn->c_conn_state == SLAP_C_BINDING ) {
1752                         break;
1753                 }
1754         }
1755         return 0;
1756 }
1757
1758 static int connection_op_activate( Operation *op )
1759 {
1760         int status;
1761         ber_tag_t tag = op->o_tag;
1762
1763         if(tag == LDAP_REQ_BIND) {
1764                 op->o_conn->c_conn_state = SLAP_C_BINDING;
1765         }
1766
1767         if (!op->o_dn.bv_len) {
1768                 op->o_authz = op->o_conn->c_authz;
1769                 ber_dupbv( &op->o_dn, &op->o_conn->c_dn );
1770                 ber_dupbv( &op->o_ndn, &op->o_conn->c_ndn );
1771         }
1772         op->o_authtype = op->o_conn->c_authtype;
1773         ber_dupbv( &op->o_authmech, &op->o_conn->c_authmech );
1774         
1775         if (!op->o_protocol) {
1776                 op->o_protocol = op->o_conn->c_protocol
1777                         ? op->o_conn->c_protocol : LDAP_VERSION3;
1778         }
1779         if (op->o_conn->c_conn_state == SLAP_C_INACTIVE
1780                 && op->o_protocol > LDAP_VERSION2)
1781         {
1782                 op->o_conn->c_conn_state = SLAP_C_ACTIVE;
1783         }
1784
1785         op->o_connid = op->o_conn->c_connid;
1786
1787         LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next );
1788
1789         status = ldap_pvt_thread_pool_submit( &connection_pool,
1790                 connection_operation, (void *) op );
1791
1792         if ( status != 0 ) {
1793 #ifdef NEW_LOGGING
1794                 LDAP_LOG( CONNECTION, ERR, 
1795                         "connection_op_activate: conn %lu        thread pool submit failed.\n",
1796                         op->o_connid, 0, 0 );
1797 #else
1798                 Debug( LDAP_DEBUG_ANY,
1799                         "ldap_pvt_thread_pool_submit: failed (%d) for conn=%lu\n",
1800                         status, op->o_connid, 0 );
1801 #endif
1802                 /* should move op to pending list */
1803         }
1804
1805         return status;
1806 }
1807
1808 int connection_write(ber_socket_t s)
1809 {
1810         Connection *c;
1811
1812         assert( connections != NULL );
1813
1814         ldap_pvt_thread_mutex_lock( &connections_mutex );
1815
1816         c = connection_get( s );
1817
1818         slapd_clr_write( s, 0);
1819
1820         if( c == NULL ) {
1821 #ifdef NEW_LOGGING
1822                 LDAP_LOG( CONNECTION, ERR, 
1823                         "connection_write: sock %ld no connection!\n", (long)s, 0, 0);
1824 #else
1825                 Debug( LDAP_DEBUG_ANY,
1826                         "connection_write(%ld): no connection!\n",
1827                         (long)s, 0, 0 );
1828 #endif
1829                 slapd_remove(s, 1, 0);
1830                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1831                 return -1;
1832         }
1833
1834         c->c_n_write++;
1835
1836 #ifdef NEW_LOGGING
1837         LDAP_LOG( CONNECTION, DETAIL1, 
1838                 "connection_write conn %lu waking output.\n", c->c_connid, 0, 0 );
1839 #else
1840         Debug( LDAP_DEBUG_TRACE,
1841                 "connection_write(%d): waking output for id=%lu\n",
1842                 s, c->c_connid, 0 );
1843 #endif
1844         ldap_pvt_thread_cond_signal( &c->c_write_cv );
1845
1846         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
1847                 slapd_set_read( s, 1 );
1848         }
1849         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
1850                 slapd_set_write( s, 1 );
1851         }
1852         connection_return( c );
1853         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1854         return 0;
1855 }
1856