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