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