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