1/* $NetBSD: connection.c,v 1.1.1.3 2010/12/12 15:22:27 adam Exp $ */ 2 3/* OpenLDAP: pkg/ldap/servers/slapd/connection.c,v 1.358.2.40 2010/04/13 20:23:13 kurt Exp */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2010 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17/* Portions Copyright (c) 1995 Regents of the University of Michigan. 18 * All rights reserved. 19 * 20 * Redistribution and use in source and binary forms are permitted 21 * provided that this notice is preserved and that due credit is given 22 * to the University of Michigan at Ann Arbor. The name of the University 23 * may not be used to endorse or promote products derived from this 24 * software without specific prior written permission. This software 25 * is provided ``as is'' without express or implied warranty. 26 */ 27 28#include "portable.h" 29 30#include <stdio.h> 31#ifdef HAVE_LIMITS_H 32#include <limits.h> 33#endif 34 35#include <ac/socket.h> 36#include <ac/errno.h> 37#include <ac/string.h> 38#include <ac/time.h> 39#include <ac/unistd.h> 40 41#include "lutil.h" 42#include "slap.h" 43 44#ifdef LDAP_SLAPI 45#include "slapi/slapi.h" 46#endif 47 48/* protected by connections_mutex */ 49static ldap_pvt_thread_mutex_t connections_mutex; 50static Connection *connections = NULL; 51 52static ldap_pvt_thread_mutex_t conn_nextid_mutex; 53static unsigned long conn_nextid = SLAPD_SYNC_SYNCCONN_OFFSET; 54 55static const char conn_lost_str[] = "connection lost"; 56 57const char * 58connection_state2str( int state ) 59{ 60 switch( state ) { 61 case SLAP_C_INVALID: return "!"; 62 case SLAP_C_INACTIVE: return "|"; 63 case SLAP_C_CLOSING: return "C"; 64 case SLAP_C_ACTIVE: return ""; 65 case SLAP_C_BINDING: return "B"; 66 case SLAP_C_CLIENT: return "L"; 67 } 68 69 return "?"; 70} 71 72static Connection* connection_get( ber_socket_t s ); 73 74typedef struct conn_readinfo { 75 Operation *op; 76 ldap_pvt_thread_start_t *func; 77 void *arg; 78 void *ctx; 79 int nullop; 80} conn_readinfo; 81 82static int connection_input( Connection *c, conn_readinfo *cri ); 83static void connection_close( Connection *c ); 84 85static int connection_op_activate( Operation *op ); 86static void connection_op_queue( Operation *op ); 87static int connection_resched( Connection *conn ); 88static void connection_abandon( Connection *conn ); 89static void connection_destroy( Connection *c ); 90 91static ldap_pvt_thread_start_t connection_operation; 92 93/* 94 * Initialize connection management infrastructure. 95 */ 96int connections_init(void) 97{ 98 int i; 99 100 assert( connections == NULL ); 101 102 if( connections != NULL) { 103 Debug( LDAP_DEBUG_ANY, "connections_init: already initialized.\n", 104 0, 0, 0 ); 105 return -1; 106 } 107 108 /* should check return of every call */ 109 ldap_pvt_thread_mutex_init( &connections_mutex ); 110 ldap_pvt_thread_mutex_init( &conn_nextid_mutex ); 111 112 connections = (Connection *) ch_calloc( dtblsize, sizeof(Connection) ); 113 114 if( connections == NULL ) { 115 Debug( LDAP_DEBUG_ANY, "connections_init: " 116 "allocation (%d*%ld) of connection array failed\n", 117 dtblsize, (long) sizeof(Connection), 0 ); 118 return -1; 119 } 120 121 assert( connections[0].c_struct_state == SLAP_C_UNINITIALIZED ); 122 assert( connections[dtblsize-1].c_struct_state == SLAP_C_UNINITIALIZED ); 123 124 for (i=0; i<dtblsize; i++) connections[i].c_conn_idx = i; 125 126 /* 127 * per entry initialization of the Connection array initialization 128 * will be done by connection_init() 129 */ 130 131 return 0; 132} 133 134/* 135 * Destroy connection management infrastructure. 136 */ 137 138int connections_destroy(void) 139{ 140 ber_socket_t i; 141 142 /* should check return of every call */ 143 144 if( connections == NULL) { 145 Debug( LDAP_DEBUG_ANY, "connections_destroy: nothing to destroy.\n", 146 0, 0, 0 ); 147 return -1; 148 } 149 150 for ( i = 0; i < dtblsize; i++ ) { 151 if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) { 152 ber_sockbuf_free( connections[i].c_sb ); 153 ldap_pvt_thread_mutex_destroy( &connections[i].c_mutex ); 154 ldap_pvt_thread_mutex_destroy( &connections[i].c_write1_mutex ); 155 ldap_pvt_thread_mutex_destroy( &connections[i].c_write2_mutex ); 156 ldap_pvt_thread_cond_destroy( &connections[i].c_write1_cv ); 157 ldap_pvt_thread_cond_destroy( &connections[i].c_write2_cv ); 158#ifdef LDAP_SLAPI 159 if ( slapi_plugins_used ) { 160 slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, 161 &connections[i] ); 162 } 163#endif 164 } 165 } 166 167 free( connections ); 168 connections = NULL; 169 170 ldap_pvt_thread_mutex_destroy( &connections_mutex ); 171 ldap_pvt_thread_mutex_destroy( &conn_nextid_mutex ); 172 return 0; 173} 174 175/* 176 * shutdown all connections 177 */ 178int connections_shutdown(void) 179{ 180 ber_socket_t i; 181 182 for ( i = 0; i < dtblsize; i++ ) { 183 if( connections[i].c_struct_state != SLAP_C_UNINITIALIZED ) { 184 ldap_pvt_thread_mutex_lock( &connections[i].c_mutex ); 185 if( connections[i].c_struct_state == SLAP_C_USED ) { 186 187 /* give persistent clients a chance to cleanup */ 188 if( connections[i].c_conn_state == SLAP_C_CLIENT ) { 189 ldap_pvt_thread_pool_submit( &connection_pool, 190 connections[i].c_clientfunc, connections[i].c_clientarg ); 191 } else { 192 /* c_mutex is locked */ 193 connection_closing( &connections[i], "slapd shutdown" ); 194 connection_close( &connections[i] ); 195 } 196 } 197 ldap_pvt_thread_mutex_unlock( &connections[i].c_mutex ); 198 } 199 } 200 201 return 0; 202} 203 204/* 205 * Timeout idle connections. 206 */ 207int connections_timeout_idle(time_t now) 208{ 209 int i = 0, writers = 0; 210 int connindex; 211 Connection* c; 212 time_t old; 213 214 old = slapd_get_writetime(); 215 216 for( c = connection_first( &connindex ); 217 c != NULL; 218 c = connection_next( c, &connindex ) ) 219 { 220 /* Don't timeout a slow-running request or a persistent 221 * outbound connection. But if it has a writewaiter, see 222 * if the waiter has been there too long. 223 */ 224 if(( c->c_n_ops_executing && !c->c_writewaiter) 225 || c->c_conn_state == SLAP_C_CLIENT ) { 226 continue; 227 } 228 229 if( global_idletimeout && 230 difftime( c->c_activitytime+global_idletimeout, now) < 0 ) { 231 /* close it */ 232 connection_closing( c, "idletimeout" ); 233 connection_close( c ); 234 i++; 235 continue; 236 } 237 if ( c->c_writewaiter && global_writetimeout ) { 238 writers = 1; 239 if( difftime( c->c_activitytime+global_writetimeout, now) < 0 ) { 240 /* close it */ 241 connection_closing( c, "writetimeout" ); 242 connection_close( c ); 243 i++; 244 } 245 } 246 } 247 connection_done( c ); 248 if ( old && !writers ) 249 slapd_clr_writetime( old ); 250 251 return i; 252} 253 254static Connection* connection_get( ber_socket_t s ) 255{ 256 Connection *c; 257 258 Debug( LDAP_DEBUG_ARGS, 259 "connection_get(%ld)\n", 260 (long) s, 0, 0 ); 261 262 assert( connections != NULL ); 263 264 if(s == AC_SOCKET_INVALID) return NULL; 265 266 assert( s < dtblsize ); 267 c = &connections[s]; 268 269 if( c != NULL ) { 270 ldap_pvt_thread_mutex_lock( &c->c_mutex ); 271 272 assert( c->c_struct_state != SLAP_C_UNINITIALIZED ); 273 274 if( c->c_struct_state != SLAP_C_USED ) { 275 /* connection must have been closed due to resched */ 276 277 assert( c->c_conn_state == SLAP_C_INVALID ); 278 assert( c->c_sd == AC_SOCKET_INVALID ); 279 280 Debug( LDAP_DEBUG_CONNS, 281 "connection_get(%d): connection not used\n", 282 s, 0, 0 ); 283 284 ldap_pvt_thread_mutex_unlock( &c->c_mutex ); 285 return NULL; 286 } 287 288 Debug( LDAP_DEBUG_TRACE, 289 "connection_get(%d): got connid=%lu\n", 290 s, c->c_connid, 0 ); 291 292 c->c_n_get++; 293 294 assert( c->c_struct_state == SLAP_C_USED ); 295 assert( c->c_conn_state != SLAP_C_INVALID ); 296 assert( c->c_sd != AC_SOCKET_INVALID ); 297 298#ifndef SLAPD_MONITOR 299 if ( global_idletimeout > 0 ) 300#endif /* ! SLAPD_MONITOR */ 301 { 302 c->c_activitytime = slap_get_time(); 303 } 304 } 305 306 return c; 307} 308 309static void connection_return( Connection *c ) 310{ 311 ldap_pvt_thread_mutex_unlock( &c->c_mutex ); 312} 313 314Connection * connection_init( 315 ber_socket_t s, 316 Listener *listener, 317 const char* dnsname, 318 const char* peername, 319 int flags, 320 slap_ssf_t ssf, 321 struct berval *authid 322 LDAP_PF_LOCAL_SENDMSG_ARG(struct berval *peerbv)) 323{ 324 unsigned long id; 325 Connection *c; 326 int doinit = 0; 327 ber_socket_t sfd = SLAP_FD2SOCK(s); 328 329 assert( connections != NULL ); 330 331 assert( listener != NULL ); 332 assert( dnsname != NULL ); 333 assert( peername != NULL ); 334 335#ifndef HAVE_TLS 336 assert( !( flags & CONN_IS_TLS )); 337#endif 338 339 if( s == AC_SOCKET_INVALID ) { 340 Debug( LDAP_DEBUG_ANY, 341 "connection_init: init of socket %ld invalid.\n", (long)s, 0, 0 ); 342 return NULL; 343 } 344 345 assert( s >= 0 ); 346 assert( s < dtblsize ); 347 c = &connections[s]; 348 if( c->c_struct_state == SLAP_C_UNINITIALIZED ) { 349 doinit = 1; 350 } else { 351 assert( c->c_struct_state == SLAP_C_UNUSED ); 352 } 353 354 if( doinit ) { 355 c->c_send_ldap_result = slap_send_ldap_result; 356 c->c_send_search_entry = slap_send_search_entry; 357 c->c_send_search_reference = slap_send_search_reference; 358 c->c_send_ldap_extended = slap_send_ldap_extended; 359 c->c_send_ldap_intermediate = slap_send_ldap_intermediate; 360 361 BER_BVZERO( &c->c_authmech ); 362 BER_BVZERO( &c->c_dn ); 363 BER_BVZERO( &c->c_ndn ); 364 365 c->c_listener = NULL; 366 BER_BVZERO( &c->c_peer_domain ); 367 BER_BVZERO( &c->c_peer_name ); 368 369 LDAP_STAILQ_INIT(&c->c_ops); 370 LDAP_STAILQ_INIT(&c->c_pending_ops); 371 372#ifdef LDAP_X_TXN 373 c->c_txn = CONN_TXN_INACTIVE; 374 c->c_txn_backend = NULL; 375 LDAP_STAILQ_INIT(&c->c_txn_ops); 376#endif 377 378 BER_BVZERO( &c->c_sasl_bind_mech ); 379 c->c_sasl_done = 0; 380 c->c_sasl_authctx = NULL; 381 c->c_sasl_sockctx = NULL; 382 c->c_sasl_extra = NULL; 383 c->c_sasl_bindop = NULL; 384 385 c->c_sb = ber_sockbuf_alloc( ); 386 387 { 388 ber_len_t max = sockbuf_max_incoming; 389 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); 390 } 391 392 c->c_currentber = NULL; 393 394 /* should check status of thread calls */ 395 ldap_pvt_thread_mutex_init( &c->c_mutex ); 396 ldap_pvt_thread_mutex_init( &c->c_write1_mutex ); 397 ldap_pvt_thread_mutex_init( &c->c_write2_mutex ); 398 ldap_pvt_thread_cond_init( &c->c_write1_cv ); 399 ldap_pvt_thread_cond_init( &c->c_write2_cv ); 400 401#ifdef LDAP_SLAPI 402 if ( slapi_plugins_used ) { 403 slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, c ); 404 } 405#endif 406 } 407 408 ldap_pvt_thread_mutex_lock( &c->c_mutex ); 409 410 assert( BER_BVISNULL( &c->c_authmech ) ); 411 assert( BER_BVISNULL( &c->c_dn ) ); 412 assert( BER_BVISNULL( &c->c_ndn ) ); 413 assert( c->c_listener == NULL ); 414 assert( BER_BVISNULL( &c->c_peer_domain ) ); 415 assert( BER_BVISNULL( &c->c_peer_name ) ); 416 assert( LDAP_STAILQ_EMPTY(&c->c_ops) ); 417 assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) ); 418#ifdef LDAP_X_TXN 419 assert( c->c_txn == CONN_TXN_INACTIVE ); 420 assert( c->c_txn_backend == NULL ); 421 assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) ); 422#endif 423 assert( BER_BVISNULL( &c->c_sasl_bind_mech ) ); 424 assert( c->c_sasl_done == 0 ); 425 assert( c->c_sasl_authctx == NULL ); 426 assert( c->c_sasl_sockctx == NULL ); 427 assert( c->c_sasl_extra == NULL ); 428 assert( c->c_sasl_bindop == NULL ); 429 assert( c->c_currentber == NULL ); 430 assert( c->c_writewaiter == 0); 431 assert( c->c_writers == 0); 432 433 c->c_listener = listener; 434 c->c_sd = s; 435 436 if ( flags & CONN_IS_CLIENT ) { 437 c->c_connid = 0; 438 ldap_pvt_thread_mutex_lock( &connections_mutex ); 439 c->c_conn_state = SLAP_C_CLIENT; 440 c->c_struct_state = SLAP_C_USED; 441 ldap_pvt_thread_mutex_unlock( &connections_mutex ); 442 c->c_close_reason = "?"; /* should never be needed */ 443 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_FD, &sfd ); 444 ldap_pvt_thread_mutex_unlock( &c->c_mutex ); 445 446 return c; 447 } 448 449 ber_str2bv( dnsname, 0, 1, &c->c_peer_domain ); 450 ber_str2bv( peername, 0, 1, &c->c_peer_name ); 451 452 c->c_n_ops_received = 0; 453 c->c_n_ops_executing = 0; 454 c->c_n_ops_pending = 0; 455 c->c_n_ops_completed = 0; 456 457 c->c_n_get = 0; 458 c->c_n_read = 0; 459 c->c_n_write = 0; 460 461 /* set to zero until bind, implies LDAP_VERSION3 */ 462 c->c_protocol = 0; 463 464#ifndef SLAPD_MONITOR 465 if ( global_idletimeout > 0 ) 466#endif /* ! SLAPD_MONITOR */ 467 { 468 c->c_activitytime = c->c_starttime = slap_get_time(); 469 } 470 471#ifdef LDAP_CONNECTIONLESS 472 c->c_is_udp = 0; 473 if( flags & CONN_IS_UDP ) { 474 c->c_is_udp = 1; 475#ifdef LDAP_DEBUG 476 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug, 477 LBER_SBIOD_LEVEL_PROVIDER, (void*)"udp_" ); 478#endif 479 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_udp, 480 LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd ); 481 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_readahead, 482 LBER_SBIOD_LEVEL_PROVIDER, NULL ); 483 } else 484#endif /* LDAP_CONNECTIONLESS */ 485#ifdef LDAP_PF_LOCAL 486 if ( flags & CONN_IS_IPC ) { 487#ifdef LDAP_DEBUG 488 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug, 489 LBER_SBIOD_LEVEL_PROVIDER, (void*)"ipc_" ); 490#endif 491 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_fd, 492 LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd ); 493#ifdef LDAP_PF_LOCAL_SENDMSG 494 if ( !BER_BVISEMPTY( peerbv )) 495 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_UNGET_BUF, peerbv ); 496#endif 497 } else 498#endif /* LDAP_PF_LOCAL */ 499 { 500#ifdef LDAP_DEBUG 501 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug, 502 LBER_SBIOD_LEVEL_PROVIDER, (void*)"tcp_" ); 503#endif 504 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_tcp, 505 LBER_SBIOD_LEVEL_PROVIDER, (void *)&sfd ); 506 } 507 508#ifdef LDAP_DEBUG 509 ber_sockbuf_add_io( c->c_sb, &ber_sockbuf_io_debug, 510 INT_MAX, (void*)"ldap_" ); 511#endif 512 513 if( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_NONBLOCK, 514 c /* non-NULL */ ) < 0 ) 515 { 516 Debug( LDAP_DEBUG_ANY, 517 "connection_init(%d, %s): set nonblocking failed\n", 518 s, c->c_peer_name.bv_val, 0 ); 519 } 520 521 ldap_pvt_thread_mutex_lock( &conn_nextid_mutex ); 522 id = c->c_connid = conn_nextid++; 523 ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex ); 524 525 ldap_pvt_thread_mutex_lock( &connections_mutex ); 526 c->c_conn_state = SLAP_C_INACTIVE; 527 c->c_struct_state = SLAP_C_USED; 528 ldap_pvt_thread_mutex_unlock( &connections_mutex ); 529 c->c_close_reason = "?"; /* should never be needed */ 530 531 c->c_ssf = c->c_transport_ssf = ssf; 532 c->c_tls_ssf = 0; 533 534#ifdef HAVE_TLS 535 if ( flags & CONN_IS_TLS ) { 536 c->c_is_tls = 1; 537 c->c_needs_tls_accept = 1; 538 } else { 539 c->c_is_tls = 0; 540 c->c_needs_tls_accept = 0; 541 } 542#endif 543 544 slap_sasl_open( c, 0 ); 545 slap_sasl_external( c, ssf, authid ); 546 547 slapd_add_internal( s, 1 ); 548 ldap_pvt_thread_mutex_unlock( &c->c_mutex ); 549 550 backend_connection_init(c); 551 552 return c; 553} 554 555void connection2anonymous( Connection *c ) 556{ 557 assert( connections != NULL ); 558 assert( c != NULL ); 559 560 { 561 ber_len_t max = sockbuf_max_incoming; 562 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); 563 } 564 565 if ( !BER_BVISNULL( &c->c_authmech ) ) { 566 ch_free(c->c_authmech.bv_val); 567 } 568 BER_BVZERO( &c->c_authmech ); 569 570 if ( !BER_BVISNULL( &c->c_dn ) ) { 571 ch_free(c->c_dn.bv_val); 572 } 573 BER_BVZERO( &c->c_dn ); 574 575 if ( !BER_BVISNULL( &c->c_ndn ) ) { 576 ch_free(c->c_ndn.bv_val); 577 } 578 BER_BVZERO( &c->c_ndn ); 579 580 if ( !BER_BVISNULL( &c->c_sasl_authz_dn ) ) { 581 ber_memfree_x( c->c_sasl_authz_dn.bv_val, NULL ); 582 } 583 BER_BVZERO( &c->c_sasl_authz_dn ); 584 585 c->c_authz_backend = NULL; 586} 587 588static void 589connection_destroy( Connection *c ) 590{ 591 unsigned long connid; 592 const char *close_reason; 593 Sockbuf *sb; 594 ber_socket_t sd; 595 596 assert( connections != NULL ); 597 assert( c != NULL ); 598 assert( c->c_struct_state != SLAP_C_UNUSED ); 599 assert( c->c_conn_state != SLAP_C_INVALID ); 600 assert( LDAP_STAILQ_EMPTY(&c->c_ops) ); 601 assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) ); 602#ifdef LDAP_X_TXN 603 assert( c->c_txn == CONN_TXN_INACTIVE ); 604 assert( c->c_txn_backend == NULL ); 605 assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) ); 606#endif 607 assert( c->c_writewaiter == 0); 608 assert( c->c_writers == 0); 609 610 /* only for stats (print -1 as "%lu" may give unexpected results ;) */ 611 connid = c->c_connid; 612 close_reason = c->c_close_reason; 613 614 ldap_pvt_thread_mutex_lock( &connections_mutex ); 615 c->c_struct_state = SLAP_C_PENDING; 616 ldap_pvt_thread_mutex_unlock( &connections_mutex ); 617 618 backend_connection_destroy(c); 619 620 c->c_protocol = 0; 621 c->c_connid = -1; 622 623 c->c_activitytime = c->c_starttime = 0; 624 625 connection2anonymous( c ); 626 c->c_listener = NULL; 627 628 if(c->c_peer_domain.bv_val != NULL) { 629 free(c->c_peer_domain.bv_val); 630 } 631 BER_BVZERO( &c->c_peer_domain ); 632 if(c->c_peer_name.bv_val != NULL) { 633 free(c->c_peer_name.bv_val); 634 } 635 BER_BVZERO( &c->c_peer_name ); 636 637 c->c_sasl_bind_in_progress = 0; 638 if(c->c_sasl_bind_mech.bv_val != NULL) { 639 free(c->c_sasl_bind_mech.bv_val); 640 } 641 BER_BVZERO( &c->c_sasl_bind_mech ); 642 643 slap_sasl_close( c ); 644 645 if ( c->c_currentber != NULL ) { 646 ber_free( c->c_currentber, 1 ); 647 c->c_currentber = NULL; 648 } 649 650 651#ifdef LDAP_SLAPI 652 /* call destructors, then constructors; avoids unnecessary allocation */ 653 if ( slapi_plugins_used ) { 654 slapi_int_clear_object_extensions( SLAPI_X_EXT_CONNECTION, c ); 655 } 656#endif 657 658 sd = c->c_sd; 659 c->c_sd = AC_SOCKET_INVALID; 660 c->c_conn_state = SLAP_C_INVALID; 661 c->c_struct_state = SLAP_C_UNUSED; 662 c->c_close_reason = "?"; /* should never be needed */ 663 664 sb = c->c_sb; 665 c->c_sb = ber_sockbuf_alloc( ); 666 { 667 ber_len_t max = sockbuf_max_incoming; 668 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); 669 } 670 671 /* c must be fully reset by this point; when we call slapd_remove 672 * it may get immediately reused by a new connection. 673 */ 674 if ( sd != AC_SOCKET_INVALID ) { 675 slapd_remove( sd, sb, 1, 0, 0 ); 676 677 if ( close_reason == NULL ) { 678 Statslog( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed\n", 679 connid, (long) sd, 0, 0, 0 ); 680 } else { 681 Statslog( LDAP_DEBUG_STATS, "conn=%lu fd=%ld closed (%s)\n", 682 connid, (long) sd, close_reason, 0, 0 ); 683 } 684 } 685} 686 687int connection_valid( Connection *c ) 688{ 689 /* c_mutex must be locked by caller */ 690 691 assert( c != NULL ); 692 693 return c->c_struct_state == SLAP_C_USED && 694 c->c_conn_state >= SLAP_C_ACTIVE && 695 c->c_conn_state <= SLAP_C_CLIENT; 696} 697 698static void connection_abandon( Connection *c ) 699{ 700 /* c_mutex must be locked by caller */ 701 702 Operation *o, *next, op = {0}; 703 Opheader ohdr = {0}; 704 SlapReply rs = {0}; 705 706 op.o_hdr = &ohdr; 707 op.o_conn = c; 708 op.o_connid = c->c_connid; 709 op.o_tag = LDAP_REQ_ABANDON; 710 711 for ( o = LDAP_STAILQ_FIRST( &c->c_ops ); o; o=next ) { 712 next = LDAP_STAILQ_NEXT( o, o_next ); 713 op.orn_msgid = o->o_msgid; 714 o->o_abandon = 1; 715 op.o_bd = frontendDB; 716 frontendDB->be_abandon( &op, &rs ); 717 } 718 719#ifdef LDAP_X_TXN 720 /* remove operations in pending transaction */ 721 while ( (o = LDAP_STAILQ_FIRST( &c->c_txn_ops )) != NULL) { 722 LDAP_STAILQ_REMOVE_HEAD( &c->c_txn_ops, o_next ); 723 LDAP_STAILQ_NEXT(o, o_next) = NULL; 724 slap_op_free( o, NULL ); 725 } 726 727 /* clear transaction */ 728 c->c_txn_backend = NULL; 729 c->c_txn = CONN_TXN_INACTIVE; 730#endif 731 732 /* remove pending operations */ 733 while ( (o = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) { 734 LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next ); 735 LDAP_STAILQ_NEXT(o, o_next) = NULL; 736 slap_op_free( o, NULL ); 737 } 738} 739 740static void 741connection_wake_writers( Connection *c ) 742{ 743 /* wake write blocked operations */ 744 ldap_pvt_thread_mutex_lock( &c->c_write1_mutex ); 745 if ( c->c_writers > 0 ) { 746 c->c_writers = -c->c_writers; 747 ldap_pvt_thread_cond_broadcast( &c->c_write1_cv ); 748 ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex ); 749 if ( c->c_writewaiter ) { 750 ldap_pvt_thread_mutex_lock( &c->c_write2_mutex ); 751 ldap_pvt_thread_cond_signal( &c->c_write2_cv ); 752 slapd_clr_write( c->c_sd, 1 ); 753 ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex ); 754 } 755 ldap_pvt_thread_mutex_lock( &c->c_write1_mutex ); 756 while ( c->c_writers ) { 757 ldap_pvt_thread_cond_wait( &c->c_write1_cv, &c->c_write1_mutex ); 758 } 759 ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex ); 760 } else { 761 ldap_pvt_thread_mutex_unlock( &c->c_write1_mutex ); 762 slapd_clr_write( c->c_sd, 1 ); 763 } 764} 765 766void connection_closing( Connection *c, const char *why ) 767{ 768 assert( connections != NULL ); 769 assert( c != NULL ); 770 771 if ( c->c_struct_state != SLAP_C_USED ) return; 772 773 assert( c->c_conn_state != SLAP_C_INVALID ); 774 775 /* c_mutex must be locked by caller */ 776 777 if( c->c_conn_state != SLAP_C_CLOSING ) { 778 Debug( LDAP_DEBUG_CONNS, 779 "connection_closing: readying conn=%lu sd=%d for close\n", 780 c->c_connid, c->c_sd, 0 ); 781 /* update state to closing */ 782 c->c_conn_state = SLAP_C_CLOSING; 783 c->c_close_reason = why; 784 785 /* don't listen on this port anymore */ 786 slapd_clr_read( c->c_sd, 0 ); 787 788 /* abandon active operations */ 789 connection_abandon( c ); 790 791 /* wake write blocked operations */ 792 connection_wake_writers( c ); 793 794 } else if( why == NULL && c->c_close_reason == conn_lost_str ) { 795 /* Client closed connection after doing Unbind. */ 796 c->c_close_reason = NULL; 797 } 798} 799 800static void 801connection_close( Connection *c ) 802{ 803 assert( connections != NULL ); 804 assert( c != NULL ); 805 806 if ( c->c_struct_state != SLAP_C_USED ) return; 807 808 assert( c->c_conn_state == SLAP_C_CLOSING ); 809 810 /* NOTE: c_mutex should be locked by caller */ 811 812 if ( !LDAP_STAILQ_EMPTY(&c->c_ops) || 813 !LDAP_STAILQ_EMPTY(&c->c_pending_ops) ) 814 { 815 Debug( LDAP_DEBUG_CONNS, 816 "connection_close: deferring conn=%lu sd=%d\n", 817 c->c_connid, c->c_sd, 0 ); 818 return; 819 } 820 821 Debug( LDAP_DEBUG_TRACE, "connection_close: conn=%lu sd=%d\n", 822 c->c_connid, c->c_sd, 0 ); 823 824 connection_destroy( c ); 825} 826 827unsigned long connections_nextid(void) 828{ 829 unsigned long id; 830 assert( connections != NULL ); 831 832 ldap_pvt_thread_mutex_lock( &conn_nextid_mutex ); 833 834 id = conn_nextid; 835 836 ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex ); 837 838 return id; 839} 840 841Connection* connection_first( ber_socket_t *index ) 842{ 843 assert( connections != NULL ); 844 assert( index != NULL ); 845 846 ldap_pvt_thread_mutex_lock( &connections_mutex ); 847 for( *index = 0; *index < dtblsize; (*index)++) { 848 if( connections[*index].c_struct_state != SLAP_C_UNINITIALIZED ) { 849 break; 850 } 851 } 852 ldap_pvt_thread_mutex_unlock( &connections_mutex ); 853 854 return connection_next(NULL, index); 855} 856 857Connection* connection_next( Connection *c, ber_socket_t *index ) 858{ 859 assert( connections != NULL ); 860 assert( index != NULL ); 861 assert( *index <= dtblsize ); 862 863 if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex ); 864 865 c = NULL; 866 867 ldap_pvt_thread_mutex_lock( &connections_mutex ); 868 for(; *index < dtblsize; (*index)++) { 869 int c_struct; 870 if( connections[*index].c_struct_state == SLAP_C_UNINITIALIZED ) { 871 /* FIXME: accessing c_conn_state without locking c_mutex */ 872 assert( connections[*index].c_conn_state == SLAP_C_INVALID ); 873 continue; 874 } 875 876 if( connections[*index].c_struct_state == SLAP_C_USED ) { 877 c = &connections[(*index)++]; 878 if ( ldap_pvt_thread_mutex_trylock( &c->c_mutex )) { 879 /* avoid deadlock */ 880 ldap_pvt_thread_mutex_unlock( &connections_mutex ); 881 ldap_pvt_thread_mutex_lock( &c->c_mutex ); 882 ldap_pvt_thread_mutex_lock( &connections_mutex ); 883 if ( c->c_struct_state != SLAP_C_USED ) { 884 ldap_pvt_thread_mutex_unlock( &c->c_mutex ); 885 c = NULL; 886 continue; 887 } 888 } 889 assert( c->c_conn_state != SLAP_C_INVALID ); 890 break; 891 } 892 893 c_struct = connections[*index].c_struct_state; 894 if ( c_struct == SLAP_C_PENDING ) 895 continue; 896 assert( c_struct == SLAP_C_UNUSED ); 897 /* FIXME: accessing c_conn_state without locking c_mutex */ 898 assert( connections[*index].c_conn_state == SLAP_C_INVALID ); 899 } 900 901 ldap_pvt_thread_mutex_unlock( &connections_mutex ); 902 return c; 903} 904 905void connection_done( Connection *c ) 906{ 907 assert( connections != NULL ); 908 909 if( c != NULL ) ldap_pvt_thread_mutex_unlock( &c->c_mutex ); 910} 911 912/* 913 * connection_activity - handle the request operation op on connection 914 * conn. This routine figures out what kind of operation it is and 915 * calls the appropriate stub to handle it. 916 */ 917 918#ifdef SLAPD_MONITOR 919/* FIXME: returns 0 in case of failure */ 920#define INCR_OP_INITIATED(index) \ 921 do { \ 922 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \ 923 ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated_[(index)], 1); \ 924 ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \ 925 } while (0) 926#define INCR_OP_COMPLETED(index) \ 927 do { \ 928 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \ 929 ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed, 1); \ 930 ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed_[(index)], 1); \ 931 ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \ 932 } while (0) 933#else /* !SLAPD_MONITOR */ 934#define INCR_OP_INITIATED(index) do { } while (0) 935#define INCR_OP_COMPLETED(index) \ 936 do { \ 937 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); \ 938 ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_completed, 1); \ 939 ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); \ 940 } while (0) 941#endif /* !SLAPD_MONITOR */ 942 943/* 944 * NOTE: keep in sync with enum in slapd.h 945 */ 946static BI_op_func *opfun[] = { 947 do_bind, 948 do_unbind, 949 do_search, 950 do_compare, 951 do_modify, 952 do_modrdn, 953 do_add, 954 do_delete, 955 do_abandon, 956 do_extended, 957 NULL 958}; 959 960/* Counters are per-thread, not per-connection. 961 */ 962static void 963conn_counter_destroy( void *key, void *data ) 964{ 965 slap_counters_t **prev, *sc; 966 967 ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex ); 968 for ( prev = &slap_counters.sc_next, sc = slap_counters.sc_next; sc; 969 prev = &sc->sc_next, sc = sc->sc_next ) { 970 if ( sc == data ) { 971 int i; 972 973 *prev = sc->sc_next; 974 /* Copy data to main counter */ 975 ldap_pvt_mp_add( slap_counters.sc_bytes, sc->sc_bytes ); 976 ldap_pvt_mp_add( slap_counters.sc_pdu, sc->sc_pdu ); 977 ldap_pvt_mp_add( slap_counters.sc_entries, sc->sc_entries ); 978 ldap_pvt_mp_add( slap_counters.sc_refs, sc->sc_refs ); 979 ldap_pvt_mp_add( slap_counters.sc_ops_initiated, sc->sc_ops_initiated ); 980 ldap_pvt_mp_add( slap_counters.sc_ops_completed, sc->sc_ops_completed ); 981#ifdef SLAPD_MONITOR 982 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 983 ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_initiated_[ i ] ); 984 ldap_pvt_mp_add( slap_counters.sc_ops_initiated_[ i ], sc->sc_ops_completed_[ i ] ); 985 } 986#endif /* SLAPD_MONITOR */ 987 slap_counters_destroy( sc ); 988 ber_memfree_x( data, NULL ); 989 break; 990 } 991 } 992 ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex ); 993} 994 995static void 996conn_counter_init( Operation *op, void *ctx ) 997{ 998 slap_counters_t *sc; 999 void *vsc = NULL; 1000 1001 if ( ldap_pvt_thread_pool_getkey( 1002 ctx, (void *)conn_counter_init, &vsc, NULL ) || !vsc ) { 1003 vsc = ch_malloc( sizeof( slap_counters_t )); 1004 sc = vsc; 1005 slap_counters_init( sc ); 1006 ldap_pvt_thread_pool_setkey( ctx, (void*)conn_counter_init, vsc, 1007 conn_counter_destroy, NULL, NULL ); 1008 1009 ldap_pvt_thread_mutex_lock( &slap_counters.sc_mutex ); 1010 sc->sc_next = slap_counters.sc_next; 1011 slap_counters.sc_next = sc; 1012 ldap_pvt_thread_mutex_unlock( &slap_counters.sc_mutex ); 1013 } 1014 op->o_counters = vsc; 1015} 1016 1017static void * 1018connection_operation( void *ctx, void *arg_v ) 1019{ 1020 int rc = LDAP_OTHER, cancel; 1021 Operation *op = arg_v; 1022 SlapReply rs = {REP_RESULT}; 1023 ber_tag_t tag = op->o_tag; 1024 slap_op_t opidx = SLAP_OP_LAST; 1025 Connection *conn = op->o_conn; 1026 void *memctx = NULL; 1027 void *memctx_null = NULL; 1028 ber_len_t memsiz; 1029 1030 conn_counter_init( op, ctx ); 1031 ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); 1032 /* FIXME: returns 0 in case of failure */ 1033 ldap_pvt_mp_add_ulong(op->o_counters->sc_ops_initiated, 1); 1034 ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); 1035 1036 op->o_threadctx = ctx; 1037 op->o_tid = ldap_pvt_thread_pool_tid( ctx ); 1038 1039 switch ( tag ) { 1040 case LDAP_REQ_BIND: 1041 case LDAP_REQ_UNBIND: 1042 case LDAP_REQ_ADD: 1043 case LDAP_REQ_DELETE: 1044 case LDAP_REQ_MODDN: 1045 case LDAP_REQ_MODIFY: 1046 case LDAP_REQ_COMPARE: 1047 case LDAP_REQ_SEARCH: 1048 case LDAP_REQ_ABANDON: 1049 case LDAP_REQ_EXTENDED: 1050 break; 1051 default: 1052 Debug( LDAP_DEBUG_ANY, "connection_operation: " 1053 "conn %lu unknown LDAP request 0x%lx\n", 1054 conn->c_connid, tag, 0 ); 1055 op->o_tag = LBER_ERROR; 1056 rs.sr_err = LDAP_PROTOCOL_ERROR; 1057 rs.sr_text = "unknown LDAP request"; 1058 send_ldap_disconnect( op, &rs ); 1059 rc = SLAPD_DISCONNECT; 1060 goto operations_error; 1061 } 1062 1063 if( conn->c_sasl_bind_in_progress && tag != LDAP_REQ_BIND ) { 1064 Debug( LDAP_DEBUG_ANY, "connection_operation: " 1065 "error: SASL bind in progress (tag=%ld).\n", 1066 (long) tag, 0, 0 ); 1067 send_ldap_error( op, &rs, LDAP_OPERATIONS_ERROR, 1068 "SASL bind in progress" ); 1069 rc = LDAP_OPERATIONS_ERROR; 1070 goto operations_error; 1071 } 1072 1073#ifdef LDAP_X_TXN 1074 if (( conn->c_txn == CONN_TXN_SPECIFY ) && ( 1075 ( tag == LDAP_REQ_ADD ) || 1076 ( tag == LDAP_REQ_DELETE ) || 1077 ( tag == LDAP_REQ_MODIFY ) || 1078 ( tag == LDAP_REQ_MODRDN ))) 1079 { 1080 /* Disable SLAB allocator for all update operations 1081 issued inside of a transaction */ 1082 op->o_tmpmemctx = NULL; 1083 op->o_tmpmfuncs = &ch_mfuncs; 1084 } else 1085#endif 1086 { 1087 /* We can use Thread-Local storage for most mallocs. We can 1088 * also use TL for ber parsing, but not on Add or Modify. 1089 */ 1090#if 0 1091 memsiz = ber_len( op->o_ber ) * 64; 1092 if ( SLAP_SLAB_SIZE > memsiz ) memsiz = SLAP_SLAB_SIZE; 1093#endif 1094 memsiz = SLAP_SLAB_SIZE; 1095 1096 memctx = slap_sl_mem_create( memsiz, SLAP_SLAB_STACK, ctx, 1 ); 1097 op->o_tmpmemctx = memctx; 1098 op->o_tmpmfuncs = &slap_sl_mfuncs; 1099 if ( tag != LDAP_REQ_ADD && tag != LDAP_REQ_MODIFY ) { 1100 /* Note - the ber and its buffer are already allocated from 1101 * regular memory; this only affects subsequent mallocs that 1102 * ber_scanf may invoke. 1103 */ 1104 ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx ); 1105 } 1106 } 1107 1108 opidx = slap_req2op( tag ); 1109 assert( opidx != SLAP_OP_LAST ); 1110 INCR_OP_INITIATED( opidx ); 1111 rc = (*(opfun[opidx]))( op, &rs ); 1112 1113operations_error: 1114 if ( rc == SLAPD_DISCONNECT ) { 1115 tag = LBER_ERROR; 1116 1117 } else if ( opidx != SLAP_OP_LAST ) { 1118 /* increment completed operations count 1119 * only if operation was initiated 1120 * and rc != SLAPD_DISCONNECT */ 1121 INCR_OP_COMPLETED( opidx ); 1122 } 1123 1124 ldap_pvt_thread_mutex_lock( &conn->c_mutex ); 1125 1126 if ( opidx == SLAP_OP_BIND && conn->c_conn_state == SLAP_C_BINDING ) 1127 conn->c_conn_state = SLAP_C_ACTIVE; 1128 1129 cancel = op->o_cancel; 1130 if ( cancel != SLAP_CANCEL_NONE && cancel != SLAP_CANCEL_DONE ) { 1131 if ( cancel == SLAP_CANCEL_REQ ) { 1132 op->o_cancel = rc == SLAPD_ABANDON 1133 ? SLAP_CANCEL_ACK : LDAP_TOO_LATE; 1134 } 1135 1136 do { 1137 /* Fake a cond_wait with thread_yield, then 1138 * verify the result properly mutex-protected. 1139 */ 1140 ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); 1141 do { 1142 ldap_pvt_thread_yield(); 1143 } while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE 1144 && cancel != SLAP_CANCEL_DONE ); 1145 ldap_pvt_thread_mutex_lock( &conn->c_mutex ); 1146 } while ( (cancel = op->o_cancel) != SLAP_CANCEL_NONE 1147 && cancel != SLAP_CANCEL_DONE ); 1148 } 1149 1150 ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null ); 1151 1152 LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next); 1153 LDAP_STAILQ_NEXT(op, o_next) = NULL; 1154 conn->c_n_ops_executing--; 1155 conn->c_n_ops_completed++; 1156 1157 switch( tag ) { 1158 case LBER_ERROR: 1159 case LDAP_REQ_UNBIND: 1160 /* c_mutex is locked */ 1161 connection_closing( conn, 1162 tag == LDAP_REQ_UNBIND ? NULL : "operations error" ); 1163 break; 1164 } 1165 1166 connection_resched( conn ); 1167 ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); 1168 slap_op_free( op, ctx ); 1169 return NULL; 1170} 1171 1172static const Listener dummy_list = { BER_BVC(""), BER_BVC("") }; 1173 1174Connection *connection_client_setup( 1175 ber_socket_t s, 1176 ldap_pvt_thread_start_t *func, 1177 void *arg ) 1178{ 1179 Connection *c; 1180 ber_socket_t sfd = SLAP_SOCKNEW( s ); 1181 1182 c = connection_init( sfd, (Listener *)&dummy_list, "", "", 1183 CONN_IS_CLIENT, 0, NULL 1184 LDAP_PF_LOCAL_SENDMSG_ARG(NULL)); 1185 if ( c ) { 1186 c->c_clientfunc = func; 1187 c->c_clientarg = arg; 1188 1189 slapd_add_internal( sfd, 0 ); 1190 } 1191 return c; 1192} 1193 1194void connection_client_enable( 1195 Connection *c ) 1196{ 1197 slapd_set_read( c->c_sd, 1 ); 1198} 1199 1200void connection_client_stop( 1201 Connection *c ) 1202{ 1203 Sockbuf *sb; 1204 ber_socket_t s = c->c_sd; 1205 1206 /* get (locked) connection */ 1207 c = connection_get( s ); 1208 1209 assert( c->c_conn_state == SLAP_C_CLIENT ); 1210 1211 c->c_listener = NULL; 1212 c->c_conn_state = SLAP_C_INVALID; 1213 c->c_struct_state = SLAP_C_UNUSED; 1214 c->c_sd = AC_SOCKET_INVALID; 1215 c->c_close_reason = "?"; /* should never be needed */ 1216 sb = c->c_sb; 1217 c->c_sb = ber_sockbuf_alloc( ); 1218 { 1219 ber_len_t max = sockbuf_max_incoming; 1220 ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_SET_MAX_INCOMING, &max ); 1221 } 1222 slapd_remove( s, sb, 0, 1, 0 ); 1223 1224 connection_return( c ); 1225} 1226 1227static int connection_read( ber_socket_t s, conn_readinfo *cri ); 1228 1229static void* connection_read_thread( void* ctx, void* argv ) 1230{ 1231 int rc ; 1232 conn_readinfo cri = { NULL, NULL, NULL, NULL, 0 }; 1233 ber_socket_t s = (long)argv; 1234 1235 /* 1236 * read incoming LDAP requests. If there is more than one, 1237 * the first one is returned with new_op 1238 */ 1239 cri.ctx = ctx; 1240 if( ( rc = connection_read( s, &cri ) ) < 0 ) { 1241 Debug( LDAP_DEBUG_CONNS, "connection_read(%d) error\n", s, 0, 0 ); 1242 return (void*)(long)rc; 1243 } 1244 1245 /* execute a single queued request in the same thread */ 1246 if( cri.op && !cri.nullop ) { 1247 rc = (long)connection_operation( ctx, cri.op ); 1248 } else if ( cri.func ) { 1249 rc = (long)cri.func( ctx, cri.arg ); 1250 } 1251 1252 return (void*)(long)rc; 1253} 1254 1255int connection_read_activate( ber_socket_t s ) 1256{ 1257 int rc; 1258 1259 /* 1260 * suspend reading on this file descriptor until a connection processing 1261 * thread reads data on it. Otherwise the listener thread will repeatedly 1262 * submit the same event on it to the pool. 1263 */ 1264 rc = slapd_clr_read( s, 0 ); 1265 if ( rc ) 1266 return rc; 1267 1268 /* Don't let blocked writers block a pause request */ 1269 if ( connections[s].c_writewaiter && 1270 ldap_pvt_thread_pool_pausing( &connection_pool )) 1271 connection_wake_writers( &connections[s] ); 1272 1273 rc = ldap_pvt_thread_pool_submit( &connection_pool, 1274 connection_read_thread, (void *)(long)s ); 1275 1276 if( rc != 0 ) { 1277 Debug( LDAP_DEBUG_ANY, 1278 "connection_read_activate(%d): submit failed (%d)\n", 1279 s, rc, 0 ); 1280 } 1281 1282 return rc; 1283} 1284 1285static int 1286connection_read( ber_socket_t s, conn_readinfo *cri ) 1287{ 1288 int rc = 0; 1289 Connection *c; 1290 1291 assert( connections != NULL ); 1292 1293 /* get (locked) connection */ 1294 c = connection_get( s ); 1295 1296 if( c == NULL ) { 1297 Debug( LDAP_DEBUG_ANY, 1298 "connection_read(%ld): no connection!\n", 1299 (long) s, 0, 0 ); 1300 1301 return -1; 1302 } 1303 1304 c->c_n_read++; 1305 1306 if( c->c_conn_state == SLAP_C_CLOSING ) { 1307 Debug( LDAP_DEBUG_CONNS, 1308 "connection_read(%d): closing, ignoring input for id=%lu\n", 1309 s, c->c_connid, 0 ); 1310 connection_return( c ); 1311 return 0; 1312 } 1313 1314 if ( c->c_conn_state == SLAP_C_CLIENT ) { 1315 cri->func = c->c_clientfunc; 1316 cri->arg = c->c_clientarg; 1317 /* read should already be cleared */ 1318 connection_return( c ); 1319 return 0; 1320 } 1321 1322 Debug( LDAP_DEBUG_TRACE, 1323 "connection_read(%d): checking for input on id=%lu\n", 1324 s, c->c_connid, 0 ); 1325 1326#ifdef HAVE_TLS 1327 if ( c->c_is_tls && c->c_needs_tls_accept ) { 1328 rc = ldap_pvt_tls_accept( c->c_sb, slap_tls_ctx ); 1329 if ( rc < 0 ) { 1330 Debug( LDAP_DEBUG_TRACE, 1331 "connection_read(%d): TLS accept failure " 1332 "error=%d id=%lu, closing\n", 1333 s, rc, c->c_connid ); 1334 1335 c->c_needs_tls_accept = 0; 1336 /* c_mutex is locked */ 1337 connection_closing( c, "TLS negotiation failure" ); 1338 connection_close( c ); 1339 connection_return( c ); 1340 return 0; 1341 1342 } else if ( rc == 0 ) { 1343 void *ssl; 1344 struct berval authid = BER_BVNULL; 1345 1346 c->c_needs_tls_accept = 0; 1347 1348 /* we need to let SASL know */ 1349 ssl = ldap_pvt_tls_sb_ctx( c->c_sb ); 1350 1351 c->c_tls_ssf = (slap_ssf_t) ldap_pvt_tls_get_strength( ssl ); 1352 if( c->c_tls_ssf > c->c_ssf ) { 1353 c->c_ssf = c->c_tls_ssf; 1354 } 1355 1356 rc = dnX509peerNormalize( ssl, &authid ); 1357 if ( rc != LDAP_SUCCESS ) { 1358 Debug( LDAP_DEBUG_TRACE, "connection_read(%d): " 1359 "unable to get TLS client DN, error=%d id=%lu\n", 1360 s, rc, c->c_connid ); 1361 } 1362 Statslog( LDAP_DEBUG_STATS, 1363 "conn=%lu fd=%d TLS established tls_ssf=%u ssf=%u\n", 1364 c->c_connid, (int) s, c->c_tls_ssf, c->c_ssf, 0 ); 1365 slap_sasl_external( c, c->c_tls_ssf, &authid ); 1366 if ( authid.bv_val ) free( authid.bv_val ); 1367 } else if ( rc == 1 && ber_sockbuf_ctrl( c->c_sb, 1368 LBER_SB_OPT_NEEDS_WRITE, NULL )) { /* need to retry */ 1369 slapd_set_write( s, 1 ); 1370 connection_return( c ); 1371 return 0; 1372 } 1373 1374 /* if success and data is ready, fall thru to data input loop */ 1375 if( !ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL ) ) 1376 { 1377 slapd_set_read( s, 1 ); 1378 connection_return( c ); 1379 return 0; 1380 } 1381 } 1382#endif 1383 1384#ifdef HAVE_CYRUS_SASL 1385 if ( c->c_sasl_layers ) { 1386 /* If previous layer is not removed yet, give up for now */ 1387 if ( !c->c_sasl_sockctx ) { 1388 slapd_set_read( s, 1 ); 1389 connection_return( c ); 1390 return 0; 1391 } 1392 1393 c->c_sasl_layers = 0; 1394 1395 rc = ldap_pvt_sasl_install( c->c_sb, c->c_sasl_sockctx ); 1396 if( rc != LDAP_SUCCESS ) { 1397 Debug( LDAP_DEBUG_TRACE, 1398 "connection_read(%d): SASL install error " 1399 "error=%d id=%lu, closing\n", 1400 s, rc, c->c_connid ); 1401 1402 /* c_mutex is locked */ 1403 connection_closing( c, "SASL layer install failure" ); 1404 connection_close( c ); 1405 connection_return( c ); 1406 return 0; 1407 } 1408 } 1409#endif 1410 1411#define CONNECTION_INPUT_LOOP 1 1412/* #define DATA_READY_LOOP 1 */ 1413 1414 do { 1415 /* How do we do this without getting into a busy loop ? */ 1416 rc = connection_input( c, cri ); 1417 } 1418#ifdef DATA_READY_LOOP 1419 while( !rc && ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_DATA_READY, NULL )); 1420#elif defined CONNECTION_INPUT_LOOP 1421 while(!rc); 1422#else 1423 while(0); 1424#endif 1425 1426 if( rc < 0 ) { 1427 Debug( LDAP_DEBUG_CONNS, 1428 "connection_read(%d): input error=%d id=%lu, closing.\n", 1429 s, rc, c->c_connid ); 1430 1431 /* c_mutex is locked */ 1432 connection_closing( c, conn_lost_str ); 1433 connection_close( c ); 1434 connection_return( c ); 1435 return 0; 1436 } 1437 1438 if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) { 1439 slapd_set_write( s, 0 ); 1440 } 1441 1442 slapd_set_read( s, 1 ); 1443 connection_return( c ); 1444 1445 return 0; 1446} 1447 1448static int 1449connection_input( Connection *conn , conn_readinfo *cri ) 1450{ 1451 Operation *op; 1452 ber_tag_t tag; 1453 ber_len_t len; 1454 ber_int_t msgid; 1455 BerElement *ber; 1456 int rc; 1457#ifdef LDAP_CONNECTIONLESS 1458 Sockaddr peeraddr; 1459 char *cdn = NULL; 1460#endif 1461 char *defer = NULL; 1462 void *ctx; 1463 1464 if ( conn->c_currentber == NULL && 1465 ( conn->c_currentber = ber_alloc()) == NULL ) 1466 { 1467 Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 ); 1468 return -1; 1469 } 1470 1471 sock_errset(0); 1472 1473#ifdef LDAP_CONNECTIONLESS 1474 if ( conn->c_is_udp ) { 1475 char peername[sizeof("IP=255.255.255.255:65336")]; 1476 1477 len = ber_int_sb_read(conn->c_sb, &peeraddr, sizeof(struct sockaddr)); 1478 if (len != sizeof(struct sockaddr)) return 1; 1479 1480 sprintf( peername, "IP=%s:%d", 1481 inet_ntoa( peeraddr.sa_in_addr.sin_addr ), 1482 (unsigned) ntohs( peeraddr.sa_in_addr.sin_port ) ); 1483 Statslog( LDAP_DEBUG_STATS, 1484 "conn=%lu UDP request from %s (%s) accepted.\n", 1485 conn->c_connid, peername, conn->c_sock_name.bv_val, 0, 0 ); 1486 } 1487#endif 1488 1489 tag = ber_get_next( conn->c_sb, &len, conn->c_currentber ); 1490 if ( tag != LDAP_TAG_MESSAGE ) { 1491 int err = sock_errno(); 1492 1493 if ( err != EWOULDBLOCK && err != EAGAIN ) { 1494 /* log, close and send error */ 1495 Debug( LDAP_DEBUG_TRACE, 1496 "ber_get_next on fd %d failed errno=%d (%s)\n", 1497 conn->c_sd, err, sock_errstr(err) ); 1498 ber_free( conn->c_currentber, 1 ); 1499 conn->c_currentber = NULL; 1500 1501 return -2; 1502 } 1503 return 1; 1504 } 1505 1506 ber = conn->c_currentber; 1507 conn->c_currentber = NULL; 1508 1509 if ( (tag = ber_get_int( ber, &msgid )) != LDAP_TAG_MSGID ) { 1510 /* log, close and send error */ 1511 Debug( LDAP_DEBUG_ANY, "ber_get_int returns 0x%lx\n", tag, 0, 0 ); 1512 ber_free( ber, 1 ); 1513 return -1; 1514 } 1515 1516 if ( (tag = ber_peek_tag( ber, &len )) == LBER_ERROR ) { 1517 /* log, close and send error */ 1518 Debug( LDAP_DEBUG_ANY, "ber_peek_tag returns 0x%lx\n", tag, 0, 0 ); 1519 ber_free( ber, 1 ); 1520 1521 return -1; 1522 } 1523 1524#ifdef LDAP_CONNECTIONLESS 1525 if( conn->c_is_udp ) { 1526 if( tag == LBER_OCTETSTRING ) { 1527 ber_get_stringa( ber, &cdn ); 1528 tag = ber_peek_tag(ber, &len); 1529 } 1530 if( tag != LDAP_REQ_ABANDON && tag != LDAP_REQ_SEARCH ) { 1531 Debug( LDAP_DEBUG_ANY, "invalid req for UDP 0x%lx\n", tag, 0, 0 ); 1532 ber_free( ber, 1 ); 1533 return 0; 1534 } 1535 } 1536#endif 1537 1538 if(tag == LDAP_REQ_BIND) { 1539 /* immediately abandon all existing operations upon BIND */ 1540 connection_abandon( conn ); 1541 } 1542 1543 ctx = cri->ctx; 1544 op = slap_op_alloc( ber, msgid, tag, conn->c_n_ops_received++, ctx ); 1545 1546 Debug( LDAP_DEBUG_TRACE, "op tag 0x%lx, time %ld\n", tag, 1547 (long) op->o_time, 0); 1548 1549 op->o_conn = conn; 1550 /* clear state if the connection is being reused from inactive */ 1551 if ( conn->c_conn_state == SLAP_C_INACTIVE ) { 1552 memset( &conn->c_pagedresults_state, 0, 1553 sizeof( conn->c_pagedresults_state ) ); 1554 } 1555 1556 op->o_res_ber = NULL; 1557 1558#ifdef LDAP_CONNECTIONLESS 1559 if (conn->c_is_udp) { 1560 if ( cdn ) { 1561 ber_str2bv( cdn, 0, 1, &op->o_dn ); 1562 op->o_protocol = LDAP_VERSION2; 1563 } 1564 op->o_res_ber = ber_alloc_t( LBER_USE_DER ); 1565 if (op->o_res_ber == NULL) return 1; 1566 1567 rc = ber_write( op->o_res_ber, (char *)&peeraddr, 1568 sizeof(struct sockaddr), 0 ); 1569 1570 if (rc != sizeof(struct sockaddr)) { 1571 Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 ); 1572 return 1; 1573 } 1574 1575 if (op->o_protocol == LDAP_VERSION2) { 1576 rc = ber_printf(op->o_res_ber, "{is{" /*}}*/, op->o_msgid, ""); 1577 if (rc == -1) { 1578 Debug( LDAP_DEBUG_ANY, "ber_write failed\n", 0, 0, 0 ); 1579 return rc; 1580 } 1581 } 1582 } 1583#endif /* LDAP_CONNECTIONLESS */ 1584 1585 rc = 0; 1586 1587 /* Don't process requests when the conn is in the middle of a 1588 * Bind, or if it's closing. Also, don't let any single conn 1589 * use up all the available threads, and don't execute if we're 1590 * currently blocked on output. And don't execute if there are 1591 * already pending ops, let them go first. Abandon operations 1592 * get exceptions to some, but not all, cases. 1593 */ 1594 switch( tag ){ 1595 default: 1596 /* Abandon and Unbind are exempt from these checks */ 1597 if (conn->c_conn_state == SLAP_C_CLOSING) { 1598 defer = "closing"; 1599 break; 1600 } else if (conn->c_writewaiter) { 1601 defer = "awaiting write"; 1602 break; 1603 } else if (conn->c_n_ops_pending) { 1604 defer = "pending operations"; 1605 break; 1606 } 1607 /* FALLTHRU */ 1608 case LDAP_REQ_ABANDON: 1609 /* Unbind is exempt from these checks */ 1610 if (conn->c_n_ops_executing >= connection_pool_max/2) { 1611 defer = "too many executing"; 1612 break; 1613 } else if (conn->c_conn_state == SLAP_C_BINDING) { 1614 defer = "binding"; 1615 break; 1616 } 1617 /* FALLTHRU */ 1618 case LDAP_REQ_UNBIND: 1619 break; 1620 } 1621 1622 if( defer ) { 1623 int max = conn->c_dn.bv_len 1624 ? slap_conn_max_pending_auth 1625 : slap_conn_max_pending; 1626 1627 Debug( LDAP_DEBUG_ANY, 1628 "connection_input: conn=%lu deferring operation: %s\n", 1629 conn->c_connid, defer, 0 ); 1630 conn->c_n_ops_pending++; 1631 LDAP_STAILQ_INSERT_TAIL( &conn->c_pending_ops, op, o_next ); 1632 rc = ( conn->c_n_ops_pending > max ) ? -1 : 0; 1633 1634 } else { 1635 conn->c_n_ops_executing++; 1636 1637 /* 1638 * The first op will be processed in the same thread context, 1639 * as long as there is only one op total. 1640 * Subsequent ops will be submitted to the pool by 1641 * calling connection_op_activate() 1642 */ 1643 if ( cri->op == NULL ) { 1644 /* the first incoming request */ 1645 connection_op_queue( op ); 1646 cri->op = op; 1647 } else { 1648 if ( !cri->nullop ) { 1649 cri->nullop = 1; 1650 rc = ldap_pvt_thread_pool_submit( &connection_pool, 1651 connection_operation, (void *) cri->op ); 1652 } 1653 connection_op_activate( op ); 1654 } 1655 } 1656 1657#ifdef NO_THREADS 1658 if ( conn->c_struct_state != SLAP_C_USED ) { 1659 /* connection must have got closed underneath us */ 1660 return 1; 1661 } 1662#endif 1663 1664 assert( conn->c_struct_state == SLAP_C_USED ); 1665 return rc; 1666} 1667 1668static int 1669connection_resched( Connection *conn ) 1670{ 1671 Operation *op; 1672 1673 if( conn->c_writewaiter ) 1674 return 0; 1675 1676 if( conn->c_conn_state == SLAP_C_CLOSING ) { 1677 Debug( LDAP_DEBUG_CONNS, "connection_resched: " 1678 "attempting closing conn=%lu sd=%d\n", 1679 conn->c_connid, conn->c_sd, 0 ); 1680 connection_close( conn ); 1681 return 0; 1682 } 1683 1684 if( conn->c_conn_state != SLAP_C_ACTIVE ) { 1685 /* other states need different handling */ 1686 return 0; 1687 } 1688 1689 while ((op = LDAP_STAILQ_FIRST( &conn->c_pending_ops )) != NULL) { 1690 if ( conn->c_n_ops_executing > connection_pool_max/2 ) break; 1691 1692 LDAP_STAILQ_REMOVE_HEAD( &conn->c_pending_ops, o_next ); 1693 LDAP_STAILQ_NEXT(op, o_next) = NULL; 1694 1695 /* pending operations should not be marked for abandonment */ 1696 assert(!op->o_abandon); 1697 1698 conn->c_n_ops_pending--; 1699 conn->c_n_ops_executing++; 1700 1701 connection_op_activate( op ); 1702 1703 if ( conn->c_conn_state == SLAP_C_BINDING ) break; 1704 } 1705 return 0; 1706} 1707 1708static void 1709connection_init_log_prefix( Operation *op ) 1710{ 1711 if ( op->o_connid == (unsigned long)(-1) ) { 1712 snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ), 1713 "conn=-1 op=%lu", op->o_opid ); 1714 1715 } else { 1716 snprintf( op->o_log_prefix, sizeof( op->o_log_prefix ), 1717 "conn=%lu op=%lu", op->o_connid, op->o_opid ); 1718 } 1719} 1720 1721static int connection_bind_cleanup_cb( Operation *op, SlapReply *rs ) 1722{ 1723 op->o_conn->c_sasl_bindop = NULL; 1724 1725 ch_free( op->o_callback ); 1726 op->o_callback = NULL; 1727 1728 return SLAP_CB_CONTINUE; 1729} 1730 1731static int connection_bind_cb( Operation *op, SlapReply *rs ) 1732{ 1733 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); 1734 op->o_conn->c_sasl_bind_in_progress = 1735 ( rs->sr_err == LDAP_SASL_BIND_IN_PROGRESS ); 1736 1737 /* Moved here from bind.c due to ITS#4158 */ 1738 op->o_conn->c_sasl_bindop = NULL; 1739 if ( op->orb_method == LDAP_AUTH_SASL ) { 1740 if( rs->sr_err == LDAP_SUCCESS ) { 1741 ber_dupbv(&op->o_conn->c_dn, &op->orb_edn); 1742 if( !BER_BVISEMPTY( &op->orb_edn ) ) { 1743 /* edn is always normalized already */ 1744 ber_dupbv( &op->o_conn->c_ndn, &op->o_conn->c_dn ); 1745 } 1746 op->o_tmpfree( op->orb_edn.bv_val, op->o_tmpmemctx ); 1747 BER_BVZERO( &op->orb_edn ); 1748 op->o_conn->c_authmech = op->o_conn->c_sasl_bind_mech; 1749 BER_BVZERO( &op->o_conn->c_sasl_bind_mech ); 1750 1751 op->o_conn->c_sasl_ssf = op->orb_ssf; 1752 if( op->orb_ssf > op->o_conn->c_ssf ) { 1753 op->o_conn->c_ssf = op->orb_ssf; 1754 } 1755 1756 if( !BER_BVISEMPTY( &op->o_conn->c_dn ) ) { 1757 ber_len_t max = sockbuf_max_incoming_auth; 1758 ber_sockbuf_ctrl( op->o_conn->c_sb, 1759 LBER_SB_OPT_SET_MAX_INCOMING, &max ); 1760 } 1761 1762 /* log authorization identity */ 1763 Statslog( LDAP_DEBUG_STATS, 1764 "%s BIND dn=\"%s\" mech=%s sasl_ssf=%d ssf=%d\n", 1765 op->o_log_prefix, 1766 BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val, 1767 op->o_conn->c_authmech.bv_val, 1768 op->orb_ssf, op->o_conn->c_ssf ); 1769 1770 Debug( LDAP_DEBUG_TRACE, 1771 "do_bind: SASL/%s bind: dn=\"%s\" sasl_ssf=%d\n", 1772 op->o_conn->c_authmech.bv_val, 1773 BER_BVISNULL( &op->o_conn->c_dn ) ? "<empty>" : op->o_conn->c_dn.bv_val, 1774 op->orb_ssf ); 1775 1776 } else if ( rs->sr_err != LDAP_SASL_BIND_IN_PROGRESS ) { 1777 if ( !BER_BVISNULL( &op->o_conn->c_sasl_bind_mech ) ) { 1778 free( op->o_conn->c_sasl_bind_mech.bv_val ); 1779 BER_BVZERO( &op->o_conn->c_sasl_bind_mech ); 1780 } 1781 } 1782 } 1783 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 1784 1785 ch_free( op->o_callback ); 1786 op->o_callback = NULL; 1787 1788 return SLAP_CB_CONTINUE; 1789} 1790 1791static void connection_op_queue( Operation *op ) 1792{ 1793 ber_tag_t tag = op->o_tag; 1794 1795 if (tag == LDAP_REQ_BIND) { 1796 slap_callback *sc = ch_calloc( 1, sizeof( slap_callback )); 1797 sc->sc_response = connection_bind_cb; 1798 sc->sc_cleanup = connection_bind_cleanup_cb; 1799 sc->sc_next = op->o_callback; 1800 op->o_callback = sc; 1801 op->o_conn->c_conn_state = SLAP_C_BINDING; 1802 } 1803 1804 if (!op->o_dn.bv_len) { 1805 op->o_authz = op->o_conn->c_authz; 1806 if ( BER_BVISNULL( &op->o_conn->c_sasl_authz_dn )) { 1807 ber_dupbv( &op->o_dn, &op->o_conn->c_dn ); 1808 ber_dupbv( &op->o_ndn, &op->o_conn->c_ndn ); 1809 } else { 1810 ber_dupbv( &op->o_dn, &op->o_conn->c_sasl_authz_dn ); 1811 ber_dupbv( &op->o_ndn, &op->o_conn->c_sasl_authz_dn ); 1812 } 1813 } 1814 1815 op->o_authtype = op->o_conn->c_authtype; 1816 ber_dupbv( &op->o_authmech, &op->o_conn->c_authmech ); 1817 1818 if (!op->o_protocol) { 1819 op->o_protocol = op->o_conn->c_protocol 1820 ? op->o_conn->c_protocol : LDAP_VERSION3; 1821 } 1822 1823 if (op->o_conn->c_conn_state == SLAP_C_INACTIVE && 1824 op->o_protocol > LDAP_VERSION2) 1825 { 1826 op->o_conn->c_conn_state = SLAP_C_ACTIVE; 1827 } 1828 1829 op->o_connid = op->o_conn->c_connid; 1830 connection_init_log_prefix( op ); 1831 1832 LDAP_STAILQ_INSERT_TAIL( &op->o_conn->c_ops, op, o_next ); 1833} 1834 1835static int connection_op_activate( Operation *op ) 1836{ 1837 int rc; 1838 1839 connection_op_queue( op ); 1840 1841 rc = ldap_pvt_thread_pool_submit( &connection_pool, 1842 connection_operation, (void *) op ); 1843 1844 if ( rc != 0 ) { 1845 Debug( LDAP_DEBUG_ANY, 1846 "connection_op_activate: submit failed (%d) for conn=%lu\n", 1847 rc, op->o_connid, 0 ); 1848 /* should move op to pending list */ 1849 } 1850 1851 return rc; 1852} 1853 1854int connection_write(ber_socket_t s) 1855{ 1856 Connection *c; 1857 Operation *op; 1858 1859 assert( connections != NULL ); 1860 1861 slapd_clr_write( s, 0 ); 1862 1863 c = connection_get( s ); 1864 if( c == NULL ) { 1865 Debug( LDAP_DEBUG_ANY, 1866 "connection_write(%ld): no connection!\n", 1867 (long)s, 0, 0 ); 1868 return -1; 1869 } 1870 1871#ifdef HAVE_TLS 1872 if ( c->c_is_tls && c->c_needs_tls_accept ) { 1873 connection_return( c ); 1874 connection_read_activate( s ); 1875 return 0; 1876 } 1877#endif 1878 1879 c->c_n_write++; 1880 1881 Debug( LDAP_DEBUG_TRACE, 1882 "connection_write(%d): waking output for id=%lu\n", 1883 s, c->c_connid, 0 ); 1884 ldap_pvt_thread_mutex_lock( &c->c_write2_mutex ); 1885 ldap_pvt_thread_cond_signal( &c->c_write2_cv ); 1886 ldap_pvt_thread_mutex_unlock( &c->c_write2_mutex ); 1887 1888 if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_READ, NULL ) ) { 1889 slapd_set_read( s, 1 ); 1890 } 1891 if ( ber_sockbuf_ctrl( c->c_sb, LBER_SB_OPT_NEEDS_WRITE, NULL ) ) { 1892 slapd_set_write( s, 1 ); 1893 } 1894 1895 /* If there are ops pending because of a writewaiter, 1896 * start one up. 1897 */ 1898 while ((op = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) { 1899 if ( !c->c_writewaiter ) break; 1900 if ( c->c_n_ops_executing > connection_pool_max/2 ) break; 1901 1902 LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next ); 1903 LDAP_STAILQ_NEXT(op, o_next) = NULL; 1904 1905 /* pending operations should not be marked for abandonment */ 1906 assert(!op->o_abandon); 1907 1908 c->c_n_ops_pending--; 1909 c->c_n_ops_executing++; 1910 1911 connection_op_activate( op ); 1912 1913 break; 1914 } 1915 1916 connection_return( c ); 1917 return 0; 1918} 1919 1920#ifdef LDAP_SLAPI 1921typedef struct conn_fake_extblock { 1922 void *eb_conn; 1923 void *eb_op; 1924} conn_fake_extblock; 1925 1926static void 1927connection_fake_destroy( 1928 void *key, 1929 void *data ) 1930{ 1931 Connection conn = {0}; 1932 Operation op = {0}; 1933 Opheader ohdr = {0}; 1934 1935 conn_fake_extblock *eb = data; 1936 1937 op.o_hdr = &ohdr; 1938 op.o_hdr->oh_extensions = eb->eb_op; 1939 conn.c_extensions = eb->eb_conn; 1940 op.o_conn = &conn; 1941 conn.c_connid = -1; 1942 op.o_connid = -1; 1943 1944 ber_memfree_x( eb, NULL ); 1945 slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, &op ); 1946 slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, &conn ); 1947} 1948#endif 1949 1950void 1951connection_fake_init( 1952 Connection *conn, 1953 OperationBuffer *opbuf, 1954 void *ctx ) 1955{ 1956 connection_fake_init2( conn, opbuf, ctx, 1 ); 1957} 1958 1959void 1960operation_fake_init( 1961 Connection *conn, 1962 Operation *op, 1963 void *ctx, 1964 int newmem ) 1965{ 1966 /* set memory context */ 1967 op->o_tmpmemctx = slap_sl_mem_create(SLAP_SLAB_SIZE, SLAP_SLAB_STACK, ctx, 1968 newmem ); 1969 op->o_tmpmfuncs = &slap_sl_mfuncs; 1970 op->o_threadctx = ctx; 1971 op->o_tid = ldap_pvt_thread_pool_tid( ctx ); 1972 1973 op->o_counters = &slap_counters; 1974 op->o_conn = conn; 1975 op->o_connid = op->o_conn->c_connid; 1976 connection_init_log_prefix( op ); 1977} 1978 1979 1980void 1981connection_fake_init2( 1982 Connection *conn, 1983 OperationBuffer *opbuf, 1984 void *ctx, 1985 int newmem ) 1986{ 1987 Operation *op = (Operation *) opbuf; 1988 1989 conn->c_connid = -1; 1990 conn->c_conn_idx = -1; 1991 conn->c_send_ldap_result = slap_send_ldap_result; 1992 conn->c_send_search_entry = slap_send_search_entry; 1993 conn->c_send_search_reference = slap_send_search_reference; 1994 conn->c_send_ldap_extended = slap_send_ldap_extended; 1995 conn->c_send_ldap_intermediate = slap_send_ldap_intermediate; 1996 conn->c_listener = (Listener *)&dummy_list; 1997 conn->c_peer_domain = slap_empty_bv; 1998 conn->c_peer_name = slap_empty_bv; 1999 2000 memset( opbuf, 0, sizeof( *opbuf )); 2001 op->o_hdr = &opbuf->ob_hdr; 2002 op->o_controls = opbuf->ob_controls; 2003 2004 operation_fake_init( conn, op, ctx, newmem ); 2005 2006#ifdef LDAP_SLAPI 2007 if ( slapi_plugins_used ) { 2008 conn_fake_extblock *eb; 2009 void *ebx = NULL; 2010 2011 /* Use thread keys to make sure these eventually get cleaned up */ 2012 if ( ldap_pvt_thread_pool_getkey( ctx, (void *)connection_fake_init, 2013 &ebx, NULL )) { 2014 eb = ch_malloc( sizeof( *eb )); 2015 slapi_int_create_object_extensions( SLAPI_X_EXT_CONNECTION, conn ); 2016 slapi_int_create_object_extensions( SLAPI_X_EXT_OPERATION, op ); 2017 eb->eb_conn = conn->c_extensions; 2018 eb->eb_op = op->o_hdr->oh_extensions; 2019 ldap_pvt_thread_pool_setkey( ctx, (void *)connection_fake_init, 2020 eb, connection_fake_destroy, NULL, NULL ); 2021 } else { 2022 eb = ebx; 2023 conn->c_extensions = eb->eb_conn; 2024 op->o_hdr->oh_extensions = eb->eb_op; 2025 } 2026 } 2027#endif /* LDAP_SLAPI */ 2028 2029 slap_op_time( &op->o_time, &op->o_tincr ); 2030} 2031 2032void 2033connection_assign_nextid( Connection *conn ) 2034{ 2035 ldap_pvt_thread_mutex_lock( &conn_nextid_mutex ); 2036 conn->c_connid = conn_nextid++; 2037 ldap_pvt_thread_mutex_unlock( &conn_nextid_mutex ); 2038} 2039