Back to index

openldap  2.4.31
connection.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 1998-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00016  * All rights reserved.
00017  *
00018  * Redistribution and use in source and binary forms are permitted
00019  * provided that this notice is preserved and that due credit is given
00020  * to the University of Michigan at Ann Arbor. The name of the University
00021  * may not be used to endorse or promote products derived from this
00022  * software without specific prior written permission. This software
00023  * is provided ``as is'' without express or implied warranty.
00024  */
00025 
00026 #include "portable.h"
00027 
00028 #include <stdio.h>
00029 #ifdef HAVE_LIMITS_H
00030 #include <limits.h>
00031 #endif
00032 
00033 #include <ac/socket.h>
00034 #include <ac/errno.h>
00035 #include <ac/string.h>
00036 #include <ac/time.h>
00037 #include <ac/unistd.h>
00038 
00039 #include "lutil.h"
00040 #include "slap.h"
00041 
00042 #ifdef LDAP_CONNECTIONLESS
00043 #include "../../libraries/liblber/lber-int.h"    /* ber_int_sb_read() */
00044 #endif
00045 
00046 #ifdef LDAP_SLAPI
00047 #include "slapi/slapi.h"
00048 #endif
00049 
00050 /* protected by connections_mutex */
00051 static ldap_pvt_thread_mutex_t connections_mutex;
00052 static Connection *connections = NULL;
00053 
00054 static ldap_pvt_thread_mutex_t conn_nextid_mutex;
00055 static unsigned long conn_nextid = SLAPD_SYNC_SYNCCONN_OFFSET;
00056 
00057 static const char conn_lost_str[] = "connection lost";
00058 
00059 const char *
00060 connection_state2str( int state )
00061 {
00062        switch( state ) {
00063        case SLAP_C_INVALID: return "!";
00064        case SLAP_C_INACTIVE:       return "|";
00065        case SLAP_C_CLOSING: return "C";
00066        case SLAP_C_ACTIVE:         return "";
00067        case SLAP_C_BINDING: return "B";
00068        case SLAP_C_CLIENT:         return "L";
00069        }
00070 
00071        return "?";
00072 }
00073 
00074 static Connection* connection_get( ber_socket_t s );
00075 
00076 typedef struct conn_readinfo {
00077        Operation *op;
00078        ldap_pvt_thread_start_t *func;
00079        void *arg;
00080        void *ctx;
00081        int nullop;
00082 } conn_readinfo;
00083 
00084 static int connection_input( Connection *c, conn_readinfo *cri );
00085 static void connection_close( Connection *c );
00086 
00087 static int connection_op_activate( Operation *op );
00088 static void connection_op_queue( Operation *op );
00089 static int connection_resched( Connection *conn );
00090 static void connection_abandon( Connection *conn );
00091 static void connection_destroy( Connection *c );
00092 
00093 static ldap_pvt_thread_start_t connection_operation;
00094 
00095 /*
00096  * Initialize connection management infrastructure.
00097  */
00098 int connections_init(void)
00099 {
00100        int i;
00101 
00102        assert( connections == NULL );
00103 
00104        if( connections != NULL) {
00105               Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n",
00106                      0, 0, 0 );
00107               return -1;
00108        }
00109 
00110        /* should check return of every call */
00111        ldap_pvt_thread_mutex_init( &connections_mutex );
00112        ldap_pvt_thread_mutex_init( &conn_nextid_mutex );
00113 
00114        connections = (Connection *) ch_calloc( dtblsize, sizeof(Connection) );
00115 
00116        if( connections == NULL ) {
00117               Debug( LDAP_DEBUG_ANY, "connections_init: "
00118                      "allocation (%d*%ld) of connection array failed\n",
00119                      dtblsize, (long) sizeof(Connection), 0 );
00120               return -1;
00121        }
00122 
00123        assert( connections[0].c_struct_state == SLAP_C_UNINITIALIZED );
00124        assert( connections[dtblsize-1].c_struct_state == SLAP_C_UNINITIALIZED );
00125 
00126        for (i=0; i<dtblsize; i++) connections[i].c_conn_idx = i;
00127 
00128        /*
00129         * per entry initialization of the Connection array initialization
00130         * will be done by connection_init()
00131         */ 
00132 
00133        return 0;
00134 }
00135 
00136 /*
00137  * Destroy connection management infrastructure.
00138  */
00139 
00140 int connections_destroy(void)
00141 {
00142        ber_socket_t i;
00143 
00144        /* should check return of every call */
00145 
00146        if( connections == NULL) {
00147               Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n",
00148                      0, 0, 0 );
00149               return -1;
00150        }
00151 
00152        for ( i = 0; i < dtblsize; i++ ) {
00153               if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) {
00154                      ber_sockbuf_free( connections[i].c_sb );
00155                      ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex );
00156                      ldap_pvt_thread_mutex_destroy( &connections[i].c_write1_mutex );
00157                      ldap_pvt_thread_mutex_destroy( &connections[i].c_write2_mutex );
00158                      ldap_pvt_thread_cond_destroy( &connections[i].c_write1_cv );
00159                      ldap_pvt_thread_cond_destroy( &connections[i].c_write2_cv );
00160 #ifdef LDAP_SLAPI
00161                      if ( slapi_plugins_used ) {
00162                             slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION,
00163                                    &connections[i] );
00164                      }
00165 #endif
00166               }
00167        }
00168 
00169        free( connections );
00170        connections = NULL;
00171 
00172        ldap_pvt_thread_mutex_destroy( &connections_mutex );
00173        ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex );
00174        return 0;
00175 }
00176 
00177 /*
00178  * shutdown all connections
00179  */
00180 int connections_shutdown(void)
00181 {
00182        ber_socket_t i;
00183 
00184        for ( i = 0; i < dtblsize; i++ ) {
00185               if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) {
00186                      ldap_pvt_thread_mutex_lock( &connections[i].c_mutex );
00187                      if( connections[i].c_struct_state == SLAP_C_USED ) {
00188 
00189                             /* give persistent clients a chance to cleanup */
00190                             if( connections[i].c_conn_state == SLAP_C_CLIENT ) {
00191                                    ldap_pvt_thread_pool_submit( &connection_pool,
00192                                    connections[i].c_clientfunc, connections[i].c_clientarg );
00193                             } else {
00194                                    /* c_mutex is locked */
00195                                    connection_closing( &connections[i], "slapd shutdown" );
00196                                    connection_close( &connections[i] );
00197                             }
00198                      }
00199                      ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex );
00200               }
00201        }
00202 
00203        return 0;
00204 }
00205 
00206 /*
00207  * Timeout idle connections.
00208  */
00209 int connections_timeout_idle(time_t now)
00210 {
00211        int i = 0, writers = 0;
00212        ber_socket_t connindex;
00213        Connection* c;
00214        time_t old;
00215 
00216        old = slapd_get_writetime();
00217 
00218        for( c = connection_first( &connindex );
00219               c != NULL;
00220               c = connection_next( c, &connindex ) )
00221        {
00222               /* Don't timeout a slow-running request or a persistent
00223                * outbound connection. But if it has a writewaiter, see
00224                * if the waiter has been there too long.
00225                */
00226               if(( c->c_n_ops_executing && !c->c_writewaiter)
00227                      || c->c_conn_state == SLAP_C_CLIENT ) {
00228                      continue;
00229               }
00230 
00231               if( global_idletimeout && 
00232                      difftime( c->c_activitytime+global_idletimeout, now) < 0 ) {
00233                      /* close it */
00234                      connection_closing( c, "idletimeout" );
00235                      connection_close( c );
00236                      i++;
00237                      continue;
00238               }
00239               if ( c->c_writewaiter && global_writetimeout ) {
00240                      writers = 1;
00241                      if( difftime( c->c_activitytime+global_writetimeout, now) < 0 ) {
00242                             /* close it */
00243                             connection_closing( c, "writetimeout" );
00244                             connection_close( c );
00245                             i++;
00246                             continue;
00247                      }
00248               }
00249        }
00250        connection_done( c );
00251        if ( old && !writers )
00252               slapd_clr_writetime( old );
00253 
00254        return i;
00255 }
00256 
00257 /* Drop all client connections */
00258 void connections_drop()
00259 {
00260        Connection* c;
00261        ber_socket_t connindex;
00262 
00263        for( c = connection_first( &connindex );
00264               c != NULL;
00265               c = connection_next( c, &connindex ) )
00266        {
00267               /* Don't close a slow-running request or a persistent
00268                * outbound connection.
00269                */
00270               if(( c->c_n_ops_executing && !c->c_writewaiter)
00271                      || c->c_conn_state == SLAP_C_CLIENT ) {
00272                      continue;
00273               }
00274               connection_closing( c, "dropping" );
00275               connection_close( c );
00276        }
00277        connection_done( c );
00278 }
00279 
00280 static Connection* connection_get( ber_socket_t s )
00281 {
00282        Connection *c;
00283 
00284        Debug( LDAP_DEBUG_ARGS,
00285               "connection_get(%ld)\n",
00286               (long) s, 0, 0 );
00287 
00288        assert( connections != NULL );
00289 
00290        if(s == AC_SOCKET_INVALID) return NULL;
00291 
00292        assert( s < dtblsize );
00293        c = &connections[s];
00294 
00295        if( c != NULL ) {
00296               ldap_pvt_thread_mutex_lock( &c->c_mutex );
00297 
00298               assert( c->c_struct_state != SLAP_C_UNINITIALIZED );
00299 
00300               if( c->c_struct_state != SLAP_C_USED ) {
00301                      /* connection must have been closed due to resched */
00302 
00303                      Debug( LDAP_DEBUG_CONNS,
00304                             "connection_get(%d): connection not used\n",
00305                             s, 0, 0 );
00306                      assert( c->c_conn_state == SLAP_C_INVALID );
00307                      assert( c->c_sd == AC_SOCKET_INVALID );
00308 
00309                      ldap_pvt_thread_mutex_unlock( &c->c_mutex );
00310                      return NULL;
00311               }
00312 
00313               Debug( LDAP_DEBUG_TRACE,
00314                      "connection_get(%d): got connid=%lu\n",
00315                      s, c->c_connid, 0 );
00316 
00317               c->c_n_get++;
00318 
00319               assert( c->c_struct_state == SLAP_C_USED );
00320               assert( c->c_conn_state != SLAP_C_INVALID );
00321               assert( c->c_sd != AC_SOCKET_INVALID );
00322 
00323 #ifndef SLAPD_MONITOR
00324               if ( global_idletimeout > 0 )
00325 #endif /* ! SLAPD_MONITOR */
00326               {
00327                      c->c_activitytime = slap_get_time();
00328               }
00329        }
00330 
00331        return c;
00332 }
00333 
00334 static void connection_return( Connection *c )
00335 {
00336        ldap_pvt_thread_mutex_unlock( &c->c_mutex );
00337 }
00338 
00339 Connection * connection_init(
00340        ber_socket_t s,
00341        Listener *listener,
00342        const char* dnsname,
00343        const char* peername,
00344        int flags,
00345        slap_ssf_t ssf,
00346        struct berval *authid
00347        LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv))
00348 {
00349        unsigned long id;
00350        Connection *c;
00351        int doinit = 0;
00352        ber_socket_t sfd = SLAP_FD2SOCK(s);
00353 
00354        assert( connections != NULL );
00355 
00356        assert( listener != NULL );
00357        assert( dnsname != NULL );
00358        assert( peername != NULL );
00359 
00360 #ifndef HAVE_TLS
00361        assert( !( flags & CONN_IS_TLS ));
00362 #endif
00363 
00364        if( s == AC_SOCKET_INVALID ) {
00365               Debug( LDAP_DEBUG_ANY,
00366                      "connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 );
00367               return NULL;
00368        }
00369 
00370        assert( s >= 0 );
00371        assert( s < dtblsize );
00372        c = &connections[s];
00373        if( c->c_struct_state == SLAP_C_UNINITIALIZED ) {
00374               doinit = 1;
00375        } else {
00376               assert( c->c_struct_state == SLAP_C_UNUSED );
00377        }
00378 
00379        if( doinit ) {
00380               c->c_send_ldap_result = slap_send_ldap_result;
00381               c->c_send_search_entry = slap_send_search_entry;
00382               c->c_send_search_reference = slap_send_search_reference;
00383               c->c_send_ldap_extended = slap_send_ldap_extended;
00384               c->c_send_ldap_intermediate = slap_send_ldap_intermediate;
00385 
00386               BER_BVZERO( &c->c_authmech );
00387               BER_BVZERO( &c->c_dn );
00388               BER_BVZERO( &c->c_ndn );
00389 
00390               c->c_listener = NULL;
00391               BER_BVZERO( &c->c_peer_domain );
00392               BER_BVZERO( &c->c_peer_name );
00393 
00394               LDAP_STAILQ_INIT(&c->c_ops);
00395               LDAP_STAILQ_INIT(&c->c_pending_ops);
00396 
00397 #ifdef LDAP_X_TXN
00398               c->c_txn = CONN_TXN_INACTIVE;
00399               c->c_txn_backend = NULL;
00400               LDAP_STAILQ_INIT(&c->c_txn_ops);
00401 #endif
00402 
00403               BER_BVZERO( &c->c_sasl_bind_mech );
00404               c->c_sasl_done = 0;
00405               c->c_sasl_authctx = NULL;
00406               c->c_sasl_sockctx = NULL;
00407               c->c_sasl_extra = NULL;
00408               c->c_sasl_bindop = NULL;
00409 
00410               c->c_sb = ber_sockbuf_alloc( );
00411 
00412               {
00413                      ber_len_t max = sockbuf_max_incoming;
00414                      ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
00415               }
00416 
00417               c->c_currentber = NULL;
00418 
00419               /* should check status of thread calls */
00420               ldap_pvt_thread_mutex_init( &c->c_mutex );
00421               ldap_pvt_thread_mutex_init( &c->c_write1_mutex );
00422               ldap_pvt_thread_mutex_init( &c->c_write2_mutex );
00423               ldap_pvt_thread_cond_init( &c->c_write1_cv );
00424               ldap_pvt_thread_cond_init( &c->c_write2_cv );
00425 
00426 #ifdef LDAP_SLAPI
00427               if ( slapi_plugins_used ) {
00428                      slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, c );
00429               }
00430 #endif
00431        }
00432 
00433        ldap_pvt_thread_mutex_lock( &c->c_mutex );
00434 
00435        assert( BER_BVISNULL( &c->c_authmech ) );
00436        assert( BER_BVISNULL( &c->c_dn ) );
00437        assert( BER_BVISNULL( &c->c_ndn ) );
00438        assert( c->c_listener == NULL );
00439        assert( BER_BVISNULL( &c->c_peer_domain ) );
00440        assert( BER_BVISNULL( &c->c_peer_name ) );
00441        assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
00442        assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) );
00443 #ifdef LDAP_X_TXN
00444        assert( c->c_txn == CONN_TXN_INACTIVE );
00445        assert( c->c_txn_backend == NULL );
00446        assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) );
00447 #endif
00448        assert( BER_BVISNULL( &c->c_sasl_bind_mech ) );
00449        assert( c->c_sasl_done == 0 );
00450        assert( c->c_sasl_authctx == NULL );
00451        assert( c->c_sasl_sockctx == NULL );
00452        assert( c->c_sasl_extra == NULL );
00453        assert( c->c_sasl_bindop == NULL );
00454        assert( c->c_currentber == NULL );
00455        assert( c->c_writewaiter == 0);
00456        assert( c->c_writers == 0);
00457 
00458        c->c_listener = listener;
00459        c->c_sd = s;
00460 
00461        if ( flags & CONN_IS_CLIENT ) {
00462               c->c_connid = 0;
00463               ldap_pvt_thread_mutex_lock( &connections_mutex );
00464               c->c_conn_state = SLAP_C_CLIENT;
00465               c->c_struct_state = SLAP_C_USED;
00466               ldap_pvt_thread_mutex_unlock( &connections_mutex );
00467               c->c_close_reason = "?";                  /* should never be needed */
00468               ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &sfd );
00469               ldap_pvt_thread_mutex_unlock( &c->c_mutex );
00470 
00471               return c;
00472        }
00473 
00474        ber_str2bv( dnsname, 0, 1, &c->c_peer_domain );
00475        ber_str2bv( peername, 0, 1, &c->c_peer_name );
00476 
00477        c->c_n_ops_received = 0;
00478        c->c_n_ops_executing = 0;
00479        c->c_n_ops_pending = 0;
00480        c->c_n_ops_completed = 0;
00481 
00482        c->c_n_get = 0;
00483        c->c_n_read = 0;
00484        c->c_n_write = 0;
00485 
00486        /* set to zero until bind, implies LDAP_VERSION3 */
00487        c->c_protocol = 0;
00488 
00489 #ifndef SLAPD_MONITOR
00490        if ( global_idletimeout > 0 )
00491 #endif /* ! SLAPD_MONITOR */
00492        {
00493               c->c_activitytime = c->c_starttime = slap_get_time();
00494        }
00495 
00496 #ifdef LDAP_CONNECTIONLESS
00497        c->c_is_udp = 0;
00498        if( flags & CONN_IS_UDP ) {
00499               c->c_is_udp = 1;
00500 #ifdef LDAP_DEBUG
00501               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
00502                      LBER_SBIOD_LEVEL_PROVIDER, (void*)"udp_" );
00503 #endif
00504               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_udp,
00505                      LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd );
00506               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead,
00507                      LBER_SBIOD_LEVEL_PROVIDER, NULL );
00508        } else
00509 #endif /* LDAP_CONNECTIONLESS */
00510 #ifdef LDAP_PF_LOCAL
00511        if ( flags & CONN_IS_IPC ) {
00512 #ifdef LDAP_DEBUG
00513               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
00514                      LBER_SBIOD_LEVEL_PROVIDER, (void*)"ipc_" );
00515 #endif
00516               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_fd,
00517                      LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd );
00518 #ifdef LDAP_PF_LOCAL_SENDMSG
00519               if ( !BER_BVISEMPTY( peerbv ))
00520                      ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_UNGET_BUF, peerbv );
00521 #endif
00522        } else
00523 #endif /* LDAP_PF_LOCAL */
00524        {
00525 #ifdef LDAP_DEBUG
00526               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
00527                      LBER_SBIOD_LEVEL_PROVIDER, (void*)"tcp_" );
00528 #endif
00529               ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_tcp,
00530                      LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd );
00531        }
00532 
00533 #ifdef LDAP_DEBUG
00534        ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug,
00535               INT_MAX, (void*)"ldap_" );
00536 #endif
00537 
00538        if( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_NONBLOCK,
00539               c /* non-NULL */ ) < 0 )
00540        {
00541               Debug( LDAP_DEBUG_ANY,
00542                      "connection_init(%d, %s): set nonblocking failed\n",
00543                      s, c->c_peer_name.bv_val, 0 );
00544        }
00545 
00546        ldap_pvt_thread_mutex_lock( &conn_nextid_mutex );
00547        id = c->c_connid = conn_nextid++;
00548        ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex );
00549 
00550        ldap_pvt_thread_mutex_lock( &connections_mutex );
00551        c->c_conn_state = SLAP_C_INACTIVE;
00552        c->c_struct_state = SLAP_C_USED;
00553        ldap_pvt_thread_mutex_unlock( &connections_mutex );
00554        c->c_close_reason = "?";                  /* should never be needed */
00555 
00556        c->c_ssf = c->c_transport_ssf = ssf;
00557        c->c_tls_ssf = 0;
00558 
00559 #ifdef HAVE_TLS
00560        if ( flags & CONN_IS_TLS ) {
00561               c->c_is_tls = 1;
00562               c->c_needs_tls_accept = 1;
00563        } else {
00564               c->c_is_tls = 0;
00565               c->c_needs_tls_accept = 0;
00566        }
00567 #endif
00568 
00569        slap_sasl_open( c, 0 );
00570        slap_sasl_external( c, ssf, authid );
00571 
00572        slapd_add_internal( s, 1 );
00573 
00574        backend_connection_init(c);
00575        ldap_pvt_thread_mutex_unlock( &c->c_mutex );
00576 
00577        return c;
00578 }
00579 
00580 void connection2anonymous( Connection *c )
00581 {
00582        assert( connections != NULL );
00583        assert( c != NULL );
00584 
00585        {
00586               ber_len_t max = sockbuf_max_incoming;
00587               ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
00588        }
00589 
00590        if ( !BER_BVISNULL( &c->c_authmech ) ) {
00591               ch_free(c->c_authmech.bv_val);
00592        }
00593        BER_BVZERO( &c->c_authmech );
00594 
00595        if ( !BER_BVISNULL( &c->c_dn ) ) {
00596               ch_free(c->c_dn.bv_val);
00597        }
00598        BER_BVZERO( &c->c_dn );
00599 
00600        if ( !BER_BVISNULL( &c->c_ndn ) ) {
00601               ch_free(c->c_ndn.bv_val);
00602        }
00603        BER_BVZERO( &c->c_ndn );
00604 
00605        if ( !BER_BVISNULL( &c->c_sasl_authz_dn ) ) {
00606               ber_memfree_x( c->c_sasl_authz_dn.bv_val, NULL );
00607        }
00608        BER_BVZERO( &c->c_sasl_authz_dn );
00609 
00610        c->c_authz_backend = NULL;
00611 }
00612 
00613 static void
00614 connection_destroy( Connection *c )
00615 {
00616        unsigned long connid;
00617        const char           *close_reason;
00618        Sockbuf                     *sb;
00619        ber_socket_t  sd;
00620 
00621        assert( connections != NULL );
00622        assert( c != NULL );
00623        assert( c->c_struct_state != SLAP_C_UNUSED );
00624        assert( c->c_conn_state != SLAP_C_INVALID );
00625        assert( LDAP_STAILQ_EMPTY(&c->c_ops) );
00626        assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) );
00627 #ifdef LDAP_X_TXN
00628        assert( c->c_txn == CONN_TXN_INACTIVE );
00629        assert( c->c_txn_backend == NULL );
00630        assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) );
00631 #endif
00632        assert( c->c_writewaiter == 0);
00633        assert( c->c_writers == 0);
00634 
00635        /* only for stats (print -1 as "%lu" may give unexpected results ;) */
00636        connid = c->c_connid;
00637        close_reason = c->c_close_reason;
00638 
00639        ldap_pvt_thread_mutex_lock( &connections_mutex );
00640        c->c_struct_state = SLAP_C_PENDING;
00641        ldap_pvt_thread_mutex_unlock( &connections_mutex );
00642 
00643        backend_connection_destroy(c);
00644 
00645        c->c_protocol = 0;
00646        c->c_connid = -1;
00647 
00648        c->c_activitytime = c->c_starttime = 0;
00649 
00650        connection2anonymous( c );
00651        c->c_listener = NULL;
00652 
00653        if(c->c_peer_domain.bv_val != NULL) {
00654               free(c->c_peer_domain.bv_val);
00655        }
00656        BER_BVZERO( &c->c_peer_domain );
00657        if(c->c_peer_name.bv_val != NULL) {
00658               free(c->c_peer_name.bv_val);
00659        }
00660        BER_BVZERO( &c->c_peer_name );
00661 
00662        c->c_sasl_bind_in_progress = 0;
00663        if(c->c_sasl_bind_mech.bv_val != NULL) {
00664               free(c->c_sasl_bind_mech.bv_val);
00665        }
00666        BER_BVZERO( &c->c_sasl_bind_mech );
00667 
00668        slap_sasl_close( c );
00669 
00670        if ( c->c_currentber != NULL ) {
00671               ber_free( c->c_currentber, 1 );
00672               c->c_currentber = NULL;
00673        }
00674 
00675 
00676 #ifdef LDAP_SLAPI
00677        /* call destructors, then constructors; avoids unnecessary allocation */
00678        if ( slapi_plugins_used ) {
00679               slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c );
00680        }
00681 #endif
00682 
00683        sd = c->c_sd;
00684        c->c_sd = AC_SOCKET_INVALID;
00685        c->c_conn_state = SLAP_C_INVALID;
00686        c->c_struct_state = SLAP_C_UNUSED;
00687        c->c_close_reason = "?";                  /* should never be needed */
00688 
00689        sb = c->c_sb;
00690        c->c_sb = ber_sockbuf_alloc( );
00691        {
00692               ber_len_t max = sockbuf_max_incoming;
00693               ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
00694        }
00695 
00696        /* c must be fully reset by this point; when we call slapd_remove
00697         * it may get immediately reused by a new connection.
00698         */
00699        if ( sd != AC_SOCKET_INVALID ) {
00700               slapd_remove( sd, sb, 1, 0, 0 );
00701 
00702               if ( close_reason == NULL ) {
00703                      Statslog( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed\n",
00704                             connid, (long) sd, 0, 0, 0 );
00705               } else {
00706                      Statslog( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed (%s)\n",
00707                             connid, (long) sd, close_reason, 0, 0 );
00708               }
00709        }
00710 }
00711 
00712 int connection_valid( Connection *c )
00713 {
00714        /* c_mutex must be locked by caller */
00715 
00716        assert( c != NULL );
00717 
00718        return c->c_struct_state == SLAP_C_USED &&
00719               c->c_conn_state >= SLAP_C_ACTIVE &&
00720               c->c_conn_state <= SLAP_C_CLIENT;
00721 }
00722 
00723 static void connection_abandon( Connection *c )
00724 {
00725        /* c_mutex must be locked by caller */
00726 
00727        Operation *o, *next, op = {0};
00728        Opheader ohdr = {0};
00729 
00730        op.o_hdr = &ohdr;
00731        op.o_conn = c;
00732        op.o_connid = c->c_connid;
00733        op.o_tag = LDAP_REQ_ABANDON;
00734 
00735        for ( o = LDAP_STAILQ_FIRST( &c->c_ops ); o; o=next ) {
00736               SlapReply rs = {REP_RESULT};
00737 
00738               next = LDAP_STAILQ_NEXT( o, o_next );
00739               op.orn_msgid = o->o_msgid;
00740               o->o_abandon = 1;
00741               op.o_bd = frontendDB;
00742               frontendDB->be_abandon( &op, &rs );
00743        }
00744 
00745 #ifdef LDAP_X_TXN
00746        /* remove operations in pending transaction */
00747        while ( (o = LDAP_STAILQ_FIRST( &c->c_txn_ops )) != NULL) {
00748               LDAP_STAILQ_REMOVE_HEAD( &c->c_txn_ops, o_next );
00749               LDAP_STAILQ_NEXT(o, o_next) = NULL;
00750               slap_op_free( o, NULL );
00751        }
00752 
00753        /* clear transaction */
00754        c->c_txn_backend = NULL;
00755        c->c_txn = CONN_TXN_INACTIVE;
00756 #endif
00757 
00758        /* remove pending operations */
00759        while ( (o = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
00760               LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
00761               LDAP_STAILQ_NEXT(o, o_next) = NULL;
00762               slap_op_free( o, NULL );
00763        }
00764 }
00765 
00766 static void
00767 connection_wake_writers( Connection *c )
00768 {
00769        /* wake write blocked operations */
00770        ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
00771        if ( c->c_writers > 0 ) {
00772               c->c_writers = -c->c_writers;
00773               ldap_pvt_thread_cond_broadcast( &c->c_write1_cv );
00774               ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
00775               if ( c->c_writewaiter ) {
00776                      ldap_pvt_thread_mutex_lock( &c->c_write2_mutex );
00777                      ldap_pvt_thread_cond_signal( &c->c_write2_cv );
00778                      slapd_clr_write( c->c_sd, 1 );
00779                      ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex );
00780               }
00781               ldap_pvt_thread_mutex_lock( &c->c_write1_mutex );
00782               while ( c->c_writers ) {
00783                      ldap_pvt_thread_cond_wait( &c->c_write1_cv, &c->c_write1_mutex );
00784               }
00785               ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
00786        } else {
00787               ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex );
00788               slapd_clr_write( c->c_sd, 1 );
00789        }
00790 }
00791 
00792 void connection_closing( Connection *c, const char *why )
00793 {
00794        assert( connections != NULL );
00795        assert( c != NULL );
00796 
00797        if ( c->c_struct_state != SLAP_C_USED ) return;
00798 
00799        assert( c->c_conn_state != SLAP_C_INVALID );
00800 
00801        /* c_mutex must be locked by caller */
00802 
00803        if( c->c_conn_state != SLAP_C_CLOSING ) {
00804               Debug( LDAP_DEBUG_CONNS,
00805                      "connection_closing: readying conn=%lu sd=%d for close\n",
00806                      c->c_connid, c->c_sd, 0 );
00807               /* update state to closing */
00808               c->c_conn_state = SLAP_C_CLOSING;
00809               c->c_close_reason = why;
00810 
00811               /* don't listen on this port anymore */
00812               slapd_clr_read( c->c_sd, 0 );
00813 
00814               /* abandon active operations */
00815               connection_abandon( c );
00816 
00817               /* wake write blocked operations */
00818               connection_wake_writers( c );
00819 
00820        } else if( why == NULL && c->c_close_reason == conn_lost_str ) {
00821               /* Client closed connection after doing Unbind. */
00822               c->c_close_reason = NULL;
00823        }
00824 }
00825 
00826 static void
00827 connection_close( Connection *c )
00828 {
00829        assert( connections != NULL );
00830        assert( c != NULL );
00831 
00832        if ( c->c_struct_state != SLAP_C_USED ) return;
00833 
00834        assert( c->c_conn_state == SLAP_C_CLOSING );
00835 
00836        /* NOTE: c_mutex should be locked by caller */
00837 
00838        if ( !LDAP_STAILQ_EMPTY(&c->c_ops) ||
00839               !LDAP_STAILQ_EMPTY(&c->c_pending_ops) )
00840        {
00841               Debug( LDAP_DEBUG_CONNS,
00842                      "connection_close: deferring conn=%lu sd=%d\n",
00843                      c->c_connid, c->c_sd, 0 );
00844               return;
00845        }
00846 
00847        Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%lu sd=%d\n",
00848               c->c_connid, c->c_sd, 0 );
00849 
00850        connection_destroy( c );
00851 }
00852 
00853 unsigned long connections_nextid(void)
00854 {
00855        unsigned long id;
00856        assert( connections != NULL );
00857 
00858        ldap_pvt_thread_mutex_lock( &conn_nextid_mutex );
00859 
00860        id = conn_nextid;
00861 
00862        ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex );
00863 
00864        return id;
00865 }
00866 
00867 /*
00868  * Loop through the connections:
00869  *
00870  *     for (c = connection_first(&i); c; c = connection_next(c, &i)) ...;
00871  *     connection_done(c);
00872  *
00873  * 'i' is the cursor, initialized by connection_first().
00874  * 'c_mutex' is locked in the returned connection.  The functions must
00875  * be passed the previous return value so they can unlock it again.
00876  */
00877 
00878 Connection* connection_first( ber_socket_t *index )
00879 {
00880        assert( connections != NULL );
00881        assert( index != NULL );
00882 
00883        ldap_pvt_thread_mutex_lock( &connections_mutex );
00884        for( *index = 0; *index < dtblsize; (*index)++) {
00885               if( connections[*index].c_struct_state != SLAP_C_UNINITIALIZED ) {
00886                      break;
00887               }
00888        }
00889        ldap_pvt_thread_mutex_unlock( &connections_mutex );
00890 
00891        return connection_next(NULL, index);
00892 }
00893 
00894 /* Next connection in loop, see connection_first() */
00895 Connection* connection_next( Connection *c, ber_socket_t *index )
00896 {
00897        assert( connections != NULL );
00898        assert( index != NULL );
00899        assert( *index <= dtblsize );
00900 
00901        if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
00902 
00903        c = NULL;
00904 
00905        ldap_pvt_thread_mutex_lock( &connections_mutex );
00906        for(; *index < dtblsize; (*index)++) {
00907               int c_struct;
00908               if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) {
00909                      /* FIXME: accessing c_conn_state without locking c_mutex */
00910                      assert( connections[*index].c_conn_state == SLAP_C_INVALID );
00911                      continue;
00912               }
00913 
00914               if( connections[*index].c_struct_state == SLAP_C_USED ) {
00915                      c = &connections[(*index)++];
00916                      if ( ldap_pvt_thread_mutex_trylock( &c->c_mutex )) {
00917                             /* avoid deadlock */
00918                             ldap_pvt_thread_mutex_unlock( &connections_mutex );
00919                             ldap_pvt_thread_mutex_lock( &c->c_mutex );
00920                             ldap_pvt_thread_mutex_lock( &connections_mutex );
00921                             if ( c->c_struct_state != SLAP_C_USED ) {
00922                                    ldap_pvt_thread_mutex_unlock( &c->c_mutex );
00923                                    c = NULL;
00924                                    continue;
00925                             }
00926                      }
00927                      assert( c->c_conn_state != SLAP_C_INVALID );
00928                      break;
00929               }
00930 
00931               c_struct = connections[*index].c_struct_state;
00932               if ( c_struct == SLAP_C_PENDING )
00933                      continue;
00934               assert( c_struct == SLAP_C_UNUSED );
00935               /* FIXME: accessing c_conn_state without locking c_mutex */
00936               assert( connections[*index].c_conn_state == SLAP_C_INVALID );
00937        }
00938 
00939        ldap_pvt_thread_mutex_unlock( &connections_mutex );
00940        return c;
00941 }
00942 
00943 /* End connection loop, see connection_first() */
00944 void connection_done( Connection *c )
00945 {
00946        assert( connections != NULL );
00947 
00948        if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex );
00949 }
00950 
00951 /*
00952  * connection_activity - handle the request operation op on connection
00953  * conn.  This routine figures out what kind of operation it is and
00954  * calls the appropriate stub to handle it.
00955  */
00956 
00957 #ifdef SLAPD_MONITOR
00958 /* FIXME: returns 0 in case of failure */
00959 #define INCR_OP_INITIATED(index) \
00960        do { \
00961               ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
00962               ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated_[(index)], 1); \
00963               ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
00964        } while (0)
00965 #define INCR_OP_COMPLETED(index) \
00966        do { \
00967               ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
00968               ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed, 1); \
00969               ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed_[(index)], 1); \
00970               ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
00971        } while (0)
00972 #else /* !SLAPD_MONITOR */
00973 #define INCR_OP_INITIATED(index) do { } while (0)
00974 #define INCR_OP_COMPLETED(index) \
00975        do { \
00976               ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \
00977               ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed, 1); \
00978               ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \
00979        } while (0)
00980 #endif /* !SLAPD_MONITOR */
00981 
00982 /*
00983  * NOTE: keep in sync with enum in slapd.h
00984  */
00985 static BI_op_func *opfun[] = {
00986        do_bind,
00987        do_unbind,
00988        do_search,
00989        do_compare,
00990        do_modify,
00991        do_modrdn,
00992        do_add,
00993        do_delete,
00994        do_abandon,
00995        do_extended,
00996        NULL
00997 };
00998 
00999 /* Counters are per-thread, not per-connection.
01000  */
01001 static void
01002 conn_counter_destroy( void *key, void *data )
01003 {
01004        slap_counters_t **prev, *sc;
01005 
01006        ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
01007        for ( prev = &slap_counters.sc_next, sc = slap_counters.sc_next; sc;
01008               prev = &sc->sc_next, sc = sc->sc_next ) {
01009               if ( sc == data ) {
01010                      int i;
01011 
01012                      *prev = sc->sc_next;
01013                      /* Copy data to main counter */
01014                      ldap_pvt_mp_add( slap_counters.sc_bytes, sc->sc_bytes );
01015                      ldap_pvt_mp_add( slap_counters.sc_pdu, sc->sc_pdu );
01016                      ldap_pvt_mp_add( slap_counters.sc_entries, sc->sc_entries );
01017                      ldap_pvt_mp_add( slap_counters.sc_refs, sc->sc_refs );
01018                      ldap_pvt_mp_add( slap_counters.sc_ops_initiated, sc->sc_ops_initiated );
01019                      ldap_pvt_mp_add( slap_counters.sc_ops_completed, sc->sc_ops_completed );
01020 #ifdef SLAPD_MONITOR
01021                      for ( i = 0; i < SLAP_OP_LAST; i++ ) {
01022                             ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_initiated_[ i ] );
01023                             ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_completed_[ i ] );
01024                      }
01025 #endif /* SLAPD_MONITOR */
01026                      slap_counters_destroy( sc );
01027                      ber_memfree_x( data, NULL );
01028                      break;
01029               }
01030        }
01031        ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
01032 }
01033 
01034 static void
01035 conn_counter_init( Operation *op, void *ctx )
01036 {
01037        slap_counters_t *sc;
01038        void *vsc = NULL;
01039 
01040        if ( ldap_pvt_thread_pool_getkey(
01041                      ctx, (void *)conn_counter_init, &vsc, NULL ) || !vsc ) {
01042               vsc = ch_malloc( sizeof( slap_counters_t ));
01043               sc = vsc;
01044               slap_counters_init( sc );
01045               ldap_pvt_thread_pool_setkey( ctx, (void*)conn_counter_init, vsc,
01046                      conn_counter_destroy, NULL, NULL );
01047 
01048               ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex );
01049               sc->sc_next = slap_counters.sc_next;
01050               slap_counters.sc_next = sc;
01051               ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex );
01052        }
01053        op->o_counters = vsc;
01054 }
01055 
01056 static void *
01057 connection_operation( void *ctx, void *arg_v )
01058 {
01059        int rc = LDAP_OTHER, cancel;
01060        Operation *op = arg_v;
01061        SlapReply rs = {REP_RESULT};
01062        ber_tag_t tag = op->o_tag;
01063        slap_op_t opidx = SLAP_OP_LAST;
01064        Connection *conn = op->o_conn;
01065        void *memctx = NULL;
01066        void *memctx_null = NULL;
01067        ber_len_t memsiz;
01068 
01069        conn_counter_init( op, ctx );
01070        ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
01071        /* FIXME: returns 0 in case of failure */
01072        ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated, 1);
01073        ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
01074 
01075        op->o_threadctx = ctx;
01076        op->o_tid = ldap_pvt_thread_pool_tid( ctx );
01077 
01078        switch ( tag ) {
01079        case LDAP_REQ_BIND:
01080        case LDAP_REQ_UNBIND:
01081        case LDAP_REQ_ADD:
01082        case LDAP_REQ_DELETE:
01083        case LDAP_REQ_MODDN:
01084        case LDAP_REQ_MODIFY:
01085        case LDAP_REQ_COMPARE:
01086        case LDAP_REQ_SEARCH:
01087        case LDAP_REQ_ABANDON:
01088        case LDAP_REQ_EXTENDED:
01089               break;
01090        default:
01091               Debug( LDAP_DEBUG_ANY, "connection_operation: "
01092                      "conn %lu unknown LDAP request 0x%lx\n",
01093                      conn->c_connid, tag, 0 );
01094               op->o_tag = LBER_ERROR;
01095               rs.sr_err = LDAP_PROTOCOL_ERROR;
01096               rs.sr_text = "unknown LDAP request";
01097               send_ldap_disconnect( op, &rs );
01098               rc = SLAPD_DISCONNECT;
01099               goto operations_error;
01100        }
01101 
01102        if( conn->c_sasl_bind_in_progress && tag != LDAP_REQ_BIND ) {
01103               Debug( LDAP_DEBUG_ANY, "connection_operation: "
01104                      "error: SASL bind in progress (tag=%ld).\n",
01105                      (long) tag, 0, 0 );
01106               send_ldap_error( op, &rs, LDAP_OPERATIONS_ERROR,
01107                      "SASL bind in progress" );
01108               rc = LDAP_OPERATIONS_ERROR;
01109               goto operations_error;
01110        }
01111 
01112 #ifdef LDAP_X_TXN
01113        if (( conn->c_txn == CONN_TXN_SPECIFY ) && (
01114               ( tag == LDAP_REQ_ADD ) ||
01115               ( tag == LDAP_REQ_DELETE ) ||
01116               ( tag == LDAP_REQ_MODIFY ) ||
01117               ( tag == LDAP_REQ_MODRDN )))
01118        {
01119               /* Disable SLAB allocator for all update operations
01120                      issued inside of a transaction */
01121               op->o_tmpmemctx = NULL;
01122               op->o_tmpmfuncs = &ch_mfuncs;
01123        } else
01124 #endif
01125        {
01126        /* We can use Thread-Local storage for most mallocs. We can
01127         * also use TL for ber parsing, but not on Add or Modify.
01128         */
01129 #if 0
01130        memsiz = ber_len( op->o_ber ) * 64;
01131        if ( SLAP_SLAB_SIZE > memsiz ) memsiz = SLAP_SLAB_SIZE;
01132 #endif
01133        memsiz = SLAP_SLAB_SIZE;
01134 
01135        memctx = slap_sl_mem_create( memsiz, SLAP_SLAB_STACK, ctx, 1 );
01136        op->o_tmpmemctx = memctx;
01137        op->o_tmpmfuncs = &slap_sl_mfuncs;
01138        if ( tag != LDAP_REQ_ADD && tag != LDAP_REQ_MODIFY ) {
01139               /* Note - the ber and its buffer are already allocated from
01140                * regular memory; this only affects subsequent mallocs that
01141                * ber_scanf may invoke.
01142                */
01143               ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx );
01144        }
01145        }
01146 
01147        opidx = slap_req2op( tag );
01148        assert( opidx != SLAP_OP_LAST );
01149        INCR_OP_INITIATED( opidx );
01150        rc = (*(opfun[opidx]))( op, &rs );
01151 
01152 operations_error:
01153        if ( rc == SLAPD_DISCONNECT ) {
01154               tag = LBER_ERROR;
01155 
01156        } else if ( opidx != SLAP_OP_LAST ) {
01157               /* increment completed operations count 
01158                * only if operation was initiated
01159                * and rc != SLAPD_DISCONNECT */
01160               INCR_OP_COMPLETED( opidx );
01161        }
01162 
01163        ldap_pvt_thread_mutex_lock( &conn->c_mutex );
01164 
01165        if ( opidx == SLAP_OP_BIND && conn->c_conn_state == SLAP_C_BINDING )
01166               conn->c_conn_state = SLAP_C_ACTIVE;
01167 
01168        cancel = op->o_cancel;
01169        if ( cancel != SLAP_CANCEL_NONE && cancel != SLAP_CANCEL_DONE ) {
01170               if ( cancel == SLAP_CANCEL_REQ ) {
01171                      op->o_cancel = rc == SLAPD_ABANDON
01172                             ? SLAP_CANCEL_ACK : LDAP_TOO_LATE;
01173               }
01174 
01175               do {
01176                      /* Fake a cond_wait with thread_yield, then
01177                       * verify the result properly mutex-protected.
01178                       */
01179                      ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
01180                      do {
01181                             ldap_pvt_thread_yield();
01182                      } while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE
01183                                    && cancel != SLAP_CANCEL_DONE );
01184                      ldap_pvt_thread_mutex_lock( &conn->c_mutex );
01185               } while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE
01186                             && cancel != SLAP_CANCEL_DONE );
01187        }
01188 
01189        ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null );
01190 
01191        LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next);
01192        LDAP_STAILQ_NEXT(op, o_next) = NULL;
01193        conn->c_n_ops_executing--;
01194        conn->c_n_ops_completed++;
01195 
01196        switch( tag ) {
01197        case LBER_ERROR:
01198        case LDAP_REQ_UNBIND:
01199               /* c_mutex is locked */
01200               connection_closing( conn,
01201                      tag == LDAP_REQ_UNBIND ? NULL : "operations error" );
01202               break;
01203        }
01204 
01205        connection_resched( conn );
01206        ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
01207        slap_op_free( op, ctx );
01208        return NULL;
01209 }
01210 
01211 static const Listener dummy_list = { BER_BVC(""), BER_BVC("") };
01212 
01213 Connection *connection_client_setup(
01214        ber_socket_t s,
01215        ldap_pvt_thread_start_t *func,
01216        void *arg )
01217 {
01218        Connection *c;
01219        ber_socket_t sfd = SLAP_SOCKNEW( s );
01220 
01221        c = connection_init( sfd, (Listener *)&dummy_list, "", "",
01222               CONN_IS_CLIENT, 0, NULL
01223               LDAP_PF_LOCAL_SENDMSG_ARG(NULL));
01224        if ( c ) {
01225               c->c_clientfunc = func;
01226               c->c_clientarg = arg;
01227 
01228               slapd_add_internal( sfd, 0 );
01229        }
01230        return c;
01231 }
01232 
01233 void connection_client_enable(
01234        Connection *c )
01235 {
01236        slapd_set_read( c->c_sd, 1 );
01237 }
01238 
01239 void connection_client_stop(
01240        Connection *c )
01241 {
01242        Sockbuf *sb;
01243        ber_socket_t s = c->c_sd;
01244 
01245        /* get (locked) connection */
01246        c = connection_get( s );
01247 
01248        assert( c->c_conn_state == SLAP_C_CLIENT );
01249 
01250        c->c_listener = NULL;
01251        c->c_conn_state = SLAP_C_INVALID;
01252        c->c_struct_state = SLAP_C_UNUSED;
01253        c->c_sd = AC_SOCKET_INVALID;
01254        c->c_close_reason = "?";                  /* should never be needed */
01255        sb = c->c_sb;
01256        c->c_sb = ber_sockbuf_alloc( );
01257        {
01258               ber_len_t max = sockbuf_max_incoming;
01259               ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max );
01260        }
01261        slapd_remove( s, sb, 0, 1, 0 );
01262 
01263        connection_return( c );
01264 }
01265 
01266 static int connection_read( ber_socket_t s, conn_readinfo *cri );
01267 
01268 static void* connection_read_thread( void* ctx, void* argv )
01269 {
01270        int rc ;
01271        conn_readinfo cri = { NULL, NULL, NULL, NULL, 0 };
01272        ber_socket_t s = (long)argv;
01273 
01274        /*
01275         * read incoming LDAP requests. If there is more than one,
01276         * the first one is returned with new_op
01277         */
01278        cri.ctx = ctx;
01279        if( ( rc = connection_read( s, &cri ) ) < 0 ) {
01280               Debug( LDAP_DEBUG_CONNS, "connection_read(%d) error\n", s, 0, 0 );
01281               return (void*)(long)rc;
01282        }
01283 
01284        /* execute a single queued request in the same thread */
01285        if( cri.op && !cri.nullop ) {
01286               rc = (long)connection_operation( ctx, cri.op );
01287        } else if ( cri.func ) {
01288               rc = (long)cri.func( ctx, cri.arg );
01289        }
01290 
01291        return (void*)(long)rc;
01292 }
01293 
01294 int connection_read_activate( ber_socket_t s )
01295 {
01296        int rc;
01297 
01298        /*
01299         * suspend reading on this file descriptor until a connection processing
01300         * thread reads data on it. Otherwise the listener thread will repeatedly
01301         * submit the same event on it to the pool.
01302         */
01303        rc = slapd_clr_read( s, 0 );
01304        if ( rc )
01305               return rc;
01306 
01307        /* Don't let blocked writers block a pause request */
01308        if ( connections[s].c_writewaiter &&
01309               ldap_pvt_thread_pool_pausing( &connection_pool ))
01310               connection_wake_writers( &connections[s] );
01311 
01312        rc = ldap_pvt_thread_pool_submit( &connection_pool,
01313               connection_read_thread, (void *)(long)s );
01314 
01315        if( rc != 0 ) {
01316               Debug( LDAP_DEBUG_ANY,
01317                      "connection_read_activate(%d): submit failed (%d)\n",
01318                      s, rc, 0 );
01319        }
01320 
01321        return rc;
01322 }
01323 
01324 static int
01325 connection_read( ber_socket_t s, conn_readinfo *cri )
01326 {
01327        int rc = 0;
01328        Connection *c;
01329 
01330        assert( connections != NULL );
01331 
01332        /* get (locked) connection */
01333        c = connection_get( s );
01334 
01335        if( c == NULL ) {
01336               Debug( LDAP_DEBUG_ANY,
01337                      "connection_read(%ld): no connection!\n",
01338                      (long) s, 0, 0 );
01339 
01340               return -1;
01341        }
01342 
01343        c->c_n_read++;
01344 
01345        if( c->c_conn_state == SLAP_C_CLOSING ) {
01346               Debug( LDAP_DEBUG_CONNS,
01347                      "connection_read(%d): closing, ignoring input for id=%lu\n",
01348                      s, c->c_connid, 0 );
01349               connection_return( c );
01350               return 0;
01351        }
01352 
01353        if ( c->c_conn_state == SLAP_C_CLIENT ) {
01354               cri->func = c->c_clientfunc;
01355               cri->arg = c->c_clientarg;
01356               /* read should already be cleared */
01357               connection_return( c );
01358               return 0;
01359        }
01360 
01361        Debug( LDAP_DEBUG_TRACE,
01362               "connection_read(%d): checking for input on id=%lu\n",
01363               s, c->c_connid, 0 );
01364 
01365 #ifdef HAVE_TLS
01366        if ( c->c_is_tls && c->c_needs_tls_accept ) {
01367               rc = ldap_pvt_tls_accept( c->c_sb, slap_tls_ctx );
01368               if ( rc < 0 ) {
01369                      Debug( LDAP_DEBUG_TRACE,
01370                             "connection_read(%d): TLS accept failure "
01371                             "error=%d id=%lu, closing\n",
01372                             s, rc, c->c_connid );
01373 
01374                      c->c_needs_tls_accept = 0;
01375                      /* c_mutex is locked */
01376                      connection_closing( c, "TLS negotiation failure" );
01377                      connection_close( c );
01378                      connection_return( c );
01379                      return 0;
01380 
01381               } else if ( rc == 0 ) {
01382                      void *ssl;
01383                      struct berval authid = BER_BVNULL;
01384 
01385                      c->c_needs_tls_accept = 0;
01386 
01387                      /* we need to let SASL know */
01388                      ssl = ldap_pvt_tls_sb_ctx( c->c_sb );
01389 
01390                      c->c_tls_ssf = (slap_ssf_t) ldap_pvt_tls_get_strength( ssl );
01391                      if( c->c_tls_ssf > c->c_ssf ) {
01392                             c->c_ssf = c->c_tls_ssf;
01393                      }
01394 
01395                      rc = dnX509peerNormalize( ssl, &authid );
01396                      if ( rc != LDAP_SUCCESS ) {
01397                             Debug( LDAP_DEBUG_TRACE, "connection_read(%d): "
01398                                    "unable to get TLS client DN, error=%d id=%lu\n",
01399                                    s, rc, c->c_connid );
01400                      }
01401                      Statslog( LDAP_DEBUG_STATS,
01402                             "conn=%lu fd=%d TLS established tls_ssf=%u ssf=%u\n",
01403                          c->c_connid, (int) s, c->c_tls_ssf, c->c_ssf, 0 );
01404                      slap_sasl_external( c, c->c_tls_ssf, &authid );
01405                      if ( authid.bv_val ) free( authid.bv_val );
01406               } else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb,
01407                      LBER_SB_OPT_NEEDS_WRITE, NULL )) { /* need to retry */
01408                      slapd_set_write( s, 1 );
01409                      connection_return( c );
01410                      return 0;
01411               }
01412 
01413               /* if success and data is ready, fall thru to data input loop */
01414               if( !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) )
01415               {
01416                      slapd_set_read( s, 1 );
01417                      connection_return( c );
01418                      return 0;
01419               }
01420        }
01421 #endif
01422 
01423 #ifdef HAVE_CYRUS_SASL
01424        if ( c->c_sasl_layers ) {
01425               /* If previous layer is not removed yet, give up for now */
01426               if ( !c->c_sasl_sockctx ) {
01427                      slapd_set_read( s, 1 );
01428                      connection_return( c );
01429                      return 0;
01430               }
01431 
01432               c->c_sasl_layers = 0;
01433 
01434               rc = ldap_pvt_sasl_install( c->c_sb, c->c_sasl_sockctx );
01435               if( rc != LDAP_SUCCESS ) {
01436                      Debug( LDAP_DEBUG_TRACE,
01437                             "connection_read(%d): SASL install error "
01438                             "error=%d id=%lu, closing\n",
01439                             s, rc, c->c_connid );
01440 
01441                      /* c_mutex is locked */
01442                      connection_closing( c, "SASL layer install failure" );
01443                      connection_close( c );
01444                      connection_return( c );
01445                      return 0;
01446               }
01447        }
01448 #endif
01449 
01450 #define CONNECTION_INPUT_LOOP 1
01451 /* #define    DATA_READY_LOOP 1 */
01452 
01453        do {
01454               /* How do we do this without getting into a busy loop ? */
01455               rc = connection_input( c, cri );
01456        }
01457 #ifdef DATA_READY_LOOP
01458        while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ));
01459 #elif defined CONNECTION_INPUT_LOOP
01460        while(!rc);
01461 #else
01462        while(0);
01463 #endif
01464 
01465        if( rc < 0 ) {
01466               Debug( LDAP_DEBUG_CONNS,
01467                      "connection_read(%d): input error=%d id=%lu, closing.\n",
01468                      s, rc, c->c_connid );
01469 
01470               /* c_mutex is locked */
01471               connection_closing( c, conn_lost_str );
01472               connection_close( c );
01473               connection_return( c );
01474               return 0;
01475        }
01476 
01477        if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
01478               slapd_set_write( s, 0 );
01479        }
01480 
01481        slapd_set_read( s, 1 );
01482        connection_return( c );
01483 
01484        return 0;
01485 }
01486 
01487 static int
01488 connection_input( Connection *conn , conn_readinfo *cri )
01489 {
01490        Operation *op;
01491        ber_tag_t     tag;
01492        ber_len_t     len;
01493        ber_int_t     msgid;
01494        BerElement    *ber;
01495        int           rc;
01496 #ifdef LDAP_CONNECTIONLESS
01497        Sockaddr      peeraddr;
01498        char          *cdn = NULL;
01499 #endif
01500        char *defer = NULL;
01501        void *ctx;
01502 
01503        if ( conn->c_currentber == NULL &&
01504               ( conn->c_currentber = ber_alloc()) == NULL )
01505        {
01506               Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
01507               return -1;
01508        }
01509 
01510        sock_errset(0);
01511 
01512 #ifdef LDAP_CONNECTIONLESS
01513        if ( conn->c_is_udp ) {
01514               char peername[sizeof("IP=255.255.255.255:65336")];
01515               const char *peeraddr_string = NULL;
01516 
01517               len = ber_int_sb_read(conn->c_sb, &peeraddr, sizeof(struct sockaddr));
01518               if (len != sizeof(struct sockaddr)) return 1;
01519 
01520 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
01521               char addr[INET_ADDRSTRLEN];
01522               peeraddr_string = inet_ntop( AF_INET, &peeraddr.sa_in_addr.sin_addr,
01523                         addr, sizeof(addr) );
01524 #else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
01525               peeraddr_string = inet_ntoa( peeraddr.sa_in_addr.sin_addr );
01526 #endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */
01527               sprintf( peername, "IP=%s:%d",
01528                       peeraddr_string,
01529                      (unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) );
01530               Statslog( LDAP_DEBUG_STATS,
01531                      "conn=%lu UDP request from %s (%s) accepted.\n",
01532                      conn->c_connid, peername, conn->c_sock_name.bv_val, 0, 0 );
01533        }
01534 #endif
01535 
01536        tag = ber_get_next( conn->c_sb, &len, conn->c_currentber );
01537        if ( tag != LDAP_TAG_MESSAGE ) {
01538               int err = sock_errno();
01539 
01540               if ( err != EWOULDBLOCK && err != EAGAIN ) {
01541                      /* log, close and send error */
01542                      Debug( LDAP_DEBUG_TRACE,
01543                             "ber_get_next on fd %d failed errno=%d (%s)\n",
01544                      conn->c_sd, err, sock_errstr(err) );
01545                      ber_free( conn->c_currentber, 1 );
01546                      conn->c_currentber = NULL;
01547 
01548                      return -2;
01549               }
01550               return 1;
01551        }
01552 
01553        ber = conn->c_currentber;
01554        conn->c_currentber = NULL;
01555 
01556        if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) {
01557               /* log, close and send error */
01558               Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0, 0 );
01559               ber_free( ber, 1 );
01560               return -1;
01561        }
01562 
01563        if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) {
01564               /* log, close and send error */
01565               Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0, 0 );
01566               ber_free( ber, 1 );
01567 
01568               return -1;
01569        }
01570 
01571 #ifdef LDAP_CONNECTIONLESS
01572        if( conn->c_is_udp ) {
01573               if( tag == LBER_OCTETSTRING ) {
01574                      if ( (tag = ber_get_stringa( ber, &cdn )) != LBER_ERROR )
01575                             tag = ber_peek_tag( ber, &len );
01576               }
01577               if( tag != LDAP_REQ_ABANDON && tag != LDAP_REQ_SEARCH ) {
01578                      Debug( LDAP_DEBUG_ANY, "invalid req for UDP 0x%lx\n", tag, 0, 0 );
01579                      ber_free( ber, 1 );
01580                      return 0;
01581               }
01582        }
01583 #endif
01584 
01585        if(tag == LDAP_REQ_BIND) {
01586               /* immediately abandon all existing operations upon BIND */
01587               connection_abandon( conn );
01588        }
01589 
01590        ctx = cri->ctx;
01591        op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++, ctx );
01592 
01593        Debug( LDAP_DEBUG_TRACE, "op tag 0x%lx, time %ld\n", tag,
01594               (long) op->o_time, 0);
01595 
01596        op->o_conn = conn;
01597        /* clear state if the connection is being reused from inactive */
01598        if ( conn->c_conn_state == SLAP_C_INACTIVE ) {
01599               memset( &conn->c_pagedresults_state, 0,
01600                      sizeof( conn->c_pagedresults_state ) );
01601        }
01602 
01603        op->o_res_ber = NULL;
01604 
01605 #ifdef LDAP_CONNECTIONLESS
01606        if (conn->c_is_udp) {
01607               if ( cdn ) {
01608                      ber_str2bv( cdn, 0, 1, &op->o_dn );
01609                      op->o_protocol = LDAP_VERSION2;
01610               }
01611               op->o_res_ber = ber_alloc_t( LBER_USE_DER );
01612               if (op->o_res_ber == NULL) return 1;
01613 
01614               rc = ber_write( op->o_res_ber, (char *)&peeraddr,
01615                      sizeof(struct sockaddr), 0 );
01616 
01617               if (rc != sizeof(struct sockaddr)) {
01618                      Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
01619                      return 1;
01620               }
01621 
01622               if (op->o_protocol == LDAP_VERSION2) {
01623                      rc = ber_printf(op->o_res_ber, "{is{" /*}}*/, op->o_msgid, "");
01624                      if (rc == -1) {
01625                             Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 );
01626                             return rc;
01627                      }
01628               }
01629        }
01630 #endif /* LDAP_CONNECTIONLESS */
01631 
01632        rc = 0;
01633 
01634        /* Don't process requests when the conn is in the middle of a
01635         * Bind, or if it's closing. Also, don't let any single conn
01636         * use up all the available threads, and don't execute if we're
01637         * currently blocked on output. And don't execute if there are
01638         * already pending ops, let them go first.  Abandon operations
01639         * get exceptions to some, but not all, cases.
01640         */
01641        switch( tag ){
01642        default:
01643               /* Abandon and Unbind are exempt from these checks */
01644               if (conn->c_conn_state == SLAP_C_CLOSING) {
01645                      defer = "closing";
01646                      break;
01647               } else if (conn->c_writewaiter) {
01648                      defer = "awaiting write";
01649                      break;
01650               } else if (conn->c_n_ops_pending) {
01651                      defer = "pending operations";
01652                      break;
01653               }
01654               /* FALLTHRU */
01655        case LDAP_REQ_ABANDON:
01656               /* Unbind is exempt from these checks */
01657               if (conn->c_n_ops_executing >= connection_pool_max/2) {
01658                      defer = "too many executing";
01659                      break;
01660               } else if (conn->c_conn_state == SLAP_C_BINDING) {
01661                      defer = "binding";
01662                      break;
01663               }
01664               /* FALLTHRU */
01665        case LDAP_REQ_UNBIND:
01666               break;
01667        }
01668 
01669        if( defer ) {
01670               int max = conn->c_dn.bv_len
01671                      ? slap_conn_max_pending_auth
01672                      : slap_conn_max_pending;
01673 
01674               Debug( LDAP_DEBUG_ANY,
01675                      "connection_input: conn=%lu deferring operation: %s\n",
01676                      conn->c_connid, defer, 0 );
01677               conn->c_n_ops_pending++;
01678               LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next );
01679               rc = ( conn->c_n_ops_pending > max ) ? -1 : 0;
01680 
01681        } else {
01682               conn->c_n_ops_executing++;
01683 
01684               /*
01685                * The first op will be processed in the same thread context,
01686                * as long as there is only one op total.
01687                * Subsequent ops will be submitted to the pool by
01688                * calling connection_op_activate()
01689                */
01690               if ( cri->op == NULL ) {
01691                      /* the first incoming request */
01692                      connection_op_queue( op );
01693                      cri->op = op;
01694               } else {
01695                      if ( !cri->nullop ) {
01696                             cri->nullop = 1;
01697                             rc = ldap_pvt_thread_pool_submit( &connection_pool,
01698                                    connection_operation, (void *) cri->op );
01699                      }
01700                      connection_op_activate( op );
01701               }
01702        }
01703 
01704 #ifdef NO_THREADS
01705        if ( conn->c_struct_state != SLAP_C_USED ) {
01706               /* connection must have got closed underneath us */
01707               return 1;
01708        }
01709 #endif
01710 
01711        assert( conn->c_struct_state == SLAP_C_USED );
01712        return rc;
01713 }
01714 
01715 static int
01716 connection_resched( Connection *conn )
01717 {
01718        Operation *op;
01719 
01720        if( conn->c_writewaiter )
01721               return 0;
01722 
01723        if( conn->c_conn_state == SLAP_C_CLOSING ) {
01724               Debug( LDAP_DEBUG_CONNS, "connection_resched: "
01725                      "attempting closing conn=%lu sd=%d\n",
01726                      conn->c_connid, conn->c_sd, 0 );
01727               connection_close( conn );
01728               return 0;
01729        }
01730 
01731        if( conn->c_conn_state != SLAP_C_ACTIVE ) {
01732               /* other states need different handling */
01733               return 0;
01734        }
01735 
01736        while ((op = LDAP_STAILQ_FIRST( &conn->c_pending_ops )) != NULL) {
01737               if ( conn->c_n_ops_executing > connection_pool_max/2 ) break;
01738 
01739               LDAP_STAILQ_REMOVE_HEAD( &conn->c_pending_ops, o_next );
01740               LDAP_STAILQ_NEXT(op, o_next) = NULL;
01741 
01742               /* pending operations should not be marked for abandonment */
01743               assert(!op->o_abandon);
01744 
01745               conn->c_n_ops_pending--;
01746               conn->c_n_ops_executing++;
01747 
01748               connection_op_activate( op );
01749 
01750               if ( conn->c_conn_state == SLAP_C_BINDING ) break;
01751        }
01752        return 0;
01753 }
01754 
01755 static void
01756 connection_init_log_prefix( Operation *op )
01757 {
01758        if ( op->o_connid == (unsigned long)(-1) ) {
01759               snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ),
01760                      "conn=-1 op=%lu", op->o_opid );
01761 
01762        } else {
01763               snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ),
01764                      "conn=%lu op=%lu", op->o_connid, op->o_opid );
01765        }
01766 }
01767 
01768 static int connection_bind_cleanup_cb( Operation *op, SlapReply *rs )
01769 {
01770        op->o_conn->c_sasl_bindop = NULL;
01771 
01772        ch_free( op->o_callback );
01773        op->o_callback = NULL;
01774 
01775        return SLAP_CB_CONTINUE;
01776 }
01777 
01778 static int connection_bind_cb( Operation *op, SlapReply *rs )
01779 {
01780        ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
01781        op->o_conn->c_sasl_bind_in_progress =
01782               ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS );
01783 
01784        /* Moved here from bind.c due to ITS#4158 */
01785        op->o_conn->c_sasl_bindop = NULL;
01786        if ( op->orb_method == LDAP_AUTH_SASL ) {
01787               if( rs->sr_err == LDAP_SUCCESS ) {
01788                      ber_dupbv(&op->o_conn->c_dn, &op->orb_edn);
01789                      if( !BER_BVISEMPTY( &op->orb_edn ) ) {
01790                             /* edn is always normalized already */
01791                             ber_dupbv( &op->o_conn->c_ndn, &op->o_conn->c_dn );
01792                      }
01793                      op->o_tmpfree( op->orb_edn.bv_val, op->o_tmpmemctx );
01794                      BER_BVZERO( &op->orb_edn );
01795                      op->o_conn->c_authmech = op->o_conn->c_sasl_bind_mech;
01796                      BER_BVZERO( &op->o_conn->c_sasl_bind_mech );
01797 
01798                      op->o_conn->c_sasl_ssf = op->orb_ssf;
01799                      if( op->orb_ssf > op->o_conn->c_ssf ) {
01800                             op->o_conn->c_ssf = op->orb_ssf;
01801                      }
01802 
01803                      if( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) {
01804                             ber_len_t max = sockbuf_max_incoming_auth;
01805                             ber_sockbuf_ctrl( op->o_conn->c_sb,
01806                                    LBER_SB_OPT_SET_MAX_INCOMING, &max );
01807                      }
01808 
01809                      /* log authorization identity */
01810                      Statslog( LDAP_DEBUG_STATS,
01811                             "%s BIND dn=\"%s\" mech=%s sasl_ssf=%d ssf=%d\n",
01812                             op->o_log_prefix,
01813                             BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
01814                             op->o_conn->c_authmech.bv_val,
01815                             op->orb_ssf, op->o_conn->c_ssf );
01816 
01817                      Debug( LDAP_DEBUG_TRACE,
01818                             "do_bind: SASL/%s bind: dn=\"%s\" sasl_ssf=%d\n",
01819                             op->o_conn->c_authmech.bv_val,
01820                             BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val,
01821                             op->orb_ssf );
01822 
01823               } else if ( rs->sr_err != LDAP_SASL_BIND_IN_PROGRESS ) {
01824                      if ( !BER_BVISNULL( &op->o_conn->c_sasl_bind_mech ) ) {
01825                             free( op->o_conn->c_sasl_bind_mech.bv_val );
01826                             BER_BVZERO( &op->o_conn->c_sasl_bind_mech );
01827                      }
01828               }
01829        }
01830        ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
01831 
01832        ch_free( op->o_callback );
01833        op->o_callback = NULL;
01834 
01835        return SLAP_CB_CONTINUE;
01836 }
01837 
01838 static void connection_op_queue( Operation *op )
01839 {
01840        ber_tag_t tag = op->o_tag;
01841 
01842        if (tag == LDAP_REQ_BIND) {
01843               slap_callback *sc = ch_calloc( 1, sizeof( slap_callback ));
01844               sc->sc_response = connection_bind_cb;
01845               sc->sc_cleanup = connection_bind_cleanup_cb;
01846               sc->sc_next = op->o_callback;
01847               op->o_callback = sc;
01848               op->o_conn->c_conn_state = SLAP_C_BINDING;
01849        }
01850 
01851        if (!op->o_dn.bv_len) {
01852               op->o_authz = op->o_conn->c_authz;
01853               if ( BER_BVISNULL( &op->o_conn->c_sasl_authz_dn )) {
01854                      ber_dupbv( &op->o_dn, &op->o_conn->c_dn );
01855                      ber_dupbv( &op->o_ndn, &op->o_conn->c_ndn );
01856               } else {
01857                      ber_dupbv( &op->o_dn, &op->o_conn->c_sasl_authz_dn );
01858                      ber_dupbv( &op->o_ndn, &op->o_conn->c_sasl_authz_dn );
01859               }
01860        }
01861 
01862        op->o_authtype = op->o_conn->c_authtype;
01863        ber_dupbv( &op->o_authmech, &op->o_conn->c_authmech );
01864        
01865        if (!op->o_protocol) {
01866               op->o_protocol = op->o_conn->c_protocol
01867                      ? op->o_conn->c_protocol : LDAP_VERSION3;
01868        }
01869 
01870        if (op->o_conn->c_conn_state == SLAP_C_INACTIVE &&
01871               op->o_protocol > LDAP_VERSION2)
01872        {
01873               op->o_conn->c_conn_state = SLAP_C_ACTIVE;
01874        }
01875 
01876        op->o_connid = op->o_conn->c_connid;
01877        connection_init_log_prefix( op );
01878 
01879        LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next );
01880 }
01881 
01882 static int connection_op_activate( Operation *op )
01883 {
01884        int rc;
01885 
01886        connection_op_queue( op );
01887 
01888        rc = ldap_pvt_thread_pool_submit( &connection_pool,
01889               connection_operation, (void *) op );
01890 
01891        if ( rc != 0 ) {
01892               Debug( LDAP_DEBUG_ANY,
01893                      "connection_op_activate: submit failed (%d) for conn=%lu\n",
01894                      rc, op->o_connid, 0 );
01895               /* should move op to pending list */
01896        }
01897 
01898        return rc;
01899 }
01900 
01901 int connection_write(ber_socket_t s)
01902 {
01903        Connection *c;
01904        Operation *op;
01905 
01906        assert( connections != NULL );
01907 
01908        c = connection_get( s );
01909        if( c == NULL ) {
01910               Debug( LDAP_DEBUG_ANY,
01911                      "connection_write(%ld): no connection!\n",
01912                      (long)s, 0, 0 );
01913               return -1;
01914        }
01915 
01916        slapd_clr_write( s, 0 );
01917 
01918 #ifdef HAVE_TLS
01919        if ( c->c_is_tls && c->c_needs_tls_accept ) {
01920               connection_return( c );
01921               connection_read_activate( s );
01922               return 0;
01923        }
01924 #endif
01925 
01926        c->c_n_write++;
01927 
01928        Debug( LDAP_DEBUG_TRACE,
01929               "connection_write(%d): waking output for id=%lu\n",
01930               s, c->c_connid, 0 );
01931        ldap_pvt_thread_mutex_lock( &c->c_write2_mutex );
01932        ldap_pvt_thread_cond_signal( &c->c_write2_cv );
01933        ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex );
01934 
01935        if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) {
01936               slapd_set_read( s, 1 );
01937        }
01938        if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) {
01939               slapd_set_write( s, 1 );
01940        }
01941 
01942        /* If there are ops pending because of a writewaiter,
01943         * start one up.
01944         */
01945        while ((op = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) {
01946               if ( !c->c_writewaiter ) break;
01947               if ( c->c_n_ops_executing > connection_pool_max/2 ) break;
01948 
01949               LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next );
01950               LDAP_STAILQ_NEXT(op, o_next) = NULL;
01951 
01952               /* pending operations should not be marked for abandonment */
01953               assert(!op->o_abandon);
01954 
01955               c->c_n_ops_pending--;
01956               c->c_n_ops_executing++;
01957 
01958               connection_op_activate( op );
01959 
01960               break;
01961        }
01962 
01963        connection_return( c );
01964        return 0;
01965 }
01966 
01967 #ifdef LDAP_SLAPI
01968 typedef struct conn_fake_extblock {
01969        void *eb_conn;
01970        void *eb_op;
01971 } conn_fake_extblock;
01972 
01973 static void
01974 connection_fake_destroy(
01975        void *key,
01976        void *data )
01977 {
01978        Connection conn = {0};
01979        Operation op = {0};
01980        Opheader ohdr = {0};
01981 
01982        conn_fake_extblock *eb = data;
01983        
01984        op.o_hdr = &ohdr;
01985        op.o_hdr->oh_extensions = eb->eb_op;
01986        conn.c_extensions = eb->eb_conn;
01987        op.o_conn = &conn;
01988        conn.c_connid = -1;
01989        op.o_connid = -1;
01990 
01991        ber_memfree_x( eb, NULL );
01992        slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, &op );
01993        slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, &conn );
01994 }
01995 #endif
01996 
01997 void
01998 connection_fake_init(
01999        Connection *conn,
02000        OperationBuffer *opbuf,
02001        void *ctx )
02002 {
02003        connection_fake_init2( conn, opbuf, ctx, 1 );
02004 }
02005 
02006 void
02007 operation_fake_init(
02008        Connection *conn,
02009        Operation *op,
02010        void *ctx,
02011        int newmem )
02012 {
02013        /* set memory context */
02014        op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx,
02015               newmem );
02016        op->o_tmpmfuncs = &slap_sl_mfuncs;
02017        op->o_threadctx = ctx;
02018        op->o_tid = ldap_pvt_thread_pool_tid( ctx );
02019 
02020        op->o_counters = &slap_counters;
02021        op->o_conn = conn;
02022        op->o_connid = op->o_conn->c_connid;
02023        connection_init_log_prefix( op );
02024 }
02025 
02026 
02027 void
02028 connection_fake_init2(
02029        Connection *conn,
02030        OperationBuffer *opbuf,
02031        void *ctx,
02032        int newmem )
02033 {
02034        Operation *op = (Operation *) opbuf;
02035 
02036        conn->c_connid = -1;
02037        conn->c_conn_idx = -1;
02038        conn->c_send_ldap_result = slap_send_ldap_result;
02039        conn->c_send_search_entry = slap_send_search_entry;
02040        conn->c_send_search_reference = slap_send_search_reference;
02041        conn->c_send_ldap_extended = slap_send_ldap_extended;
02042        conn->c_send_ldap_intermediate = slap_send_ldap_intermediate;
02043        conn->c_listener = (Listener *)&dummy_list;
02044        conn->c_peer_domain = slap_empty_bv;
02045        conn->c_peer_name = slap_empty_bv;
02046 
02047        memset( opbuf, 0, sizeof( *opbuf ));
02048        op->o_hdr = &opbuf->ob_hdr;
02049        op->o_controls = opbuf->ob_controls;
02050 
02051        operation_fake_init( conn, op, ctx, newmem );
02052 
02053 #ifdef LDAP_SLAPI
02054        if ( slapi_plugins_used ) {
02055               conn_fake_extblock *eb;
02056               void *ebx = NULL;
02057 
02058               /* Use thread keys to make sure these eventually get cleaned up */
02059               if ( ldap_pvt_thread_pool_getkey( ctx, (void *)connection_fake_init,
02060                             &ebx, NULL )) {
02061                      eb = ch_malloc( sizeof( *eb ));
02062                      slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn );
02063                      slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op );
02064                      eb->eb_conn = conn->c_extensions;
02065                      eb->eb_op = op->o_hdr->oh_extensions;
02066                      ldap_pvt_thread_pool_setkey( ctx, (void *)connection_fake_init,
02067                             eb, connection_fake_destroy, NULL, NULL );
02068               } else {
02069                      eb = ebx;
02070                      conn->c_extensions = eb->eb_conn;
02071                      op->o_hdr->oh_extensions = eb->eb_op;
02072               }
02073        }
02074 #endif /* LDAP_SLAPI */
02075 
02076        slap_op_time( &op->o_time, &op->o_tincr );
02077 }
02078 
02079 void
02080 connection_assign_nextid( Connection *conn )
02081 {
02082        ldap_pvt_thread_mutex_lock( &conn_nextid_mutex );
02083        conn->c_connid = conn_nextid++;
02084        ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex );
02085 }