]> git.sur5r.net Git - openldap/blob - servers/slapd/connection.c
Fix prev commit
[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
173                 ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
174
175                 /* connections_mutex and c_mutex are locked */
176                 connection_closing( &connections[i] );
177                 connection_close( &connections[i] );
178
179                 ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
180         }
181
182         ldap_pvt_thread_mutex_unlock( &connections_mutex );
183
184         return 0;
185 }
186
187 /*
188  * Timeout idle connections.
189  */
190 int connections_timeout_idle(time_t now)
191 {
192         int i = 0;
193         int connindex;
194         Connection* c;
195
196         for( c = connection_first( &connindex );
197                 c != NULL;
198                 c = connection_next( c, &connindex ) )
199         {
200                 /* Don't timeout a slow-running request */
201                 if( c->c_n_ops_executing ) continue;
202
203                 if( difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
204                         /* close it */
205                         connection_closing( c );
206                         connection_close( c );
207                         i++;
208                 }
209         }
210         connection_done( c );
211
212         return i;
213 }
214
215 static Connection* connection_get( ber_socket_t s )
216 {
217         /* connections_mutex should be locked by caller */
218
219         Connection *c;
220
221 #ifdef NEW_LOGGING
222         LDAP_LOG( CONNECTION, ENTRY, "connection_get: socket %ld\n", (long)s, 0, 0 );
223 #else
224         Debug( LDAP_DEBUG_ARGS,
225                 "connection_get(%ld)\n",
226                 (long) s, 0, 0 );
227 #endif
228
229         assert( connections != NULL );
230
231         if(s == AC_SOCKET_INVALID) {
232                 return NULL;
233         }
234
235 #ifndef HAVE_WINSOCK
236         c = &connections[s];
237
238         assert( c->c_struct_state != SLAP_C_UNINITIALIZED );
239
240 #else
241         c = NULL;
242         {
243                 ber_socket_t i, sd;
244
245                 for(i=0; i<dtblsize; i++) {
246                         if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
247                                 assert( connections[i].c_conn_state == SLAP_C_INVALID );
248                                 assert( connections[i].c_sb == 0 );
249                                 break;
250                         }
251
252                         ber_sockbuf_ctrl( connections[i].c_sb,
253                                 LBER_SB_OPT_GET_FD, &sd );
254
255                         if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
256                                 assert( connections[i].c_conn_state == SLAP_C_INVALID );
257                                 assert( sd == AC_SOCKET_INVALID );
258                                 continue;
259                         }
260
261                         /* state can actually change from used -> unused by resched,
262                          * so don't assert details here.
263                          */
264
265                         if( sd == s ) {
266                                 c = &connections[i];
267                                 break;
268                         }
269                 }
270         }
271 #endif
272
273         if( c != NULL ) {
274                 ber_socket_t    sd;
275
276                 ldap_pvt_thread_mutex_lock( &c->c_mutex );
277
278                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
279                 if( c->c_struct_state != SLAP_C_USED ) {
280                         /* connection must have been closed due to resched */
281
282                         assert( c->c_conn_state == SLAP_C_INVALID );
283                         assert( sd == AC_SOCKET_INVALID );
284
285 #ifdef NEW_LOGGING
286                         LDAP_LOG( CONNECTION, ARGS, 
287                                 "connection_get:  connection %d not used\n", s, 0, 0 );
288 #else
289                         Debug( LDAP_DEBUG_TRACE,
290                                 "connection_get(%d): connection not used\n",
291                                 s, 0, 0 );
292 #endif
293
294                         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
295                         return NULL;
296                 }
297
298 #ifdef NEW_LOGGING
299                 LDAP_LOG( CONNECTION, RESULTS, 
300                         "connection_get: get for %d got connid %lu\n", s, c->c_connid, 0 );
301 #else
302                 Debug( LDAP_DEBUG_TRACE,
303                         "connection_get(%d): got connid=%lu\n",
304                         s, c->c_connid, 0 );
305 #endif
306
307                 c->c_n_get++;
308
309                 assert( c->c_struct_state == SLAP_C_USED );
310                 assert( c->c_conn_state != SLAP_C_INVALID );
311                 assert( sd != AC_SOCKET_INVALID );
312
313 #ifdef SLAPD_MONITOR
314                 c->c_activitytime = slap_get_time();
315 #else
316                 if( global_idletimeout > 0 ) {
317                         c->c_activitytime = slap_get_time();
318                 }
319 #endif
320         }
321
322         return c;
323 }
324
325 static void connection_return( Connection *c )
326 {
327         ldap_pvt_thread_mutex_unlock( &c->c_mutex );
328 }
329
330 long connection_init(
331         ber_socket_t s,
332         Listener *listener,
333         const char* dnsname,
334         const char* peername,
335         int tls_udp_option,
336         slap_ssf_t ssf,
337         const char *authid )
338 {
339         unsigned long id;
340         Connection *c;
341
342         assert( connections != NULL );
343
344         assert( listener != NULL );
345         assert( dnsname != NULL );
346         assert( peername != NULL );
347
348 #ifndef HAVE_TLS
349         assert( tls_udp_option != 1 );
350 #endif
351
352         if( s == AC_SOCKET_INVALID ) {
353 #ifdef NEW_LOGGING
354                 LDAP_LOG( CONNECTION, INFO, 
355                            "connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 );
356 #else
357                 Debug( LDAP_DEBUG_ANY,
358                        "connection_init(%ld): invalid.\n",
359                        (long) s, 0, 0 );
360 #endif
361                 return -1;
362         }
363
364         assert( s >= 0 );
365 #ifndef HAVE_WINSOCK
366         assert( s < dtblsize );
367 #endif
368
369         ldap_pvt_thread_mutex_lock( &connections_mutex );
370
371 #ifndef HAVE_WINSOCK
372         c = &connections[s];
373
374 #else
375         {
376                 ber_socket_t    i;
377
378                 c = NULL;
379
380         for( i=0; i < dtblsize; i++) {
381                 ber_socket_t    sd;
382
383             if( connections[i].c_struct_state == SLAP_C_UNINITIALIZED ) {
384                 assert( connections[i].c_sb == 0 );
385                 c = &connections[i];
386                 break;
387             }
388
389                         sd = AC_SOCKET_INVALID;
390                         if (connections[i].c_sb != NULL)
391                         ber_sockbuf_ctrl( connections[i].c_sb, LBER_SB_OPT_GET_FD, &sd );
392             
393             if( connections[i].c_struct_state == SLAP_C_UNUSED ) {
394                 assert( sd == AC_SOCKET_INVALID );
395                 c = &connections[i];
396                 break;
397             }
398
399             assert( connections[i].c_struct_state == SLAP_C_USED );
400             assert( connections[i].c_conn_state != SLAP_C_INVALID );
401             assert( sd != AC_SOCKET_INVALID );
402         }
403
404         if( c == NULL ) {
405 #ifdef NEW_LOGGING
406                 LDAP_LOG( CONNECTION, INFO, 
407                            "connection_init: skt %d connection table full "
408                            "(%d/%d)\n", s, i, dtblsize );
409 #else
410                 Debug( LDAP_DEBUG_ANY,
411                                 "connection_init(%d): connection table full "
412                                 "(%d/%d)\n", s, i, dtblsize);
413 #endif
414             ldap_pvt_thread_mutex_unlock( &connections_mutex );
415             return -1;
416         }
417         }
418 #endif
419
420         assert( c != NULL );
421
422         if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
423                 c->c_send_ldap_result = slap_send_ldap_result;
424                 c->c_send_search_entry = slap_send_search_entry;
425                 c->c_send_search_reference = slap_send_search_reference;
426                 c->c_send_ldap_extended = slap_send_ldap_extended;
427 #ifdef LDAP_RES_INTERMEDIATE
428                 c->c_send_ldap_intermediate = slap_send_ldap_intermediate;
429 #endif
430
431                 c->c_authmech.bv_val = NULL;
432                 c->c_authmech.bv_len = 0;
433                 c->c_dn.bv_val = NULL;
434                 c->c_dn.bv_len = 0;
435                 c->c_ndn.bv_val = NULL;
436                 c->c_ndn.bv_len = 0;
437
438                 c->c_listener = NULL;
439                 c->c_peer_domain.bv_val = NULL;
440                 c->c_peer_domain.bv_len = 0;
441                 c->c_peer_name.bv_val = NULL;
442                 c->c_peer_name.bv_len = 0;
443
444                 LDAP_STAILQ_INIT(&c->c_ops);
445                 LDAP_STAILQ_INIT(&c->c_pending_ops);
446
447                 c->c_sasl_bind_mech.bv_val = NULL;
448                 c->c_sasl_bind_mech.bv_len = 0;
449                 c->c_sasl_done = 0;
450                 c->c_sasl_authctx = NULL;
451                 c->c_sasl_sockctx = NULL;
452                 c->c_sasl_extra = NULL;
453                 c->c_sasl_bindop = NULL;
454
455                 c->c_sb = ber_sockbuf_alloc( );
456
457                 {
458                         ber_len_t max = sockbuf_max_incoming;
459                         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
460                 }
461
462                 c->c_currentber = NULL;
463
464                 /* should check status of thread calls */
465                 ldap_pvt_thread_mutex_init( &c->c_mutex );
466                 ldap_pvt_thread_mutex_init( &c->c_write_mutex );
467                 ldap_pvt_thread_cond_init( &c->c_write_cv );
468
469 #ifdef LDAP_SLAPI
470                 if ( slapi_plugins_used ) {
471                         slapi_x_create_object_extensions( SLAPI_X_EXT_CONNECTION, c );
472                 }
473 #endif
474
475                 c->c_struct_state = SLAP_C_UNUSED;
476         }
477
478     ldap_pvt_thread_mutex_lock( &c->c_mutex );
479
480     assert( c->c_struct_state == SLAP_C_UNUSED );
481     assert( c->c_authmech.bv_val == NULL );
482     assert( c->c_dn.bv_val == NULL );
483     assert( c->c_ndn.bv_val == NULL );
484     assert( c->c_listener == NULL );
485     assert( c->c_peer_domain.bv_val == NULL );
486     assert( c->c_peer_name.bv_val == NULL );
487     assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
488     assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) );
489         assert( c->c_sasl_bind_mech.bv_val == NULL );
490         assert( c->c_sasl_done == 0 );
491         assert( c->c_sasl_authctx == NULL );
492         assert( c->c_sasl_sockctx == NULL );
493         assert( c->c_sasl_extra == NULL );
494         assert( c->c_sasl_bindop == NULL );
495         assert( c->c_currentber == NULL );
496
497         c->c_listener = listener;
498         ber_str2bv( dnsname, 0, 1, &c->c_peer_domain );
499         ber_str2bv( peername, 0, 1, &c->c_peer_name );
500
501     c->c_n_ops_received = 0;
502     c->c_n_ops_executing = 0;
503     c->c_n_ops_pending = 0;
504     c->c_n_ops_completed = 0;
505
506         c->c_n_get = 0;
507         c->c_n_read = 0;
508         c->c_n_write = 0;
509
510         /* set to zero until bind, implies LDAP_VERSION3 */
511         c->c_protocol = 0;
512
513 #ifdef SLAPD_MONITOR
514         c->c_activitytime = c->c_starttime = slap_get_time();
515 #else
516         if( global_idletimeout > 0 ) {
517                 c->c_activitytime = c->c_starttime = slap_get_time();
518         }
519 #endif
520
521 #ifdef LDAP_CONNECTIONLESS
522         c->c_is_udp = 0;
523         if( tls_udp_option == 2 ) {
524                 c->c_is_udp = 1;
525 #ifdef LDAP_DEBUG
526                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
527                         LBER_SBIOD_LEVEL_PROVIDER, (void*)"udp_" );
528 #endif
529                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_udp,
530                         LBER_SBIOD_LEVEL_PROVIDER, (void *)&s );
531                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
532                         LBER_SBIOD_LEVEL_PROVIDER, NULL );
533         } else
534 #endif
535         {
536 #ifdef LDAP_DEBUG
537                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
538                         LBER_SBIOD_LEVEL_PROVIDER, (void*)"tcp_" );
539 #endif
540                 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_tcp,
541                         LBER_SBIOD_LEVEL_PROVIDER, (void *)&s );
542         }
543
544 #ifdef LDAP_DEBUG
545         ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
546                 INT_MAX, (void*)"ldap_" );
547 #endif
548
549         if( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_NONBLOCK,
550                 c /* non-NULL */ ) < 0 )
551         {
552 #ifdef NEW_LOGGING
553                 LDAP_LOG( CONNECTION, INFO, 
554                            "connection_init: conn %lu  set nonblocking failed\n",
555                            c->c_connid, 0, 0 );
556 #else
557                 Debug( LDAP_DEBUG_ANY,
558                         "connection_init(%d, %s): set nonblocking failed\n",
559                         s, c->c_peer_name.bv_val, 0 );
560 #endif
561         }
562
563     id = c->c_connid = conn_nextid++;
564
565     c->c_conn_state = SLAP_C_INACTIVE;
566     c->c_struct_state = SLAP_C_USED;
567
568         c->c_ssf = c->c_transport_ssf = ssf;
569         c->c_tls_ssf = 0;
570
571 #ifdef HAVE_TLS
572     if ( tls_udp_option == 1 ) {
573             c->c_is_tls = 1;
574             c->c_needs_tls_accept = 1;
575     } else {
576             c->c_is_tls = 0;
577             c->c_needs_tls_accept = 0;
578     }
579 #endif
580
581         slap_sasl_open( c, 0 );
582         slap_sasl_external( c, ssf, authid );
583
584     ldap_pvt_thread_mutex_unlock( &c->c_mutex );
585     ldap_pvt_thread_mutex_unlock( &connections_mutex );
586
587     backend_connection_init(c);
588
589     return id;
590 }
591
592 void connection2anonymous( Connection *c )
593 {
594         assert( connections != NULL );
595         assert( c != NULL );
596
597         {
598                 ber_len_t max = sockbuf_max_incoming;
599                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
600         }
601
602         if(c->c_authmech.bv_val != NULL ) {
603                 free(c->c_authmech.bv_val);
604                 c->c_authmech.bv_val = NULL;
605         }
606         c->c_authmech.bv_len = 0;
607
608         if(c->c_dn.bv_val != NULL) {
609                 free(c->c_dn.bv_val);
610                 c->c_dn.bv_val = NULL;
611         }
612         c->c_dn.bv_len = 0;
613         if(c->c_ndn.bv_val != NULL) {
614                 free(c->c_ndn.bv_val);
615                 c->c_ndn.bv_val = NULL;
616         }
617         c->c_ndn.bv_len = 0;
618
619         c->c_authz_backend = NULL;
620 }
621
622 static void
623 connection_destroy( Connection *c )
624 {
625         /* note: connections_mutex should be locked by caller */
626     ber_socket_t        sd;
627     unsigned long       connid;
628
629     assert( connections != NULL );
630     assert( c != NULL );
631     assert( c->c_struct_state != SLAP_C_UNUSED );
632     assert( c->c_conn_state != SLAP_C_INVALID );
633     assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
634
635     /* only for stats (print -1 as "%lu" may give unexpected results ;) */
636     connid = c->c_connid;
637
638     backend_connection_destroy(c);
639
640     c->c_protocol = 0;
641     c->c_connid = -1;
642
643     c->c_activitytime = c->c_starttime = 0;
644
645         connection2anonymous( c );
646         c->c_listener = NULL;
647
648         if(c->c_peer_domain.bv_val != NULL) {
649                 free(c->c_peer_domain.bv_val);
650                 c->c_peer_domain.bv_val = NULL;
651         }
652         c->c_peer_domain.bv_len = 0;
653         if(c->c_peer_name.bv_val != NULL) {
654                 free(c->c_peer_name.bv_val);
655                 c->c_peer_name.bv_val = NULL;
656         }
657         c->c_peer_name.bv_len = 0;
658
659         c->c_sasl_bind_in_progress = 0;
660         if(c->c_sasl_bind_mech.bv_val != NULL) {
661                 free(c->c_sasl_bind_mech.bv_val);
662                 c->c_sasl_bind_mech.bv_val = NULL;
663         }
664         c->c_sasl_bind_mech.bv_len = 0;
665
666         slap_sasl_close( c );
667
668         if ( c->c_currentber != NULL ) {
669                 ber_free( c->c_currentber, 1 );
670                 c->c_currentber = NULL;
671         }
672
673         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_GET_FD, &sd );
674         if ( sd != AC_SOCKET_INVALID ) {
675                 slapd_remove( sd, 0 );
676
677                 Statslog( LDAP_DEBUG_STATS,
678                     "conn=%lu fd=%ld closed\n",
679                         connid, (long) sd, 0, 0, 0 );
680         }
681
682         ber_sockbuf_free( c->c_sb );
683
684         c->c_sb = ber_sockbuf_alloc( );
685
686         {
687                 ber_len_t max = sockbuf_max_incoming;
688                 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
689         }
690
691     c->c_conn_state = SLAP_C_INVALID;
692     c->c_struct_state = SLAP_C_UNUSED;
693
694 #ifdef LDAP_SLAPI
695         /* call destructors, then constructors; avoids unnecessary allocation */
696         if ( slapi_plugins_used ) {
697                 slapi_x_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
698         }
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         if ( op->o_cancel != SLAP_CANCEL_ACK && ( op->o_sync_mode & SLAP_SYNC_PERSIST ) ) {
1083                 sl_mem_detach( ctx, memctx );
1084                 goto no_co_op_free;
1085         }
1086
1087         LDAP_STAILQ_REMOVE( &conn->c_ops, op, slap_op, o_next);
1088         LDAP_STAILQ_NEXT(op, o_next) = NULL;
1089
1090         conn->c_n_ops_executing--;
1091         conn->c_n_ops_completed++;
1092         memctx = NULL;
1093         ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx );
1094         slap_op_free( op );
1095
1096 no_co_op_free:
1097
1098         switch( tag ) {
1099         case LBER_ERROR:
1100         case LDAP_REQ_UNBIND:
1101                 /* c_mutex is locked */
1102                 connection_closing( conn );
1103                 break;
1104
1105         case LDAP_REQ_BIND:
1106                 conn->c_sasl_bind_in_progress =
1107                         rc == LDAP_SASL_BIND_IN_PROGRESS ? 1 : 0;
1108
1109                 if( conn->c_conn_state == SLAP_C_BINDING) {
1110                         conn->c_conn_state = SLAP_C_ACTIVE;
1111                 }
1112         }
1113
1114         connection_resched( conn );
1115
1116         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
1117
1118         return NULL;
1119 }
1120
1121 int connection_read(ber_socket_t s)
1122 {
1123         int rc = 0;
1124         Connection *c;
1125
1126         assert( connections != NULL );
1127
1128         ldap_pvt_thread_mutex_lock( &connections_mutex );
1129
1130         /* get (locked) connection */
1131         c = connection_get( s );
1132
1133         if( c == NULL ) {
1134 #ifdef NEW_LOGGING
1135                 LDAP_LOG( CONNECTION, INFO, 
1136                         "connection_read: sock %ld no connection\n", (long)s, 0, 0 );
1137 #else
1138                 Debug( LDAP_DEBUG_ANY,
1139                         "connection_read(%ld): no connection!\n",
1140                         (long) s, 0, 0 );
1141 #endif
1142                 slapd_remove(s, 0);
1143
1144                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1145                 return -1;
1146         }
1147
1148         c->c_n_read++;
1149
1150         if( c->c_conn_state == SLAP_C_CLOSING ) {
1151 #ifdef NEW_LOGGING
1152                 LDAP_LOG( CONNECTION, INFO, 
1153                         "connection_read: conn %lu connection closing, ignoring input\n",
1154                         c->c_connid, 0, 0 );
1155 #else
1156                 Debug( LDAP_DEBUG_TRACE,
1157                         "connection_read(%d): closing, ignoring input for id=%lu\n",
1158                         s, c->c_connid, 0 );
1159 #endif
1160                 connection_return( c );
1161                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1162                 return 0;
1163         }
1164
1165 #ifdef NEW_LOGGING
1166         LDAP_LOG( CONNECTION, DETAIL1, 
1167                    "connection_read: conn %lu  checking for input.\n", 
1168                    c->c_connid, 0, 0  );
1169 #else
1170         Debug( LDAP_DEBUG_TRACE,
1171                 "connection_read(%d): checking for input on id=%lu\n",
1172                 s, c->c_connid, 0 );
1173 #endif
1174
1175 #ifdef HAVE_TLS
1176         if ( c->c_is_tls && c->c_needs_tls_accept ) {
1177                 rc = ldap_pvt_tls_accept( c->c_sb, NULL );
1178                 if ( rc < 0 ) {
1179 #if 0 /* required by next #if 0 */
1180                         struct timeval tv;
1181                         fd_set rfd;
1182 #endif
1183
1184 #ifdef NEW_LOGGING
1185                         LDAP_LOG( CONNECTION, ERR, 
1186                                    "connection_read: conn %lu  TLS accept error, error %d\n",
1187                                    c->c_connid, rc, 0 );
1188 #else
1189                         Debug( LDAP_DEBUG_TRACE,
1190                                 "connection_read(%d): TLS accept error "
1191                                 "error=%d id=%lu, closing\n",
1192                                 s, rc, c->c_connid );
1193 #endif
1194                         c->c_needs_tls_accept = 0;
1195                         /* connections_mutex and c_mutex are locked */
1196                         connection_closing( c );
1197
1198 #if 0
1199                         /* Drain input before close, to allow SSL error codes
1200                          * to propagate to client. */
1201                         FD_ZERO(&rfd);
1202                         FD_SET(s, &rfd);
1203                         for (rc=1; rc>0;) {
1204                             tv.tv_sec = 1;
1205                             tv.tv_usec = 0;
1206                             rc = select(s+1, &rfd, NULL, NULL, &tv);
1207                             if (rc == 1) {
1208                                         ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DRAIN, NULL);
1209                                 }
1210                         }
1211 #endif
1212                         connection_close( c );
1213
1214                 } else if ( rc == 0 ) {
1215                         void *ssl;
1216                         struct berval authid = { 0, NULL };
1217
1218                         c->c_needs_tls_accept = 0;
1219
1220                         /* we need to let SASL know */
1221                         ssl = ldap_pvt_tls_sb_ctx( c->c_sb );
1222
1223                         c->c_tls_ssf = (slap_ssf_t) ldap_pvt_tls_get_strength( ssl );
1224                         if( c->c_tls_ssf > c->c_ssf ) {
1225                                 c->c_ssf = c->c_tls_ssf;
1226                         }
1227
1228                         rc = dnX509peerNormalize( ssl, &authid );
1229                         if ( rc != LDAP_SUCCESS ) {
1230 #ifdef NEW_LOGGING
1231                                 LDAP_LOG( CONNECTION, INFO, 
1232                                         "connection_read: conn %lu unable to get TLS client DN, "
1233                                         "error %d\n", c->c_connid, rc, 0 );
1234 #else
1235                                 Debug( LDAP_DEBUG_TRACE,
1236                                 "connection_read(%d): unable to get TLS client DN "
1237                                 "error=%d id=%lu\n",
1238                                 s, rc, c->c_connid );
1239 #endif
1240                         }
1241                         slap_sasl_external( c, c->c_tls_ssf, authid.bv_val );
1242                         if ( authid.bv_val )    free( authid.bv_val );
1243                 }
1244
1245                 /* if success and data is ready, fall thru to data input loop */
1246                 if( rc != 0 ||
1247                         !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
1248                 {
1249                         connection_return( c );
1250                         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1251                         return 0;
1252                 }
1253         }
1254 #endif
1255
1256 #ifdef HAVE_CYRUS_SASL
1257         if ( c->c_sasl_layers ) {
1258                 /* If previous layer is not removed yet, give up for now */
1259                 if ( !c->c_sasl_sockctx ) {
1260                         connection_return( c );
1261                         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1262                         return 0;
1263                 }
1264
1265                 c->c_sasl_layers = 0;
1266
1267                 rc = ldap_pvt_sasl_install( c->c_sb,  c->c_sasl_sockctx );
1268
1269                 if( rc != LDAP_SUCCESS ) {
1270 #ifdef NEW_LOGGING
1271                         LDAP_LOG( CONNECTION, ERR, 
1272                                 "connection_read: conn %lu SASL install error %d, closing\n",
1273                                 c->c_connid, rc, 0 );
1274 #else
1275                         Debug( LDAP_DEBUG_TRACE,
1276                                 "connection_read(%d): SASL install error "
1277                                 "error=%d id=%lu, closing\n",
1278                                 s, rc, c->c_connid );
1279 #endif
1280                         /* connections_mutex and c_mutex are locked */
1281                         connection_closing( c );
1282                         connection_close( c );
1283                         connection_return( c );
1284                         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1285                         return 0;
1286                 }
1287         }
1288 #endif
1289
1290 #define CONNECTION_INPUT_LOOP 1
1291 /* #define      DATA_READY_LOOP 1 */
1292
1293         do
1294         {
1295                 /* How do we do this without getting into a busy loop ? */
1296                 rc = connection_input( c );
1297         }
1298 #ifdef DATA_READY_LOOP
1299         while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) );
1300 #elif CONNECTION_INPUT_LOOP
1301         while(!rc);
1302 #else
1303         while(0);
1304 #endif
1305
1306         if( rc < 0 ) {
1307 #ifdef NEW_LOGGING
1308                 LDAP_LOG( CONNECTION, ERR, 
1309                         "connection_read: conn %lu  input error %d, closing.\n",
1310                         c->c_connid, rc, 0 );
1311 #else
1312                 Debug( LDAP_DEBUG_TRACE,
1313                         "connection_read(%d): input error=%d id=%lu, closing.\n",
1314                         s, rc, c->c_connid );
1315 #endif
1316                 /* connections_mutex and c_mutex are locked */
1317                 connection_closing( c );
1318                 connection_close( c );
1319                 connection_return( c );
1320                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1321                 return 0;
1322         }
1323
1324         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
1325                 slapd_set_read( s, 1 );
1326         }
1327
1328         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
1329                 slapd_set_write( s, 1 );
1330         }
1331
1332         connection_return( c );
1333         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1334         return 0;
1335 }
1336
1337 static int
1338 connection_input(
1339     Connection *conn
1340 )
1341 {
1342         Operation *op;
1343         ber_tag_t       tag;
1344         ber_len_t       len;
1345         ber_int_t       msgid;
1346         BerElement      *ber;
1347         int             rc;
1348 #ifdef LDAP_CONNECTIONLESS
1349         Sockaddr        peeraddr;
1350         char            *cdn = NULL;
1351 #endif
1352
1353         if ( conn->c_currentber == NULL &&
1354                 ( conn->c_currentber = ber_alloc()) == NULL )
1355         {
1356 #ifdef NEW_LOGGING
1357                 LDAP_LOG( CONNECTION, ERR, 
1358                         "connection_input: conn %lu  ber_alloc failed.\n", 
1359                         conn->c_connid, 0, 0 );
1360 #else
1361                 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
1362 #endif
1363                 return -1;
1364         }
1365
1366         errno = 0;
1367
1368 #ifdef LDAP_CONNECTIONLESS
1369         if ( conn->c_is_udp ) {
1370                 char    peername[sizeof("IP=255.255.255.255:65336")];
1371                 len = ber_int_sb_read(conn->c_sb, &peeraddr,
1372                         sizeof(struct sockaddr));
1373                 if (len != sizeof(struct sockaddr))
1374                         return 1;
1375                 sprintf( peername, "IP=%s:%d",
1376                         inet_ntoa( peeraddr.sa_in_addr.sin_addr ),
1377                         (unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) );
1378                 Statslog( LDAP_DEBUG_STATS,
1379                         "conn=%lu UDP request from %s (%s) accepted.\n",
1380                         conn->c_connid, peername, conn->c_sock_name.bv_val, 0, 0 );
1381         }
1382 #endif
1383         tag = ber_get_next( conn->c_sb, &len, conn->c_currentber );
1384         if ( tag != LDAP_TAG_MESSAGE ) {
1385                 int err = errno;
1386                 ber_socket_t    sd;
1387
1388                 ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
1389
1390 #ifdef NEW_LOGGING
1391                 LDAP_LOG( CONNECTION, ERR, 
1392                         "connection_input: conn %lu  ber_get_next failed, errno %d (%s).\n",
1393                         conn->c_connid, err, sock_errstr(err) );
1394 #else
1395                 Debug( LDAP_DEBUG_TRACE,
1396                         "ber_get_next on fd %d failed errno=%d (%s)\n",
1397                         sd, err, sock_errstr(err) );
1398 #endif
1399                 if ( err != EWOULDBLOCK && err != EAGAIN ) {
1400                         /* log, close and send error */
1401                         ber_free( conn->c_currentber, 1 );
1402                         conn->c_currentber = NULL;
1403
1404                         return -2;
1405                 }
1406                 return 1;
1407         }
1408
1409         ber = conn->c_currentber;
1410         conn->c_currentber = NULL;
1411
1412         if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
1413                 /* log, close and send error */
1414 #ifdef NEW_LOGGING
1415                 LDAP_LOG( CONNECTION, ERR, 
1416                         "connection_input: conn %lu  ber_get_int returns 0x%lx.\n",
1417                         conn->c_connid, tag, 0 );
1418 #else
1419                 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0,
1420                     0 );
1421 #endif
1422                 ber_free( ber, 1 );
1423                 return -1;
1424         }
1425
1426         if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
1427                 /* log, close and send error */
1428 #ifdef NEW_LOGGING
1429                 LDAP_LOG( CONNECTION, ERR, 
1430                            "connection_input: conn %lu  ber_peek_tag returns 0x%lx.\n",
1431                            conn->c_connid, tag, 0 );
1432 #else
1433                 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0,
1434                     0 );
1435 #endif
1436                 ber_free( ber, 1 );
1437
1438                 return -1;
1439         }
1440
1441 #ifdef LDAP_CONNECTIONLESS
1442         if( conn->c_is_udp ) {
1443                 if( tag == LBER_OCTETSTRING ) {
1444                         ber_get_stringa( ber, &cdn );
1445                         tag = ber_peek_tag(ber, &len);
1446                 }
1447                 if( tag != LDAP_REQ_ABANDON && tag != LDAP_REQ_SEARCH ) {
1448 #ifdef NEW_LOGGING
1449                     LDAP_LOG( CONNECTION, ERR, 
1450                                "connection_input: conn %lu  invalid req for UDP 0x%lx.\n",
1451                                conn->c_connid, tag, 0 );
1452 #else
1453                     Debug( LDAP_DEBUG_ANY, "invalid req for UDP 0x%lx\n", tag, 0,
1454                         0 );
1455 #endif
1456                     ber_free( ber, 1 );
1457                     return 0;
1458                 }
1459         }
1460 #endif
1461         if(tag == LDAP_REQ_BIND) {
1462                 /* immediately abandon all exiting operations upon BIND */
1463                 connection_abandon( conn );
1464         }
1465
1466         op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++ );
1467
1468         op->o_conn = conn;
1469         op->o_assertion = NULL;
1470         op->o_preread_attrs = NULL;
1471         op->o_postread_attrs = NULL;
1472         op->o_vrFilter = NULL;
1473
1474 #ifdef LDAP_CONTROL_PAGEDRESULTS
1475         op->o_pagedresults_state = conn->c_pagedresults_state;
1476 #endif
1477
1478         op->o_res_ber = NULL;
1479
1480 #ifdef LDAP_CONNECTIONLESS
1481         if (conn->c_is_udp) {
1482                 if ( cdn ) {
1483                     ber_str2bv( cdn, 0, 1, &op->o_dn );
1484                     op->o_protocol = LDAP_VERSION2;
1485                 }
1486                 op->o_res_ber = ber_alloc_t( LBER_USE_DER );
1487                 if (op->o_res_ber == NULL) return 1;
1488
1489                 rc = ber_write( op->o_res_ber, (char *)&peeraddr,
1490                         sizeof(struct sockaddr), 0 );
1491
1492                 if (rc != sizeof(struct sockaddr)) {
1493 #ifdef NEW_LOGGING
1494                         LDAP_LOG( CONNECTION, INFO, 
1495                                 "connection_input: conn %lu  ber_write failed\n",
1496                                 conn->c_connid, 0, 0 );
1497 #else
1498                         Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
1499 #endif
1500                         return 1;
1501                 }
1502
1503                 if (op->o_protocol == LDAP_VERSION2) {
1504                         rc = ber_printf(op->o_res_ber, "{is{" /*}}*/, op->o_msgid, "");
1505                         if (rc == -1) {
1506 #ifdef NEW_LOGGING
1507                                 LDAP_LOG( CONNECTION, INFO, 
1508                                         "connection_input: conn %lu  put outer sequence failed\n",
1509                                         conn->c_connid, 0, 0 );
1510 #else
1511                                 Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
1512 #endif
1513                                 return rc;
1514                         }
1515                 }
1516         }
1517 #endif /* LDAP_CONNECTIONLESS */
1518
1519         rc = 0;
1520
1521         /* Don't process requests when the conn is in the middle of a
1522          * Bind, or if it's closing. Also, don't let any single conn
1523          * use up all the available threads, and don't execute if we're
1524          * currently blocked on output. And don't execute if there are
1525          * already pending ops, let them go first.
1526          *
1527          * But always allow Abandon through; it won't cost much.
1528          */
1529         if ( tag != LDAP_REQ_ABANDON && (conn->c_conn_state == SLAP_C_BINDING
1530                 || conn->c_conn_state == SLAP_C_CLOSING
1531                 || conn->c_n_ops_executing >= connection_pool_max/2
1532                 || conn->c_n_ops_pending
1533                 || conn->c_writewaiter))
1534         {
1535                 int max = conn->c_dn.bv_len ? slap_conn_max_pending_auth
1536                          : slap_conn_max_pending;
1537 #ifdef NEW_LOGGING
1538                 LDAP_LOG( CONNECTION, INFO, 
1539                         "connection_input: conn %lu  deferring operation\n",
1540                         conn->c_connid, 0, 0 );
1541 #else
1542                 Debug( LDAP_DEBUG_ANY, "deferring operation\n", 0, 0, 0 );
1543 #endif
1544                 conn->c_n_ops_pending++;
1545                 LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next );
1546                 if ( conn->c_n_ops_pending > max ) {
1547                         rc = -1;
1548                 } else {
1549                         rc = 1;
1550                 }
1551         } else {
1552                 conn->c_n_ops_executing++;
1553                 connection_op_activate( op );
1554         }
1555
1556 #ifdef NO_THREADS
1557         if ( conn->c_struct_state != SLAP_C_USED ) {
1558                 /* connection must have got closed underneath us */
1559                 return 1;
1560         }
1561 #endif
1562         assert( conn->c_struct_state == SLAP_C_USED );
1563
1564         return rc;
1565 }
1566
1567 static int
1568 connection_resched( Connection *conn )
1569 {
1570         Operation *op;
1571
1572         if( conn->c_conn_state == SLAP_C_CLOSING ) {
1573                 int rc;
1574                 ber_socket_t    sd;
1575                 ber_sockbuf_ctrl( conn->c_sb, LBER_SB_OPT_GET_FD, &sd );
1576
1577                 /* us trylock to avoid possible deadlock */
1578                 rc = ldap_pvt_thread_mutex_trylock( &connections_mutex );
1579
1580                 if( rc ) {
1581 #ifdef NEW_LOGGING
1582                         LDAP_LOG( CONNECTION, DETAIL1, 
1583                                 "connection_resched: conn %lu  reaquiring locks.\n",
1584                                 conn->c_connid, 0, 0 );
1585 #else
1586                         Debug( LDAP_DEBUG_TRACE,
1587                                 "connection_resched: reaquiring locks conn=%lu sd=%d\n",
1588                                 conn->c_connid, sd, 0 );
1589 #endif
1590                         /*
1591                          * reaquire locks in the right order...
1592                          * this may allow another thread to close this connection,
1593                          * so recheck state below.
1594                          */
1595                         ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
1596                         ldap_pvt_thread_mutex_lock( &connections_mutex );
1597                         ldap_pvt_thread_mutex_lock( &conn->c_mutex );
1598                 }
1599
1600                 if( conn->c_conn_state != SLAP_C_CLOSING ) {
1601 #ifdef NEW_LOGGING
1602                         LDAP_LOG( CONNECTION, INFO, 
1603                                 "connection_resched: conn %lu  closed by other thread.\n",
1604                                 conn->c_connid, 0, 0 );
1605 #else
1606                         Debug( LDAP_DEBUG_TRACE, "connection_resched: "
1607                                 "closed by other thread conn=%lu sd=%d\n",
1608                                 conn->c_connid, sd, 0 );
1609 #endif
1610                 } else {
1611 #ifdef NEW_LOGGING
1612                         LDAP_LOG( CONNECTION, DETAIL1, 
1613                                 "connection_resched: conn %lu  attempting closing.\n",
1614                                 conn->c_connid, 0, 0 );
1615 #else
1616                         Debug( LDAP_DEBUG_TRACE, "connection_resched: "
1617                                 "attempting closing conn=%lu sd=%d\n",
1618                                 conn->c_connid, sd, 0 );
1619 #endif
1620                         connection_close( conn );
1621                 }
1622
1623                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1624                 return 0;
1625         }
1626
1627         if( conn->c_conn_state != SLAP_C_ACTIVE || conn->c_writewaiter ) {
1628                 /* other states need different handling */
1629                 return 0;
1630         }
1631
1632         while ((op = LDAP_STAILQ_FIRST( &conn->c_pending_ops )) != NULL) {
1633                 if ( conn->c_n_ops_executing > connection_pool_max/2 ) {
1634                         break;
1635                 }
1636                 LDAP_STAILQ_REMOVE_HEAD( &conn->c_pending_ops, o_next );
1637                 LDAP_STAILQ_NEXT(op, o_next) = NULL;
1638                 /* pending operations should not be marked for abandonment */
1639                 assert(!op->o_abandon);
1640
1641                 conn->c_n_ops_pending--;
1642                 conn->c_n_ops_executing++;
1643
1644                 connection_op_activate( op );
1645
1646                 if ( conn->c_conn_state == SLAP_C_BINDING ) {
1647                         break;
1648                 }
1649         }
1650         return 0;
1651 }
1652
1653 static int connection_op_activate( Operation *op )
1654 {
1655         int status;
1656         ber_tag_t tag = op->o_tag;
1657
1658         if(tag == LDAP_REQ_BIND) {
1659                 op->o_conn->c_conn_state = SLAP_C_BINDING;
1660         }
1661
1662         if (!op->o_dn.bv_len) {
1663             op->o_authz = op->o_conn->c_authz;
1664             ber_dupbv( &op->o_dn, &op->o_conn->c_dn );
1665             ber_dupbv( &op->o_ndn, &op->o_conn->c_ndn );
1666         }
1667         op->o_authtype = op->o_conn->c_authtype;
1668         ber_dupbv( &op->o_authmech, &op->o_conn->c_authmech );
1669         
1670         if (!op->o_protocol) {
1671             op->o_protocol = op->o_conn->c_protocol
1672                 ? op->o_conn->c_protocol : LDAP_VERSION3;
1673         }
1674         if (op->o_conn->c_conn_state == SLAP_C_INACTIVE
1675                 && op->o_protocol > LDAP_VERSION2) {
1676                 op->o_conn->c_conn_state = SLAP_C_ACTIVE;
1677         }
1678
1679         op->o_connid = op->o_conn->c_connid;
1680
1681         LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next );
1682
1683         status = ldap_pvt_thread_pool_submit( &connection_pool,
1684                 connection_operation, (void *) op );
1685
1686         if ( status != 0 ) {
1687 #ifdef NEW_LOGGING
1688                 LDAP_LOG( CONNECTION, ERR, 
1689                         "connection_op_activate: conn %lu        thread pool submit failed.\n",
1690                         op->o_connid, 0, 0 );
1691 #else
1692                 Debug( LDAP_DEBUG_ANY,
1693                 "ldap_pvt_thread_pool_submit failed (%d)\n", status, 0, 0 );
1694 #endif
1695                 /* should move op to pending list */
1696         }
1697
1698         return status;
1699 }
1700
1701 int connection_write(ber_socket_t s)
1702 {
1703         Connection *c;
1704
1705         assert( connections != NULL );
1706
1707         ldap_pvt_thread_mutex_lock( &connections_mutex );
1708
1709         c = connection_get( s );
1710
1711         slapd_clr_write( s, 0);
1712
1713         if( c == NULL ) {
1714 #ifdef NEW_LOGGING
1715                 LDAP_LOG( CONNECTION, ERR, 
1716                         "connection_write: sock %ld  no connection!\n", (long)s, 0, 0);
1717 #else
1718                 Debug( LDAP_DEBUG_ANY,
1719                         "connection_write(%ld): no connection!\n",
1720                         (long) s, 0, 0 );
1721 #endif
1722                 slapd_remove(s, 0);
1723                 ldap_pvt_thread_mutex_unlock( &connections_mutex );
1724                 return -1;
1725         }
1726
1727         c->c_n_write++;
1728
1729 #ifdef NEW_LOGGING
1730         LDAP_LOG( CONNECTION, DETAIL1, 
1731                 "connection_write conn %lu  waking output.\n", c->c_connid, 0, 0 );
1732 #else
1733         Debug( LDAP_DEBUG_TRACE,
1734                 "connection_write(%d): waking output for id=%lu\n",
1735                 s, c->c_connid, 0 );
1736 #endif
1737         ldap_pvt_thread_cond_signal( &c->c_write_cv );
1738
1739         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) )
1740                 slapd_set_read( s, 1 );
1741         if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) )
1742                 slapd_set_write( s, 1 );
1743         connection_return( c );
1744         ldap_pvt_thread_mutex_unlock( &connections_mutex );
1745         return 0;
1746 }
1747