1 /* $NetBSD: daemon.c,v 1.3 2025/09/05 21:16:24 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 * Portions Copyright 2007 by Howard Chu, Symas Corporation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that this notice is preserved and that due credit is given 23 * to the University of Michigan at Ann Arbor. The name of the University 24 * may not be used to endorse or promote products derived from this 25 * software without specific prior written permission. This software 26 * is provided ``as is'' without express or implied warranty. 27 */ 28 29 #include <sys/cdefs.h> 30 __RCSID("$NetBSD: daemon.c,v 1.3 2025/09/05 21:16:24 christos Exp $"); 31 32 #include "portable.h" 33 34 #include <stdio.h> 35 36 #include <ac/ctype.h> 37 #include <ac/errno.h> 38 #include <ac/socket.h> 39 #include <ac/string.h> 40 #include <ac/time.h> 41 #include <ac/unistd.h> 42 43 #include <event2/event.h> 44 #include <event2/dns.h> 45 #include <event2/listener.h> 46 47 #include "lload.h" 48 #include "ldap_pvt_thread.h" 49 #include "lutil.h" 50 51 #include "ldap_rq.h" 52 53 #ifdef HAVE_SYSTEMD 54 #include "sd-notify.h" 55 #endif 56 57 #ifdef LDAP_PF_LOCAL 58 #include <sys/stat.h> 59 /* this should go in <ldap.h> as soon as it is accepted */ 60 #define LDAPI_MOD_URLEXT "x-mod" 61 #endif /* LDAP_PF_LOCAL */ 62 63 #ifndef BALANCER_MODULE 64 #ifdef LDAP_PF_INET6 65 int slap_inet4or6 = AF_UNSPEC; 66 #else /* ! INETv6 */ 67 int slap_inet4or6 = AF_INET; 68 #endif /* ! INETv6 */ 69 70 /* globals */ 71 time_t starttime; 72 struct runqueue_s slapd_rq; 73 74 #ifdef LDAP_TCP_BUFFER 75 int slapd_tcp_rmem; 76 int slapd_tcp_wmem; 77 #endif /* LDAP_TCP_BUFFER */ 78 79 volatile sig_atomic_t slapd_shutdown = 0; 80 volatile sig_atomic_t slapd_gentle_shutdown = 0; 81 volatile sig_atomic_t slapd_abrupt_shutdown = 0; 82 #endif /* !BALANCER_MODULE */ 83 84 static int emfile; 85 86 ldap_pvt_thread_mutex_t lload_wait_mutex; 87 ldap_pvt_thread_cond_t lload_wait_cond; 88 ldap_pvt_thread_cond_t lload_pause_cond; 89 90 #ifndef SLAPD_MAX_DAEMON_THREADS 91 #define SLAPD_MAX_DAEMON_THREADS 16 92 #endif 93 int lload_daemon_threads = 1; 94 int lload_daemon_mask; 95 96 struct event_base *listener_base = NULL; 97 LloadListener **lload_listeners = NULL; 98 static ldap_pvt_thread_t listener_tid, *daemon_tid; 99 100 #ifndef RESOLV_CONF_PATH 101 #define RESOLV_CONF_PATH "/etc/resolv.conf" 102 #endif 103 char *lload_resolvconf_path = RESOLV_CONF_PATH; 104 105 struct event_base *daemon_base = NULL; 106 struct evdns_base *dnsbase; 107 108 struct event *lload_timeout_event; 109 struct event *lload_stats_event; 110 111 /* 112 * global lload statistics. Not mutex protected to preserve performance - 113 * increment is atomic, at most we risk a bit of inconsistency 114 */ 115 lload_global_stats_t lload_stats = {}; 116 117 #ifndef SLAPD_LISTEN_BACKLOG 118 #define SLAPD_LISTEN_BACKLOG 1024 119 #endif /* ! SLAPD_LISTEN_BACKLOG */ 120 121 #define DAEMON_ID(fd) ( fd & lload_daemon_mask ) 122 123 #ifdef HAVE_WINSOCK 124 ldap_pvt_thread_mutex_t slapd_ws_mutex; 125 SOCKET *slapd_ws_sockets; 126 #define SD_READ 1 127 #define SD_WRITE 2 128 #define SD_ACTIVE 4 129 #define SD_LISTENER 8 130 #endif 131 132 #ifdef HAVE_TCPD 133 static ldap_pvt_thread_mutex_t sd_tcpd_mutex; 134 #endif /* TCP Wrappers */ 135 136 typedef struct listener_item { 137 struct evconnlistener *listener; 138 ber_socket_t fd; 139 } listener_item; 140 141 typedef struct lload_daemon_st { 142 ldap_pvt_thread_mutex_t sd_mutex; 143 144 struct event_base *base; 145 struct event *wakeup_event; 146 } lload_daemon_st; 147 148 static lload_daemon_st lload_daemon[SLAPD_MAX_DAEMON_THREADS]; 149 150 static void daemon_wakeup_cb( evutil_socket_t sig, short what, void *arg ); 151 152 static void 153 lloadd_close( ber_socket_t s ) 154 { 155 Debug( LDAP_DEBUG_CONNS, "lloadd_close: " 156 "closing fd=%ld\n", 157 (long)s ); 158 tcp_close( s ); 159 } 160 161 static void 162 lload_free_listener_addresses( struct sockaddr **sal ) 163 { 164 struct sockaddr **sap; 165 if ( sal == NULL ) return; 166 for ( sap = sal; *sap != NULL; sap++ ) 167 ch_free(*sap); 168 ch_free( sal ); 169 } 170 171 #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) 172 static int 173 get_url_perms( char **exts, mode_t *perms, int *crit ) 174 { 175 int i; 176 177 assert( exts != NULL ); 178 assert( perms != NULL ); 179 assert( crit != NULL ); 180 181 *crit = 0; 182 for ( i = 0; exts[i]; i++ ) { 183 char *type = exts[i]; 184 int c = 0; 185 186 if ( type[0] == '!' ) { 187 c = 1; 188 type++; 189 } 190 191 if ( strncasecmp( type, LDAPI_MOD_URLEXT "=", 192 sizeof(LDAPI_MOD_URLEXT "=") - 1 ) == 0 ) { 193 char *value = type + ( sizeof(LDAPI_MOD_URLEXT "=") - 1 ); 194 mode_t p = 0; 195 int j; 196 197 switch ( strlen( value ) ) { 198 case 4: 199 /* skip leading '0' */ 200 if ( value[0] != '0' ) return LDAP_OTHER; 201 value++; 202 203 case 3: 204 for ( j = 0; j < 3; j++ ) { 205 int v; 206 207 v = value[j] - '0'; 208 209 if ( v < 0 || v > 7 ) return LDAP_OTHER; 210 211 p |= v << 3 * ( 2 - j ); 212 } 213 break; 214 215 case 10: 216 for ( j = 1; j < 10; j++ ) { 217 static mode_t m[] = { 0, S_IRUSR, S_IWUSR, S_IXUSR, 218 S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, 219 S_IXOTH }; 220 static const char c[] = "-rwxrwxrwx"; 221 222 if ( value[j] == c[j] ) { 223 p |= m[j]; 224 225 } else if ( value[j] != '-' ) { 226 return LDAP_OTHER; 227 } 228 } 229 break; 230 231 default: 232 return LDAP_OTHER; 233 } 234 235 *crit = c; 236 *perms = p; 237 238 return LDAP_SUCCESS; 239 } 240 } 241 242 return LDAP_OTHER; 243 } 244 #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ 245 246 /* port = 0 indicates AF_LOCAL */ 247 static int 248 lload_get_listener_addresses( 249 const char *host, 250 unsigned short port, 251 struct sockaddr ***sal ) 252 { 253 struct sockaddr **sap; 254 255 #ifdef LDAP_PF_LOCAL 256 if ( port == 0 ) { 257 sap = *sal = ch_malloc( 2 * sizeof(void *) ); 258 259 *sap = ch_calloc( 1, sizeof(struct sockaddr_un) ); 260 sap[1] = NULL; 261 262 if ( strlen( host ) > 263 ( sizeof( ((struct sockaddr_un *)*sap)->sun_path ) - 1 ) ) { 264 Debug( LDAP_DEBUG_ANY, "lload_get_listener_addresses: " 265 "domain socket path (%s) too long in URL\n", 266 host ); 267 goto errexit; 268 } 269 270 (*sap)->sa_family = AF_LOCAL; 271 strcpy( ((struct sockaddr_un *)*sap)->sun_path, host ); 272 } else 273 #endif /* LDAP_PF_LOCAL */ 274 { 275 #ifdef HAVE_GETADDRINFO 276 struct addrinfo hints, *res, *sai; 277 int n, err; 278 char serv[7]; 279 280 memset( &hints, '\0', sizeof(hints) ); 281 hints.ai_flags = AI_PASSIVE; 282 hints.ai_socktype = SOCK_STREAM; 283 hints.ai_family = slap_inet4or6; 284 snprintf( serv, sizeof(serv), "%d", port ); 285 286 if ( (err = getaddrinfo( host, serv, &hints, &res )) ) { 287 Debug( LDAP_DEBUG_ANY, "lload_get_listener_addresses: " 288 "getaddrinfo() failed: %s\n", 289 AC_GAI_STRERROR(err) ); 290 return -1; 291 } 292 293 sai = res; 294 for ( n = 2; ( sai = sai->ai_next ) != NULL; n++ ) { 295 /* EMPTY */; 296 } 297 sap = *sal = ch_calloc( n, sizeof(void *) ); 298 299 *sap = NULL; 300 301 for ( sai = res; sai; sai = sai->ai_next ) { 302 if ( sai->ai_addr == NULL ) { 303 Debug( LDAP_DEBUG_ANY, "lload_get_listener_addresses: " 304 "getaddrinfo ai_addr is NULL?\n" ); 305 freeaddrinfo( res ); 306 goto errexit; 307 } 308 309 switch ( sai->ai_family ) { 310 #ifdef LDAP_PF_INET6 311 case AF_INET6: 312 *sap = ch_malloc( sizeof(struct sockaddr_in6) ); 313 *(struct sockaddr_in6 *)*sap = 314 *((struct sockaddr_in6 *)sai->ai_addr); 315 break; 316 #endif /* LDAP_PF_INET6 */ 317 case AF_INET: 318 *sap = ch_malloc( sizeof(struct sockaddr_in) ); 319 *(struct sockaddr_in *)*sap = 320 *((struct sockaddr_in *)sai->ai_addr); 321 break; 322 default: 323 *sap = NULL; 324 break; 325 } 326 327 if ( *sap != NULL ) { 328 (*sap)->sa_family = sai->ai_family; 329 sap++; 330 *sap = NULL; 331 } 332 } 333 334 freeaddrinfo( res ); 335 336 #else /* ! HAVE_GETADDRINFO */ 337 int i, n = 1; 338 struct in_addr in; 339 struct hostent *he = NULL; 340 341 if ( host == NULL ) { 342 in.s_addr = htonl( INADDR_ANY ); 343 344 } else if ( !inet_aton( host, &in ) ) { 345 he = gethostbyname( host ); 346 if ( he == NULL ) { 347 Debug( LDAP_DEBUG_ANY, "lload_get_listener_addresses: " 348 "invalid host %s\n", 349 host ); 350 return -1; 351 } 352 for ( n = 0; he->h_addr_list[n]; n++ ) /* empty */; 353 } 354 355 sap = *sal = ch_malloc( ( n + 1 ) * sizeof(void *) ); 356 357 for ( i = 0; i < n; i++ ) { 358 sap[i] = ch_calloc( 1, sizeof(struct sockaddr_in) ); 359 sap[i]->sa_family = AF_INET; 360 ((struct sockaddr_in *)sap[i])->sin_port = htons( port ); 361 AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, 362 he ? (struct in_addr *)he->h_addr_list[i] : &in, 363 sizeof(struct in_addr) ); 364 } 365 sap[i] = NULL; 366 #endif /* ! HAVE_GETADDRINFO */ 367 } 368 369 return 0; 370 371 errexit: 372 lload_free_listener_addresses(*sal); 373 return -1; 374 } 375 376 static int 377 lload_open_listener( 378 const char *url, 379 LDAPURLDesc *lud, 380 int *listeners, 381 int *cur ) 382 { 383 int num, tmp, rc; 384 LloadListener l; 385 LloadListener *li; 386 unsigned short port; 387 int err, addrlen = 0; 388 struct sockaddr **sal = NULL, **psal; 389 int socktype = SOCK_STREAM; /* default to COTS */ 390 ber_socket_t s; 391 char ebuf[128]; 392 393 #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) 394 /* 395 * use safe defaults 396 */ 397 int crit = 1; 398 #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ 399 400 assert( url ); 401 assert( lud ); 402 403 l.sl_url.bv_val = NULL; 404 l.sl_mute = 0; 405 l.sl_busy = 0; 406 407 #ifndef HAVE_TLS 408 if ( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) { 409 Debug( LDAP_DEBUG_ANY, "lload_open_listener: " 410 "TLS not supported (%s)\n", 411 url ); 412 ldap_free_urldesc( lud ); 413 return -1; 414 } 415 416 if ( !lud->lud_port ) lud->lud_port = LDAP_PORT; 417 418 #else /* HAVE_TLS */ 419 l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme ); 420 #endif /* HAVE_TLS */ 421 422 l.sl_is_proxied = ldap_pvt_url_scheme2proxied( lud->lud_scheme ); 423 424 #ifdef LDAP_TCP_BUFFER 425 l.sl_tcp_rmem = 0; 426 l.sl_tcp_wmem = 0; 427 #endif /* LDAP_TCP_BUFFER */ 428 429 port = (unsigned short)lud->lud_port; 430 431 tmp = ldap_pvt_url_scheme2proto( lud->lud_scheme ); 432 if ( tmp == LDAP_PROTO_IPC ) { 433 #ifdef LDAP_PF_LOCAL 434 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) { 435 err = lload_get_listener_addresses( LDAPI_SOCK, 0, &sal ); 436 } else { 437 err = lload_get_listener_addresses( lud->lud_host, 0, &sal ); 438 } 439 #else /* ! LDAP_PF_LOCAL */ 440 441 Debug( LDAP_DEBUG_ANY, "lload_open_listener: " 442 "URL scheme not supported: %s\n", 443 url ); 444 ldap_free_urldesc( lud ); 445 return -1; 446 #endif /* ! LDAP_PF_LOCAL */ 447 } else { 448 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' || 449 strcmp( lud->lud_host, "*" ) == 0 ) { 450 err = lload_get_listener_addresses( NULL, port, &sal ); 451 } else { 452 err = lload_get_listener_addresses( lud->lud_host, port, &sal ); 453 } 454 } 455 456 #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD) 457 if ( lud->lud_exts ) { 458 err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit ); 459 } else { 460 l.sl_perms = S_IRWXU | S_IRWXO; 461 } 462 #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ 463 464 ldap_free_urldesc( lud ); 465 if ( err ) { 466 lload_free_listener_addresses( sal ); 467 return -1; 468 } 469 470 /* If we got more than one address returned, we need to make space 471 * for it in the lload_listeners array. 472 */ 473 for ( num = 0; sal[num]; num++ ) /* empty */; 474 if ( num > 1 ) { 475 *listeners += num - 1; 476 lload_listeners = ch_realloc( lload_listeners, 477 ( *listeners + 1 ) * sizeof(LloadListener *) ); 478 } 479 480 psal = sal; 481 while ( *sal != NULL ) { 482 char *af; 483 switch ( (*sal)->sa_family ) { 484 case AF_INET: 485 af = "IPv4"; 486 break; 487 #ifdef LDAP_PF_INET6 488 case AF_INET6: 489 af = "IPv6"; 490 break; 491 #endif /* LDAP_PF_INET6 */ 492 #ifdef LDAP_PF_LOCAL 493 case AF_LOCAL: 494 af = "Local"; 495 break; 496 #endif /* LDAP_PF_LOCAL */ 497 default: 498 sal++; 499 continue; 500 } 501 502 s = socket( (*sal)->sa_family, socktype, 0 ); 503 if ( s == AC_SOCKET_INVALID ) { 504 int err = sock_errno(); 505 Debug( LDAP_DEBUG_ANY, "lload_open_listener: " 506 "%s socket() failed errno=%d (%s)\n", 507 af, err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 508 sal++; 509 continue; 510 } 511 ber_pvt_socket_set_nonblock( s, 1 ); 512 l.sl_sd = s; 513 514 #ifdef LDAP_PF_LOCAL 515 if ( (*sal)->sa_family == AF_LOCAL ) { 516 unlink( ((struct sockaddr_un *)*sal)->sun_path ); 517 } else 518 #endif /* LDAP_PF_LOCAL */ 519 { 520 #ifdef SO_REUSEADDR 521 /* enable address reuse */ 522 tmp = 1; 523 rc = setsockopt( 524 s, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp) ); 525 if ( rc == AC_SOCKET_ERROR ) { 526 int err = sock_errno(); 527 Debug( LDAP_DEBUG_ANY, "lload_open_listener(%ld): " 528 "setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n", 529 (long)l.sl_sd, err, 530 sock_errstr( err, ebuf, sizeof(ebuf) ) ); 531 } 532 #endif /* SO_REUSEADDR */ 533 } 534 535 switch ( (*sal)->sa_family ) { 536 case AF_INET: 537 addrlen = sizeof(struct sockaddr_in); 538 break; 539 #ifdef LDAP_PF_INET6 540 case AF_INET6: 541 #ifdef IPV6_V6ONLY 542 /* Try to use IPv6 sockets for IPv6 only */ 543 tmp = 1; 544 rc = setsockopt( s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&tmp, 545 sizeof(tmp) ); 546 if ( rc == AC_SOCKET_ERROR ) { 547 int err = sock_errno(); 548 Debug( LDAP_DEBUG_ANY, "lload_open_listener(%ld): " 549 "setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n", 550 (long)l.sl_sd, err, 551 sock_errstr( err, ebuf, sizeof(ebuf) ) ); 552 } 553 #endif /* IPV6_V6ONLY */ 554 addrlen = sizeof(struct sockaddr_in6); 555 break; 556 #endif /* LDAP_PF_INET6 */ 557 558 #ifdef LDAP_PF_LOCAL 559 case AF_LOCAL: 560 #ifdef LOCAL_CREDS 561 { 562 int one = 1; 563 setsockopt( s, 0, LOCAL_CREDS, &one, sizeof(one) ); 564 } 565 #endif /* LOCAL_CREDS */ 566 567 addrlen = sizeof(struct sockaddr_un); 568 break; 569 #endif /* LDAP_PF_LOCAL */ 570 } 571 572 #ifdef LDAP_PF_LOCAL 573 /* create socket with all permissions set for those systems 574 * that honor permissions on sockets (e.g. Linux); typically, 575 * only write is required. To exploit filesystem permissions, 576 * place the socket in a directory and use directory's 577 * permissions. Need write perms to the directory to 578 * create/unlink the socket; likely need exec perms to access 579 * the socket (ITS#4709) */ 580 { 581 mode_t old_umask = 0; 582 583 if ( (*sal)->sa_family == AF_LOCAL ) { 584 old_umask = umask( 0 ); 585 } 586 #endif /* LDAP_PF_LOCAL */ 587 rc = bind( s, *sal, addrlen ); 588 #ifdef LDAP_PF_LOCAL 589 if ( old_umask != 0 ) { 590 umask( old_umask ); 591 } 592 } 593 #endif /* LDAP_PF_LOCAL */ 594 if ( rc ) { 595 err = sock_errno(); 596 Debug( LDAP_DEBUG_ANY, "lload_open_listener: " 597 "bind(%ld) failed errno=%d (%s)\n", 598 (long)l.sl_sd, err, 599 sock_errstr( err, ebuf, sizeof(ebuf) ) ); 600 tcp_close( s ); 601 sal++; 602 continue; 603 } 604 605 switch ( (*sal)->sa_family ) { 606 #ifdef LDAP_PF_LOCAL 607 case AF_LOCAL: { 608 char *path = ((struct sockaddr_un *)*sal)->sun_path; 609 l.sl_name.bv_len = strlen( path ) + STRLENOF("PATH="); 610 l.sl_name.bv_val = ch_malloc( l.sl_name.bv_len + 1 ); 611 snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, "PATH=%s", 612 path ); 613 } break; 614 #endif /* LDAP_PF_LOCAL */ 615 616 case AF_INET: { 617 char addr[INET_ADDRSTRLEN]; 618 const char *s; 619 #if defined(HAVE_GETADDRINFO) && defined(HAVE_INET_NTOP) 620 s = inet_ntop( AF_INET, 621 &((struct sockaddr_in *)*sal)->sin_addr, addr, 622 sizeof(addr) ); 623 #else /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ 624 s = inet_ntoa( ((struct sockaddr_in *)*sal)->sin_addr ); 625 #endif /* ! HAVE_GETADDRINFO || ! HAVE_INET_NTOP */ 626 if ( !s ) s = SLAP_STRING_UNKNOWN; 627 port = ntohs( ((struct sockaddr_in *)*sal)->sin_port ); 628 l.sl_name.bv_val = 629 ch_malloc( sizeof("IP=255.255.255.255:65535") ); 630 snprintf( l.sl_name.bv_val, 631 sizeof("IP=255.255.255.255:65535"), "IP=%s:%d", s, 632 port ); 633 l.sl_name.bv_len = strlen( l.sl_name.bv_val ); 634 } break; 635 636 #ifdef LDAP_PF_INET6 637 case AF_INET6: { 638 char addr[INET6_ADDRSTRLEN]; 639 const char *s; 640 s = inet_ntop( AF_INET6, 641 &((struct sockaddr_in6 *)*sal)->sin6_addr, addr, 642 sizeof(addr) ); 643 if ( !s ) s = SLAP_STRING_UNKNOWN; 644 port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port ); 645 l.sl_name.bv_len = strlen( s ) + sizeof("IP=[]:65535"); 646 l.sl_name.bv_val = ch_malloc( l.sl_name.bv_len ); 647 snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=[%s]:%d", s, 648 port ); 649 l.sl_name.bv_len = strlen( l.sl_name.bv_val ); 650 } break; 651 #endif /* LDAP_PF_INET6 */ 652 653 default: 654 Debug( LDAP_DEBUG_ANY, "lload_open_listener: " 655 "unsupported address family (%d)\n", 656 (int)(*sal)->sa_family ); 657 break; 658 } 659 660 AC_MEMCPY( &l.sl_sa, *sal, addrlen ); 661 ber_str2bv( url, 0, 1, &l.sl_url ); 662 li = ch_malloc( sizeof(LloadListener) ); 663 *li = l; 664 lload_listeners[*cur] = li; 665 (*cur)++; 666 sal++; 667 } 668 669 lload_free_listener_addresses( psal ); 670 671 if ( l.sl_url.bv_val == NULL ) { 672 Debug( LDAP_DEBUG_ANY, "lload_open_listener: " 673 "failed on %s\n", 674 url ); 675 return -1; 676 } 677 678 Debug( LDAP_DEBUG_TRACE, "lload_open_listener: " 679 "listener initialized %s\n", 680 l.sl_url.bv_val ); 681 682 return 0; 683 } 684 685 int 686 lload_open_new_listener( const char *url, LDAPURLDesc *lud ) 687 { 688 int rc, i, j = 0; 689 690 for ( i = 0; lload_listeners && lload_listeners[i] != NULL; 691 i++ ) /* count */ 692 ; 693 j = i; 694 695 i++; 696 lload_listeners = ch_realloc( 697 lload_listeners, ( i + 1 ) * sizeof(LloadListener *) ); 698 699 rc = lload_open_listener( url, lud, &i, &j ); 700 lload_listeners[j] = NULL; 701 return rc; 702 } 703 704 int lloadd_inited = 0; 705 706 int 707 lloadd_listeners_init( const char *urls ) 708 { 709 int i, j, n; 710 char **u; 711 LDAPURLDesc *lud; 712 713 Debug( LDAP_DEBUG_ARGS, "lloadd_listeners_init: %s\n", 714 urls ? urls : "<null>" ); 715 716 #ifdef HAVE_TCPD 717 ldap_pvt_thread_mutex_init( &sd_tcpd_mutex ); 718 #endif /* TCP Wrappers */ 719 720 if ( urls == NULL ) urls = "ldap:///"; 721 722 u = ldap_str2charray( urls, " " ); 723 724 if ( u == NULL || u[0] == NULL ) { 725 Debug( LDAP_DEBUG_ANY, "lloadd_listeners_init: " 726 "no urls (%s) provided\n", 727 urls ); 728 if ( u ) ldap_charray_free( u ); 729 return -1; 730 } 731 732 for ( i = 0; u[i] != NULL; i++ ) { 733 Debug( LDAP_DEBUG_TRACE, "lloadd_listeners_init: " 734 "listen on %s\n", 735 u[i] ); 736 } 737 738 if ( i == 0 ) { 739 Debug( LDAP_DEBUG_ANY, "lloadd_listeners_init: " 740 "no listeners to open (%s)\n", 741 urls ); 742 ldap_charray_free( u ); 743 return -1; 744 } 745 746 Debug( LDAP_DEBUG_TRACE, "lloadd_listeners_init: " 747 "%d listeners to open...\n", 748 i ); 749 lload_listeners = ch_malloc( ( i + 1 ) * sizeof(LloadListener *) ); 750 751 for ( n = 0, j = 0; u[n]; n++ ) { 752 if ( ldap_url_parse_ext( u[n], &lud, LDAP_PVT_URL_PARSE_DEF_PORT ) ) { 753 Debug( LDAP_DEBUG_ANY, "lloadd_listeners_init: " 754 "could not parse url %s\n", 755 u[n] ); 756 ldap_charray_free( u ); 757 return -1; 758 } 759 760 if ( lload_open_listener( u[n], lud, &i, &j ) ) { 761 ldap_charray_free( u ); 762 return -1; 763 } 764 } 765 lload_listeners[j] = NULL; 766 767 Debug( LDAP_DEBUG_TRACE, "lloadd_listeners_init: " 768 "%d listeners opened\n", 769 i ); 770 771 ldap_charray_free( u ); 772 773 return !i; 774 } 775 776 int 777 lloadd_daemon_destroy( void ) 778 { 779 epoch_shutdown(); 780 if ( lloadd_inited ) { 781 int i; 782 783 for ( i = 0; i < lload_daemon_threads; i++ ) { 784 ldap_pvt_thread_mutex_destroy( &lload_daemon[i].sd_mutex ); 785 if ( lload_daemon[i].wakeup_event ) { 786 event_free( lload_daemon[i].wakeup_event ); 787 } 788 if ( lload_daemon[i].base ) { 789 event_base_free( lload_daemon[i].base ); 790 } 791 } 792 793 event_free( lload_stats_event ); 794 event_free( lload_timeout_event ); 795 796 event_base_free( daemon_base ); 797 daemon_base = NULL; 798 799 lloadd_inited = 0; 800 #ifdef HAVE_TCPD 801 ldap_pvt_thread_mutex_destroy( &sd_tcpd_mutex ); 802 #endif /* TCP Wrappers */ 803 } 804 805 return 0; 806 } 807 808 static void 809 destroy_listeners( void ) 810 { 811 LloadListener *lr, **ll = lload_listeners; 812 813 if ( ll == NULL ) return; 814 815 ldap_pvt_thread_join( listener_tid, (void *)NULL ); 816 817 while ( (lr = *ll++) != NULL ) { 818 if ( lr->sl_url.bv_val ) { 819 ber_memfree( lr->sl_url.bv_val ); 820 } 821 822 if ( lr->sl_name.bv_val ) { 823 ber_memfree( lr->sl_name.bv_val ); 824 } 825 826 #ifdef LDAP_PF_LOCAL 827 if ( lr->sl_sa.sa_addr.sa_family == AF_LOCAL ) { 828 unlink( lr->sl_sa.sa_un_addr.sun_path ); 829 } 830 #endif /* LDAP_PF_LOCAL */ 831 832 evconnlistener_free( lr->listener ); 833 834 free( lr ); 835 } 836 837 free( lload_listeners ); 838 lload_listeners = NULL; 839 840 if ( listener_base ) { 841 event_base_free( listener_base ); 842 } 843 } 844 845 static void 846 lload_listener( 847 struct evconnlistener *listener, 848 ber_socket_t s, 849 struct sockaddr *a, 850 int len, 851 void *arg ) 852 { 853 LloadListener *sl = arg; 854 LloadConnection *c; 855 Sockaddr *from = (Sockaddr *)a; 856 char peername[LDAP_IPADDRLEN]; 857 struct berval peerbv = BER_BVC(peername); 858 int cflag; 859 int tid; 860 char ebuf[128]; 861 862 Debug( LDAP_DEBUG_TRACE, ">>> lload_listener(%s)\n", sl->sl_url.bv_val ); 863 864 peername[0] = '\0'; 865 866 /* Resume the listener FD to allow concurrent-processing of 867 * additional incoming connections. 868 */ 869 sl->sl_busy = 0; 870 871 tid = DAEMON_ID(s); 872 873 Debug( LDAP_DEBUG_CONNS, "lload_listener: " 874 "listen=%ld, new connection fd=%ld\n", 875 (long)sl->sl_sd, (long)s ); 876 877 #if defined(SO_KEEPALIVE) || defined(TCP_NODELAY) 878 #ifdef LDAP_PF_LOCAL 879 /* for IPv4 and IPv6 sockets only */ 880 if ( from->sa_addr.sa_family != AF_LOCAL ) 881 #endif /* LDAP_PF_LOCAL */ 882 { 883 int rc; 884 int tmp; 885 #ifdef SO_KEEPALIVE 886 /* enable keep alives */ 887 tmp = 1; 888 rc = setsockopt( 889 s, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp) ); 890 if ( rc == AC_SOCKET_ERROR ) { 891 int err = sock_errno(); 892 Debug( LDAP_DEBUG_ANY, "lload_listener(%ld): " 893 "setsockopt(SO_KEEPALIVE) failed errno=%d (%s)\n", 894 (long)s, err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 895 } 896 #endif /* SO_KEEPALIVE */ 897 #ifdef TCP_NODELAY 898 /* enable no delay */ 899 tmp = 1; 900 rc = setsockopt( 901 s, IPPROTO_TCP, TCP_NODELAY, (char *)&tmp, sizeof(tmp) ); 902 if ( rc == AC_SOCKET_ERROR ) { 903 int err = sock_errno(); 904 Debug( LDAP_DEBUG_ANY, "lload_listener(%ld): " 905 "setsockopt(TCP_NODELAY) failed errno=%d (%s)\n", 906 (long)s, err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 907 } 908 #endif /* TCP_NODELAY */ 909 } 910 #endif /* SO_KEEPALIVE || TCP_NODELAY */ 911 912 if ( sl->sl_is_proxied ) { 913 if ( !proxyp( s, from ) ) { 914 Debug( LDAP_DEBUG_ANY, "lload_listener: " 915 "proxyp(%ld) failed\n", 916 (long)s ); 917 lloadd_close( s ); 918 return; 919 } 920 } 921 922 cflag = 0; 923 switch ( from->sa_addr.sa_family ) { 924 #ifdef LDAP_PF_LOCAL 925 case AF_LOCAL: 926 cflag |= CONN_IS_IPC; 927 928 /* FIXME: apparently accept doesn't fill the sun_path member */ 929 sprintf( peername, "PATH=%s", sl->sl_sa.sa_un_addr.sun_path ); 930 break; 931 #endif /* LDAP_PF_LOCAL */ 932 933 #ifdef LDAP_PF_INET6 934 case AF_INET6: 935 #endif /* LDAP_PF_INET6 */ 936 case AF_INET: 937 ldap_pvt_sockaddrstr( from, &peerbv ); 938 break; 939 940 default: 941 lloadd_close( s ); 942 return; 943 } 944 945 #ifdef HAVE_TLS 946 if ( sl->sl_is_tls ) cflag |= CONN_IS_TLS; 947 #endif 948 c = client_init( s, peername, lload_daemon[tid].base, cflag ); 949 950 if ( !c ) { 951 Debug( LDAP_DEBUG_ANY, "lload_listener: " 952 "client_init(%ld, %s, %s) failed\n", 953 (long)s, peername, sl->sl_name.bv_val ); 954 lloadd_close( s ); 955 } 956 957 return; 958 } 959 960 static void * 961 lload_listener_thread( void *ctx ) 962 { 963 /* ITS#9984 Survive the listeners being paused if we run out of fds */ 964 int rc = event_base_loop( listener_base, EVLOOP_NO_EXIT_ON_EMPTY ); 965 Debug( LDAP_DEBUG_ANY, "lload_listener_thread: " 966 "event loop finished: rc=%d\n", 967 rc ); 968 969 return (void *)NULL; 970 } 971 972 static void 973 listener_error_cb( struct evconnlistener *lev, void *arg ) 974 { 975 LloadListener *l = arg; 976 int err = EVUTIL_SOCKET_ERROR(); 977 978 assert( l->listener == lev ); 979 if ( 980 #ifdef EMFILE 981 err == EMFILE || 982 #endif /* EMFILE */ 983 #ifdef ENFILE 984 err == ENFILE || 985 #endif /* ENFILE */ 986 0 ) { 987 ldap_pvt_thread_mutex_lock( &lload_daemon[0].sd_mutex ); 988 emfile++; 989 /* Stop listening until an existing session closes */ 990 l->sl_mute = 1; 991 evconnlistener_disable( lev ); 992 ldap_pvt_thread_mutex_unlock( &lload_daemon[0].sd_mutex ); 993 Debug( LDAP_DEBUG_ANY, "listener_error_cb: " 994 "too many open files, cannot accept new connections on " 995 "url=%s\n", 996 l->sl_url.bv_val ); 997 } else { 998 char ebuf[128]; 999 Debug( LDAP_DEBUG_ANY, "listener_error_cb: " 1000 "received an error on a listener, shutting down: '%s'\n", 1001 sock_errstr( err, ebuf, sizeof(ebuf) ) ); 1002 event_base_loopexit( l->base, NULL ); 1003 } 1004 } 1005 1006 void 1007 listeners_reactivate( void ) 1008 { 1009 int i; 1010 1011 ldap_pvt_thread_mutex_lock( &lload_daemon[0].sd_mutex ); 1012 for ( i = 0; emfile && lload_listeners[i] != NULL; i++ ) { 1013 LloadListener *lr = lload_listeners[i]; 1014 1015 if ( lr->sl_sd == AC_SOCKET_INVALID ) continue; 1016 if ( lr->sl_mute ) { 1017 emfile--; 1018 evconnlistener_enable( lr->listener ); 1019 lr->sl_mute = 0; 1020 Debug( LDAP_DEBUG_CONNS, "listeners_reactivate: " 1021 "reactivated listener url=%s\n", 1022 lr->sl_url.bv_val ); 1023 } 1024 } 1025 if ( emfile && lload_listeners[i] == NULL ) { 1026 /* Walked the entire list without enabling anything; emfile 1027 * counter is stale. Reset it. */ 1028 emfile = 0; 1029 } 1030 ldap_pvt_thread_mutex_unlock( &lload_daemon[0].sd_mutex ); 1031 } 1032 1033 static int 1034 lload_listener_activate( void ) 1035 { 1036 struct evconnlistener *listener; 1037 int l, rc; 1038 char ebuf[128]; 1039 1040 listener_base = event_base_new(); 1041 if ( !listener_base ) return -1; 1042 1043 for ( l = 0; lload_listeners[l] != NULL; l++ ) { 1044 if ( lload_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; 1045 1046 /* FIXME: TCP-only! */ 1047 #ifdef LDAP_TCP_BUFFER 1048 if ( 1 ) { 1049 int origsize, size, realsize, rc; 1050 socklen_t optlen; 1051 1052 size = 0; 1053 if ( lload_listeners[l]->sl_tcp_rmem > 0 ) { 1054 size = lload_listeners[l]->sl_tcp_rmem; 1055 } else if ( slapd_tcp_rmem > 0 ) { 1056 size = slapd_tcp_rmem; 1057 } 1058 1059 if ( size > 0 ) { 1060 optlen = sizeof(origsize); 1061 rc = getsockopt( lload_listeners[l]->sl_sd, SOL_SOCKET, 1062 SO_RCVBUF, (void *)&origsize, &optlen ); 1063 1064 if ( rc ) { 1065 int err = sock_errno(); 1066 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1067 "getsockopt(SO_RCVBUF) failed errno=%d (%s)\n", 1068 err, AC_STRERROR_R( err, ebuf, sizeof(ebuf) ) ); 1069 } 1070 1071 optlen = sizeof(size); 1072 rc = setsockopt( lload_listeners[l]->sl_sd, SOL_SOCKET, 1073 SO_RCVBUF, (const void *)&size, optlen ); 1074 1075 if ( rc ) { 1076 int err = sock_errno(); 1077 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1078 "setsockopt(SO_RCVBUF) failed errno=%d (%s)\n", 1079 err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 1080 } 1081 1082 optlen = sizeof(realsize); 1083 rc = getsockopt( lload_listeners[l]->sl_sd, SOL_SOCKET, 1084 SO_RCVBUF, (void *)&realsize, &optlen ); 1085 1086 if ( rc ) { 1087 int err = sock_errno(); 1088 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1089 "getsockopt(SO_RCVBUF) failed errno=%d (%s)\n", 1090 err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 1091 } 1092 1093 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1094 "url=%s (#%d) RCVBUF original size=%d requested " 1095 "size=%d real size=%d\n", 1096 lload_listeners[l]->sl_url.bv_val, l, origsize, size, 1097 realsize ); 1098 } 1099 1100 size = 0; 1101 if ( lload_listeners[l]->sl_tcp_wmem > 0 ) { 1102 size = lload_listeners[l]->sl_tcp_wmem; 1103 } else if ( slapd_tcp_wmem > 0 ) { 1104 size = slapd_tcp_wmem; 1105 } 1106 1107 if ( size > 0 ) { 1108 optlen = sizeof(origsize); 1109 rc = getsockopt( lload_listeners[l]->sl_sd, SOL_SOCKET, 1110 SO_SNDBUF, (void *)&origsize, &optlen ); 1111 1112 if ( rc ) { 1113 int err = sock_errno(); 1114 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1115 "getsockopt(SO_SNDBUF) failed errno=%d (%s)\n", 1116 err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 1117 } 1118 1119 optlen = sizeof(size); 1120 rc = setsockopt( lload_listeners[l]->sl_sd, SOL_SOCKET, 1121 SO_SNDBUF, (const void *)&size, optlen ); 1122 1123 if ( rc ) { 1124 int err = sock_errno(); 1125 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1126 "setsockopt(SO_SNDBUF) failed errno=%d (%s)\n", 1127 err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 1128 } 1129 1130 optlen = sizeof(realsize); 1131 rc = getsockopt( lload_listeners[l]->sl_sd, SOL_SOCKET, 1132 SO_SNDBUF, (void *)&realsize, &optlen ); 1133 1134 if ( rc ) { 1135 int err = sock_errno(); 1136 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1137 "getsockopt(SO_SNDBUF) failed errno=%d (%s)\n", 1138 err, sock_errstr( err, ebuf, sizeof(ebuf) ) ); 1139 } 1140 1141 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1142 "url=%s (#%d) SNDBUF original size=%d requested " 1143 "size=%d real size=%d\n", 1144 lload_listeners[l]->sl_url.bv_val, l, origsize, size, 1145 realsize ); 1146 } 1147 } 1148 #endif /* LDAP_TCP_BUFFER */ 1149 1150 lload_listeners[l]->sl_busy = 1; 1151 listener = evconnlistener_new( listener_base, lload_listener, 1152 lload_listeners[l], 1153 LEV_OPT_THREADSAFE|LEV_OPT_DEFERRED_ACCEPT, 1154 SLAPD_LISTEN_BACKLOG, lload_listeners[l]->sl_sd ); 1155 if ( !listener ) { 1156 int err = sock_errno(); 1157 1158 #ifdef LDAP_PF_INET6 1159 /* If error is EADDRINUSE, we are trying to listen to INADDR_ANY and 1160 * we are already listening to in6addr_any, then we want to ignore 1161 * this and continue. 1162 */ 1163 if ( err == EADDRINUSE ) { 1164 int i; 1165 struct sockaddr_in sa = lload_listeners[l]->sl_sa.sa_in_addr; 1166 struct sockaddr_in6 sa6; 1167 1168 if ( sa.sin_family == AF_INET && 1169 sa.sin_addr.s_addr == htonl( INADDR_ANY ) ) { 1170 for ( i = 0; i < l; i++ ) { 1171 sa6 = lload_listeners[i]->sl_sa.sa_in6_addr; 1172 if ( sa6.sin6_family == AF_INET6 && 1173 !memcmp( &sa6.sin6_addr, &in6addr_any, 1174 sizeof(struct in6_addr) ) ) { 1175 break; 1176 } 1177 } 1178 1179 if ( i < l ) { 1180 /* We are already listening to in6addr_any */ 1181 Debug( LDAP_DEBUG_CONNS, "lload_listener_activate: " 1182 "Attempt to listen to 0.0.0.0 failed, " 1183 "already listening on ::, assuming IPv4 " 1184 "included\n" ); 1185 lloadd_close( lload_listeners[l]->sl_sd ); 1186 lload_listeners[l]->sl_sd = AC_SOCKET_INVALID; 1187 continue; 1188 } 1189 } 1190 } 1191 #endif /* LDAP_PF_INET6 */ 1192 Debug( LDAP_DEBUG_ANY, "lload_listener_activate: " 1193 "listen(%s, 5) failed errno=%d (%s)\n", 1194 lload_listeners[l]->sl_url.bv_val, err, 1195 sock_errstr( err, ebuf, sizeof(ebuf) ) ); 1196 return -1; 1197 } 1198 1199 lload_listeners[l]->base = listener_base; 1200 lload_listeners[l]->listener = listener; 1201 evconnlistener_set_error_cb( listener, listener_error_cb ); 1202 } 1203 1204 rc = ldap_pvt_thread_create( 1205 &listener_tid, 0, lload_listener_thread, lload_listeners[l] ); 1206 1207 if ( rc != 0 ) { 1208 Debug( LDAP_DEBUG_ANY, "lload_listener_activate(%d): " 1209 "submit failed (%d)\n", 1210 lload_listeners[l]->sl_sd, rc ); 1211 } 1212 return rc; 1213 } 1214 1215 static void * 1216 lloadd_io_task( void *ptr ) 1217 { 1218 int rc; 1219 int tid = (ldap_pvt_thread_t *)ptr - daemon_tid; 1220 struct event_base *base = lload_daemon[tid].base; 1221 struct event *event; 1222 1223 event = event_new( base, -1, EV_WRITE, daemon_wakeup_cb, ptr ); 1224 if ( !event ) { 1225 Debug( LDAP_DEBUG_ANY, "lloadd_io_task: " 1226 "failed to set up the wakeup event\n" ); 1227 return (void *)-1; 1228 } 1229 event_add( event, NULL ); 1230 lload_daemon[tid].wakeup_event = event; 1231 1232 /* run */ 1233 rc = event_base_dispatch( base ); 1234 Debug( LDAP_DEBUG_ANY, "lloadd_io_task: " 1235 "Daemon %d, event loop finished: rc=%d\n", 1236 tid, rc ); 1237 1238 if ( !slapd_gentle_shutdown ) { 1239 slapd_abrupt_shutdown = 1; 1240 } 1241 1242 return NULL; 1243 } 1244 1245 int 1246 lloadd_daemon( struct event_base *daemon_base ) 1247 { 1248 int i, rc; 1249 LloadTier *tier; 1250 struct event_base *base; 1251 struct event *event; 1252 struct timeval second = { 1, 0 }; 1253 1254 assert( daemon_base != NULL ); 1255 1256 dnsbase = evdns_base_new( daemon_base, 0 ); 1257 if ( !dnsbase ) { 1258 Debug( LDAP_DEBUG_ANY, "lloadd startup: " 1259 "failed to set up for async name resolution\n" ); 1260 return -1; 1261 } 1262 1263 /* 1264 * ITS#10070: Allow both operation without working DNS (test environments) 1265 * and e.g. containers that don't have a /etc/resolv.conf but do have a 1266 * server listening on 127.0.0.1 which is the default. 1267 */ 1268 (void)evdns_base_resolv_conf_parse( dnsbase, 1269 DNS_OPTION_NAMESERVERS|DNS_OPTION_HOSTSFILE, 1270 lload_resolvconf_path ); 1271 1272 if ( lload_daemon_threads > SLAPD_MAX_DAEMON_THREADS ) 1273 lload_daemon_threads = SLAPD_MAX_DAEMON_THREADS; 1274 1275 daemon_tid = 1276 ch_malloc( lload_daemon_threads * sizeof(ldap_pvt_thread_t) ); 1277 1278 for ( i = 0; i < lload_daemon_threads; i++ ) { 1279 base = event_base_new(); 1280 if ( !base ) { 1281 Debug( LDAP_DEBUG_ANY, "lloadd startup: " 1282 "failed to acquire event base for an I/O thread\n" ); 1283 return -1; 1284 } 1285 lload_daemon[i].base = base; 1286 1287 ldap_pvt_thread_mutex_init( &lload_daemon[i].sd_mutex ); 1288 /* threads that handle client and upstream sockets */ 1289 rc = ldap_pvt_thread_create( 1290 &daemon_tid[i], 0, lloadd_io_task, &daemon_tid[i] ); 1291 1292 if ( rc != 0 ) { 1293 Debug( LDAP_DEBUG_ANY, "lloadd startup: " 1294 "listener ldap_pvt_thread_create failed (%d)\n", 1295 rc ); 1296 return rc; 1297 } 1298 } 1299 1300 if ( (rc = lload_listener_activate()) != 0 ) { 1301 return rc; 1302 } 1303 1304 LDAP_STAILQ_FOREACH ( tier, &tiers, t_next ) { 1305 if ( tier->t_type.tier_startup( tier ) ) { 1306 return -1; 1307 } 1308 } 1309 1310 event = event_new( daemon_base, -1, EV_TIMEOUT|EV_PERSIST, 1311 lload_tiers_update, NULL ); 1312 if ( !event ) { 1313 Debug( LDAP_DEBUG_ANY, "lloadd: " 1314 "failed to allocate stats update event\n" ); 1315 return -1; 1316 } 1317 lload_stats_event = event; 1318 event_add( event, &second ); 1319 1320 event = evtimer_new( daemon_base, operations_timeout, event_self_cbarg() ); 1321 if ( !event ) { 1322 Debug( LDAP_DEBUG_ANY, "lloadd: " 1323 "failed to allocate timeout event\n" ); 1324 return -1; 1325 } 1326 lload_timeout_event = event; 1327 1328 /* TODO: should we just add it with any timeout and re-add when the timeout 1329 * changes? */ 1330 if ( lload_timeout_api ) { 1331 event_add( event, lload_timeout_api ); 1332 } 1333 1334 checked_lock( &lload_wait_mutex ); 1335 lloadd_inited = 1; 1336 ldap_pvt_thread_cond_signal( &lload_wait_cond ); 1337 checked_unlock( &lload_wait_mutex ); 1338 #if !defined(BALANCER_MODULE) && defined(HAVE_SYSTEMD) 1339 rc = sd_notify( 1, "READY=1" ); 1340 if ( rc < 0 ) { 1341 Debug( LDAP_DEBUG_ANY, "lloadd startup: " 1342 "systemd sd_notify failed (%d)\n", rc ); 1343 } 1344 #endif /* !BALANCER_MODULE && HAVE_SYSTEMD */ 1345 1346 rc = event_base_dispatch( daemon_base ); 1347 Debug( LDAP_DEBUG_ANY, "lloadd shutdown: " 1348 "Main event loop finished: rc=%d\n", 1349 rc ); 1350 1351 /* shutdown */ 1352 event_base_loopexit( listener_base, 0 ); 1353 1354 /* wait for the listener threads to complete */ 1355 destroy_listeners(); 1356 1357 /* Mark upstream connections closing and prevent from opening new ones */ 1358 lload_tiers_shutdown(); 1359 1360 /* Do the same for clients */ 1361 clients_destroy( 1 ); 1362 1363 for ( i = 0; i < lload_daemon_threads; i++ ) { 1364 /* 1365 * https://github.com/libevent/libevent/issues/623 1366 * deleting the event doesn't notify the base, just activate it and 1367 * let it delete itself 1368 */ 1369 event_active( lload_daemon[i].wakeup_event, EV_READ, 0 ); 1370 } 1371 1372 for ( i = 0; i < lload_daemon_threads; i++ ) { 1373 ldap_pvt_thread_join( daemon_tid[i], (void *)NULL ); 1374 } 1375 1376 #ifndef BALANCER_MODULE 1377 if ( LogTest( LDAP_DEBUG_ANY ) ) { 1378 int t = ldap_pvt_thread_pool_backload( &connection_pool ); 1379 Debug( LDAP_DEBUG_ANY, "lloadd shutdown: " 1380 "waiting for %d operations/tasks to finish\n", 1381 t ); 1382 } 1383 ldap_pvt_thread_pool_close( &connection_pool, 1 ); 1384 #endif 1385 1386 lload_tiers_destroy(); 1387 clients_destroy( 0 ); 1388 lload_bindconf_free( &bindconf ); 1389 evdns_base_free( dnsbase, 0 ); 1390 1391 ch_free( daemon_tid ); 1392 daemon_tid = NULL; 1393 1394 lloadd_daemon_destroy(); 1395 1396 /* If we're a slapd module, let the thread that initiated the shut down 1397 * know we've finished */ 1398 checked_lock( &lload_wait_mutex ); 1399 ldap_pvt_thread_cond_signal( &lload_wait_cond ); 1400 checked_unlock( &lload_wait_mutex ); 1401 1402 return 0; 1403 } 1404 1405 static void 1406 daemon_wakeup_cb( evutil_socket_t sig, short what, void *arg ) 1407 { 1408 int tid = (ldap_pvt_thread_t *)arg - daemon_tid; 1409 1410 Debug( LDAP_DEBUG_TRACE, "daemon_wakeup_cb: " 1411 "Daemon thread %d woken up\n", 1412 tid ); 1413 event_del( lload_daemon[tid].wakeup_event ); 1414 } 1415 1416 LloadChange lload_change = { .type = LLOAD_CHANGE_UNDEFINED }; 1417 1418 #ifdef BALANCER_MODULE 1419 int 1420 backend_conn_cb( ldap_pvt_thread_start_t *start, void *startarg, void *arg ) 1421 { 1422 LloadConnection *c = startarg; 1423 LloadBackend *b = arg; 1424 1425 if ( b == NULL || c->c_backend == b ) { 1426 CONNECTION_LOCK_DESTROY(c); 1427 return 1; 1428 } 1429 return 0; 1430 } 1431 1432 #ifdef HAVE_TLS 1433 int 1434 client_tls_cb( ldap_pvt_thread_start_t *start, void *startarg, void *arg ) 1435 { 1436 LloadConnection *c = startarg; 1437 1438 if ( c->c_destroy == client_destroy && 1439 c->c_is_tls == LLOAD_TLS_ESTABLISHED ) { 1440 CONNECTION_LOCK_DESTROY(c); 1441 return 1; 1442 } 1443 return 0; 1444 } 1445 #endif /* HAVE_TLS */ 1446 1447 static int 1448 detach_linked_backend_cb( LloadConnection *client, LloadBackend *b ) 1449 { 1450 int rc = LDAP_SUCCESS; 1451 1452 if ( client->c_backend != b ) { 1453 return rc; 1454 } 1455 1456 Debug( LDAP_DEBUG_CONNS, "detach_linked_backend_cb: " 1457 "detaching backend '%s' from connid=%lu%s\n", 1458 b->b_name.bv_val, client->c_connid, 1459 client->c_restricted == LLOAD_OP_RESTRICTED_BACKEND ? 1460 " and closing the connection" : 1461 "" ); 1462 1463 /* We were approached from the connection list */ 1464 assert( IS_ALIVE( client, c_refcnt ) ); 1465 1466 assert( client->c_restricted == LLOAD_OP_RESTRICTED_WRITE || 1467 client->c_restricted == LLOAD_OP_RESTRICTED_BACKEND ); 1468 if ( client->c_restricted == LLOAD_OP_RESTRICTED_BACKEND ) { 1469 int gentle = 1; 1470 CONNECTION_LOCK(client); 1471 rc = lload_connection_close( client, &gentle ); 1472 CONNECTION_UNLOCK(client); 1473 } 1474 1475 client->c_restricted = LLOAD_OP_NOT_RESTRICTED; 1476 client->c_restricted_at = 0; 1477 client->c_restricted_inflight = 0; 1478 1479 return rc; 1480 } 1481 1482 void 1483 lload_handle_backend_invalidation( LloadChange *change ) 1484 { 1485 LloadBackend *b = change->target; 1486 LloadTier *tier = b->b_tier; 1487 1488 assert( change->object == LLOAD_BACKEND ); 1489 1490 if ( change->type == LLOAD_CHANGE_ADD ) { 1491 BackendInfo *mi = backend_info( "monitor" ); 1492 1493 if ( mi ) { 1494 monitor_extra_t *mbe = mi->bi_extra; 1495 if ( mbe->is_configured() ) { 1496 lload_monitor_backend_init( mi, tier->t_monitor, b ); 1497 } 1498 } 1499 1500 if ( tier->t_type.tier_change ) { 1501 tier->t_type.tier_change( tier, change ); 1502 } 1503 1504 checked_lock( &b->b_mutex ); 1505 backend_retry( b ); 1506 checked_unlock( &b->b_mutex ); 1507 return; 1508 } else if ( change->type == LLOAD_CHANGE_DEL ) { 1509 ldap_pvt_thread_pool_walk( 1510 &connection_pool, handle_pdus, backend_conn_cb, b ); 1511 ldap_pvt_thread_pool_walk( 1512 &connection_pool, upstream_bind, backend_conn_cb, b ); 1513 1514 checked_lock( &clients_mutex ); 1515 connections_walk( 1516 &clients_mutex, &clients, 1517 (CONNCB)detach_linked_backend_cb, b ); 1518 checked_unlock( &clients_mutex ); 1519 1520 if ( tier->t_type.tier_change ) { 1521 tier->t_type.tier_change( tier, change ); 1522 } 1523 lload_backend_destroy( b ); 1524 return; 1525 } 1526 assert( change->type == LLOAD_CHANGE_MODIFY ); 1527 1528 /* 1529 * A change that can't be handled gracefully, terminate all connections and 1530 * start over. 1531 */ 1532 if ( change->flags.backend & LLOAD_BACKEND_MOD_OTHER ) { 1533 ldap_pvt_thread_pool_walk( 1534 &connection_pool, handle_pdus, backend_conn_cb, b ); 1535 ldap_pvt_thread_pool_walk( 1536 &connection_pool, upstream_bind, backend_conn_cb, b ); 1537 checked_lock( &b->b_mutex ); 1538 backend_reset( b, 0 ); 1539 backend_retry( b ); 1540 checked_unlock( &b->b_mutex ); 1541 return; 1542 } 1543 1544 /* 1545 * Handle changes to number of connections: 1546 * - a change might get the connection limit above the pool size: 1547 * - consider closing (in order of priority?): 1548 * - connections awaiting connect() completion 1549 * - connections currently preparing 1550 * - bind connections over limit (which is 0 if 'feature vc' is on 1551 * - regular connections over limit 1552 * - below pool size 1553 * - call backend_retry if there are no opening connections 1554 * - one pool size above and one below the configured size 1555 * - still close the ones above limit, it should sort itself out 1556 * the only issue is if a closing connection isn't guaranteed to do 1557 * that at some point 1558 */ 1559 if ( change->flags.backend & LLOAD_BACKEND_MOD_CONNS ) { 1560 int bind_requested = 0, need_close = 0, need_open = 0; 1561 LloadConnection *c; 1562 1563 bind_requested = 1564 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS 1565 (lload_features & LLOAD_FEATURE_VC) ? 0 : 1566 #endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */ 1567 b->b_numbindconns; 1568 1569 if ( b->b_bindavail > bind_requested ) { 1570 need_close += b->b_bindavail - bind_requested; 1571 } else if ( b->b_bindavail < bind_requested ) { 1572 need_open = 1; 1573 } 1574 1575 if ( b->b_active > b->b_numconns ) { 1576 need_close += b->b_active - b->b_numconns; 1577 } else if ( b->b_active < b->b_numconns ) { 1578 need_open = 1; 1579 } 1580 1581 if ( !need_open ) { 1582 need_close += b->b_opening; 1583 1584 while ( !LDAP_LIST_EMPTY( &b->b_connecting ) ) { 1585 LloadPendingConnection *p = LDAP_LIST_FIRST( &b->b_connecting ); 1586 1587 LDAP_LIST_REMOVE( p, next ); 1588 event_free( p->event ); 1589 evutil_closesocket( p->fd ); 1590 ch_free( p ); 1591 b->b_opening--; 1592 need_close--; 1593 } 1594 } 1595 1596 if ( need_close || !need_open ) { 1597 /* It might be too late to repurpose a preparing connection, just 1598 * close them all */ 1599 while ( !LDAP_CIRCLEQ_EMPTY( &b->b_preparing ) ) { 1600 c = LDAP_CIRCLEQ_FIRST( &b->b_preparing ); 1601 1602 event_del( c->c_read_event ); 1603 CONNECTION_LOCK_DESTROY(c); 1604 assert( c == NULL ); 1605 b->b_opening--; 1606 need_close--; 1607 } 1608 if ( event_pending( b->b_retry_event, EV_TIMEOUT, NULL ) ) { 1609 event_del( b->b_retry_event ); 1610 b->b_opening--; 1611 } 1612 assert( b->b_opening == 0 ); 1613 } 1614 1615 if ( b->b_bindavail > bind_requested ) { 1616 int diff = b->b_bindavail - bind_requested; 1617 1618 assert( need_close >= diff ); 1619 1620 LDAP_CIRCLEQ_FOREACH ( c, &b->b_bindconns, c_next ) { 1621 int gentle = 1; 1622 1623 lload_connection_close( c, &gentle ); 1624 need_close--; 1625 diff--; 1626 if ( !diff ) { 1627 break; 1628 } 1629 } 1630 assert( diff == 0 ); 1631 } 1632 1633 if ( b->b_active > b->b_numconns ) { 1634 int diff = b->b_active - b->b_numconns; 1635 1636 assert( need_close >= diff ); 1637 1638 LDAP_CIRCLEQ_FOREACH ( c, &b->b_conns, c_next ) { 1639 int gentle = 1; 1640 1641 lload_connection_close( c, &gentle ); 1642 need_close--; 1643 diff--; 1644 if ( !diff ) { 1645 break; 1646 } 1647 } 1648 assert( diff == 0 ); 1649 } 1650 assert( need_close == 0 ); 1651 1652 if ( need_open ) { 1653 checked_lock( &b->b_mutex ); 1654 backend_retry( b ); 1655 checked_unlock( &b->b_mutex ); 1656 } 1657 } 1658 } 1659 1660 void 1661 lload_handle_tier_invalidation( LloadChange *change ) 1662 { 1663 LloadTier *tier; 1664 1665 assert( change->object == LLOAD_TIER ); 1666 tier = change->target; 1667 1668 if ( change->type == LLOAD_CHANGE_ADD ) { 1669 BackendInfo *mi = backend_info( "monitor" ); 1670 1671 if ( mi ) { 1672 monitor_extra_t *mbe = mi->bi_extra; 1673 if ( mbe->is_configured() ) { 1674 lload_monitor_tier_init( mi, tier ); 1675 } 1676 } 1677 1678 tier->t_type.tier_startup( tier ); 1679 if ( LDAP_STAILQ_EMPTY( &tiers ) ) { 1680 LDAP_STAILQ_INSERT_HEAD( &tiers, tier, t_next ); 1681 } else { 1682 LDAP_STAILQ_INSERT_TAIL( &tiers, tier, t_next ); 1683 } 1684 return; 1685 } else if ( change->type == LLOAD_CHANGE_DEL ) { 1686 LDAP_STAILQ_REMOVE( &tiers, tier, LloadTier, t_next ); 1687 tier->t_type.tier_reset( tier, 1 ); 1688 tier->t_type.tier_destroy( tier ); 1689 return; 1690 } 1691 assert( change->type == LLOAD_CHANGE_MODIFY ); 1692 1693 if ( tier->t_type.tier_change ) { 1694 tier->t_type.tier_change( tier, change ); 1695 } 1696 } 1697 1698 void 1699 lload_handle_global_invalidation( LloadChange *change ) 1700 { 1701 assert( change->type == LLOAD_CHANGE_MODIFY ); 1702 assert( change->object == LLOAD_DAEMON ); 1703 1704 if ( change->flags.daemon & LLOAD_DAEMON_MOD_THREADS ) { 1705 /* walk the task queue to remove any tasks belonging to us. */ 1706 /* TODO: initiate a full module restart, everything will fall into 1707 * place at that point */ 1708 ldap_pvt_thread_pool_walk( 1709 &connection_pool, handle_pdus, backend_conn_cb, NULL ); 1710 ldap_pvt_thread_pool_walk( 1711 &connection_pool, upstream_bind, backend_conn_cb, NULL ); 1712 assert(0); 1713 return; 1714 } 1715 1716 if ( change->flags.daemon & LLOAD_DAEMON_MOD_FEATURES ) { 1717 lload_features_t feature_diff = 1718 lload_features ^ ( ~(uintptr_t)change->target ); 1719 /* Feature change handling: 1720 * - VC (TODO): 1721 * - on: terminate all bind connections 1722 * - off: cancel all bind operations in progress, reopen bind connections 1723 * - ProxyAuthz: 1724 * - on: nothing needed 1725 * - off: clear c_auth/privileged on each client 1726 * - read pause (WIP): 1727 * - nothing needed? 1728 */ 1729 1730 assert( change->target ); 1731 if ( feature_diff & LLOAD_FEATURE_VC ) { 1732 assert(0); 1733 feature_diff &= ~LLOAD_FEATURE_VC; 1734 } 1735 if ( feature_diff & LLOAD_FEATURE_PAUSE ) { 1736 feature_diff &= ~LLOAD_FEATURE_PAUSE; 1737 } 1738 if ( feature_diff & LLOAD_FEATURE_PROXYAUTHZ ) { 1739 if ( !(lload_features & LLOAD_FEATURE_PROXYAUTHZ) ) { 1740 LloadConnection *c; 1741 /* We switched proxyauthz off */ 1742 LDAP_CIRCLEQ_FOREACH ( c, &clients, c_next ) { 1743 if ( !BER_BVISNULL( &c->c_auth ) ) { 1744 ber_memfree( c->c_auth.bv_val ); 1745 BER_BVZERO( &c->c_auth ); 1746 } 1747 if ( c->c_type == LLOAD_C_PRIVILEGED ) { 1748 c->c_type = LLOAD_C_OPEN; 1749 } 1750 } 1751 } 1752 feature_diff &= ~LLOAD_FEATURE_PROXYAUTHZ; 1753 } 1754 assert( !feature_diff ); 1755 } 1756 1757 #ifdef HAVE_TLS 1758 if ( change->flags.daemon & LLOAD_DAEMON_MOD_TLS ) { 1759 /* terminate all clients with TLS set up */ 1760 ldap_pvt_thread_pool_walk( 1761 &connection_pool, handle_pdus, client_tls_cb, NULL ); 1762 if ( !LDAP_CIRCLEQ_EMPTY( &clients ) ) { 1763 LloadConnection *c = LDAP_CIRCLEQ_FIRST( &clients ); 1764 unsigned long first_connid = c->c_connid; 1765 1766 while ( c ) { 1767 LloadConnection *next = 1768 LDAP_CIRCLEQ_LOOP_NEXT( &clients, c, c_next ); 1769 if ( c->c_is_tls ) { 1770 CONNECTION_LOCK_DESTROY(c); 1771 assert( c == NULL ); 1772 } 1773 c = next; 1774 if ( c->c_connid <= first_connid ) { 1775 c = NULL; 1776 } 1777 } 1778 } 1779 } 1780 #endif /* HAVE_TLS */ 1781 1782 if ( change->flags.daemon & LLOAD_DAEMON_MOD_BINDCONF ) { 1783 LloadConnection *c; 1784 1785 /* 1786 * Only timeout changes can be handled gracefully, terminate all 1787 * connections and start over. 1788 */ 1789 ldap_pvt_thread_pool_walk( 1790 &connection_pool, handle_pdus, backend_conn_cb, NULL ); 1791 ldap_pvt_thread_pool_walk( 1792 &connection_pool, upstream_bind, backend_conn_cb, NULL ); 1793 1794 lload_tiers_reset( 0 ); 1795 1796 /* Reconsider the PRIVILEGED flag on all clients */ 1797 LDAP_CIRCLEQ_FOREACH ( c, &clients, c_next ) { 1798 int privileged = ber_bvstrcasecmp( &c->c_auth, &lloadd_identity ); 1799 1800 /* We have just terminated all pending operations (even pins), there 1801 * should be no connections still binding/closing */ 1802 assert( c->c_state == LLOAD_C_READY ); 1803 1804 c->c_type = privileged ? LLOAD_C_PRIVILEGED : LLOAD_C_OPEN; 1805 } 1806 } 1807 } 1808 1809 int 1810 lload_handle_invalidation( LloadChange *change ) 1811 { 1812 if ( (change->type == LLOAD_CHANGE_MODIFY) && 1813 change->flags.generic == 0 ) { 1814 Debug( LDAP_DEBUG_ANY, "lload_handle_invalidation: " 1815 "a modify where apparently nothing changed\n" ); 1816 } 1817 1818 switch ( change->object ) { 1819 case LLOAD_BACKEND: 1820 lload_handle_backend_invalidation( change ); 1821 break; 1822 case LLOAD_TIER: 1823 lload_handle_tier_invalidation( change ); 1824 break; 1825 case LLOAD_DAEMON: 1826 lload_handle_global_invalidation( change ); 1827 break; 1828 default: 1829 Debug( LDAP_DEBUG_ANY, "lload_handle_invalidation: " 1830 "unrecognised change\n" ); 1831 assert(0); 1832 } 1833 1834 return LDAP_SUCCESS; 1835 } 1836 1837 static void 1838 lload_pause_event_cb( evutil_socket_t s, short what, void *arg ) 1839 { 1840 /* 1841 * We are pausing, signal the pausing thread we've finished and 1842 * wait until the thread pool resumes operation. 1843 * 1844 * Do this in lockstep with the pausing thread. 1845 */ 1846 checked_lock( &lload_wait_mutex ); 1847 ldap_pvt_thread_cond_signal( &lload_wait_cond ); 1848 1849 /* Now wait until we unpause, then we can resume operation */ 1850 ldap_pvt_thread_cond_wait( &lload_pause_cond, &lload_wait_mutex ); 1851 checked_unlock( &lload_wait_mutex ); 1852 } 1853 1854 /* 1855 * Signal the event base to terminate processing as soon as it can and wait for 1856 * lload_pause_event_cb to notify us this has happened. 1857 */ 1858 static int 1859 lload_pause_base( struct event_base *base ) 1860 { 1861 int rc; 1862 1863 checked_lock( &lload_wait_mutex ); 1864 event_base_once( base, -1, EV_TIMEOUT, lload_pause_event_cb, base, NULL ); 1865 rc = ldap_pvt_thread_cond_wait( &lload_wait_cond, &lload_wait_mutex ); 1866 checked_unlock( &lload_wait_mutex ); 1867 1868 return rc; 1869 } 1870 1871 void 1872 lload_pause_server( void ) 1873 { 1874 LloadChange ch = { .type = LLOAD_CHANGE_UNDEFINED }; 1875 int i; 1876 1877 lload_pause_base( listener_base ); 1878 lload_pause_base( daemon_base ); 1879 1880 for ( i = 0; i < lload_daemon_threads; i++ ) { 1881 lload_pause_base( lload_daemon[i].base ); 1882 } 1883 1884 lload_change = ch; 1885 } 1886 1887 void 1888 lload_unpause_server( void ) 1889 { 1890 if ( lload_change.type != LLOAD_CHANGE_UNDEFINED ) { 1891 lload_handle_invalidation( &lload_change ); 1892 } 1893 1894 /* 1895 * Make sure lloadd is completely ready to unpause by now: 1896 * 1897 * After the broadcast, we handle I/O and begin filling the thread pool, in 1898 * high load conditions, we might hit the pool limits and start processing 1899 * operations in the I/O threads (one PDU per socket at a time for fairness 1900 * sake) even before a pause has finished from slapd's point of view! 1901 * 1902 * When (max_pdus_per_cycle == 0) we don't use the pool for these at all and 1903 * most lload processing starts immediately making this even more prominent. 1904 */ 1905 ldap_pvt_thread_cond_broadcast( &lload_pause_cond ); 1906 } 1907 #endif /* BALANCER_MODULE */ 1908 1909 void 1910 lload_sig_shutdown( evutil_socket_t sig, short what, void *arg ) 1911 { 1912 struct event_base *daemon_base = arg; 1913 int save_errno = errno; 1914 int i; 1915 1916 /* 1917 * If the NT Service Manager is controlling the server, we don't 1918 * want SIGBREAK to kill the server. For some strange reason, 1919 * SIGBREAK is generated when a user logs out. 1920 */ 1921 1922 #if defined(HAVE_NT_SERVICE_MANAGER) && defined(SIGBREAK) 1923 if ( is_NT_Service && sig == SIGBREAK ) { 1924 /* empty */; 1925 } else 1926 #endif /* HAVE_NT_SERVICE_MANAGER && SIGBREAK */ 1927 #ifdef SIGHUP 1928 if ( sig == SIGHUP && global_gentlehup && slapd_gentle_shutdown == 0 ) { 1929 slapd_gentle_shutdown = 1; 1930 } else 1931 #endif /* SIGHUP */ 1932 { 1933 slapd_shutdown = 1; 1934 } 1935 1936 for ( i = 0; i < lload_daemon_threads; i++ ) { 1937 event_base_loopexit( lload_daemon[i].base, NULL ); 1938 } 1939 event_base_loopexit( daemon_base, NULL ); 1940 1941 errno = save_errno; 1942 } 1943 1944 struct event_base * 1945 lload_get_base( ber_socket_t s ) 1946 { 1947 int tid = DAEMON_ID(s); 1948 return lload_daemon[tid].base; 1949 } 1950 1951 LloadListener ** 1952 lloadd_get_listeners( void ) 1953 { 1954 /* Could return array with no listeners if !listening, but current 1955 * callers mostly look at the URLs. E.g. syncrepl uses this to 1956 * identify the server, which means it wants the startup arguments. 1957 */ 1958 return lload_listeners; 1959 } 1960 1961 /* Reject all incoming requests */ 1962 void 1963 lload_suspend_listeners( void ) 1964 { 1965 int i; 1966 for ( i = 0; lload_listeners[i]; i++ ) { 1967 lload_listeners[i]->sl_mute = 1; 1968 evconnlistener_disable( lload_listeners[i]->listener ); 1969 listen( lload_listeners[i]->sl_sd, 0 ); 1970 } 1971 } 1972 1973 /* Resume after a suspend */ 1974 void 1975 lload_resume_listeners( void ) 1976 { 1977 int i; 1978 for ( i = 0; lload_listeners[i]; i++ ) { 1979 lload_listeners[i]->sl_mute = 0; 1980 listen( lload_listeners[i]->sl_sd, SLAPD_LISTEN_BACKLOG ); 1981 evconnlistener_enable( lload_listeners[i]->listener ); 1982 } 1983 } 1984