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