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