X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fdaemon.c;h=b4755a80b2d6ce2e002ccb90c4ace6d34982eedc;hb=6170a2bbb481e56afe3e05ca81248c99a860d427;hp=38f804466b502bc0621d29a7300463aa69fa9719;hpb=0f0122abdd9aad010fe46e89969f4462b1c1f853;p=openldap diff --git a/servers/slapd/daemon.c b/servers/slapd/daemon.c index 38f804466b..b4755a80b2 100644 --- a/servers/slapd/daemon.c +++ b/servers/slapd/daemon.c @@ -1,7 +1,26 @@ /* $OpenLDAP$ */ -/* - * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2004 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* Portions Copyright (c) 1995 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific prior written permission. This software + * is provided ``as is'' without express or implied warranty. */ #include "portable.h" @@ -15,10 +34,15 @@ #include #include -#include "ldap_pvt.h" +#include "slap.h" #include "ldap_pvt_thread.h" #include "lutil.h" -#include "slap.h" + +#include "ldap_rq.h" + +#if defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL) +#include +#endif #ifdef HAVE_TCPD #include @@ -45,31 +69,35 @@ int slap_inet4or6 = AF_INET; /* globals */ time_t starttime; ber_socket_t dtblsize; +slap_ssf_t local_ssf = LDAP_PVT_SASL_LOCAL_SSF; Listener **slap_listeners = NULL; #define SLAPD_LISTEN 10 static ber_socket_t wake_sds[2]; +static int emfile; -#if defined(NO_THREADS) || defined(HAVE_GNU_PTH) static int waking; #define WAKE_LISTENER(w) \ -((w && !waking) ? tcp_write( wake_sds[1], "0", 1 ), waking=1 : 0) -#else -#define WAKE_LISTENER(w) \ -do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0) -#endif +do { if (w && waking < 5) { waking++; tcp_write( wake_sds[1], "0", 1 ); } } while(0) -#ifndef HAVE_WINSOCK -static -#endif volatile sig_atomic_t slapd_shutdown = 0, slapd_gentle_shutdown = 0; +volatile sig_atomic_t slapd_abrupt_shutdown = 0; static struct slap_daemon { ldap_pvt_thread_mutex_t sd_mutex; ber_socket_t sd_nactives; + int sd_nwriters; + +#ifdef HAVE_EPOLL + struct epoll_event *sd_epolls; + int sd_nepolls; + int *sd_index; + int sd_epfd; + int sd_nfds; +#else #ifndef HAVE_WINSOCK /* In winsock, accept() returns values higher than dtblsize @@ -80,8 +108,196 @@ static struct slap_daemon { fd_set sd_actives; fd_set sd_readers; fd_set sd_writers; +#endif } slap_daemon; +#ifdef HAVE_EPOLL +#define SLAP_EVENTS_ARE_INDEXED 0 +#define SLAP_SOCK_IX(s) (slap_daemon.sd_index[s]) +#define SLAP_SOCK_EP(s) (slap_daemon.sd_epolls[SLAP_SOCK_IX(s)]) +#define SLAP_SOCK_EV(s) (SLAP_SOCK_EP(s).events) +#define SLAP_SOCK_IS_ACTIVE(s) (SLAP_SOCK_IX(s) != -1) +#define SLAP_SOCK_NOT_ACTIVE(s) (SLAP_SOCK_IX(s) == -1) +#define SLAP_SOCK_IS_SET(s, mode) (SLAP_SOCK_EV(s) & mode) + +#define SLAP_SOCK_IS_READ(s) SLAP_SOCK_IS_SET(s, EPOLLIN) +#define SLAP_SOCK_IS_WRITE(s) SLAP_SOCK_IS_SET(s, EPOLLOUT) + +#define SLAP_SET_SOCK(s, mode) do { \ + if ((SLAP_SOCK_EV(s) & mode) != mode) { \ + SLAP_SOCK_EV(s) |= mode; \ + epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, s, \ + &SLAP_SOCK_EP(s)); \ + } \ +} while(0) + +#define SLAP_CLR_SOCK(s, mode) do { \ + if ((SLAP_SOCK_EV(s) & mode)) { \ + SLAP_SOCK_EV(s) &= ~mode; \ + epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_MOD, s, \ + &SLAP_SOCK_EP(s)); \ + } \ +} while(0) + +#define SLAP_SOCK_SET_READ(s) SLAP_SET_SOCK(s, EPOLLIN) +#define SLAP_SOCK_SET_WRITE(s) SLAP_SET_SOCK(s, EPOLLOUT) + +#define SLAP_SOCK_CLR_READ(s) SLAP_CLR_SOCK(s, EPOLLIN) +#define SLAP_SOCK_CLR_WRITE(s) SLAP_CLR_SOCK(s, EPOLLOUT) + +#define SLAP_CLR_EVENT(i, mode) (revents[i].events &= ~mode) + + +#define SLAP_EVENT_MAX slap_daemon.sd_nfds + +/* If a Listener address is provided, store that as the epoll data. + * Otherwise, store the address of this socket's slot in the + * index array. If we can't do this add, the system is out of + * resources and we need to shutdown. + */ +#define SLAP_ADD_SOCK(s, l) do { \ + int rc; \ + SLAP_SOCK_IX(s) = slap_daemon.sd_nfds; \ + SLAP_SOCK_EP(s).data.ptr = (l) ? (l) : (void *)(&SLAP_SOCK_IX(s)); \ + SLAP_SOCK_EV(s) = EPOLLIN; \ + rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_ADD, s, \ + &SLAP_SOCK_EP(s)); \ + if ( rc == 0 ) slap_daemon.sd_nfds++; \ + else { \ + Debug( LDAP_DEBUG_ANY, "daemon: epoll_ctl ADD failed, errno %d, shutting down\n", \ + errno, 0, 0 ); \ + slapd_shutdown = 2; \ + } \ +} while(0) + +#define SLAP_EV_LISTENER(ptr) (((int *)(ptr) >= slap_daemon.sd_index && \ + (int *)(ptr) <= (slap_daemon.sd_index+dtblsize)) ? 0 : 1) + +#define SLAP_EV_PTRFD(ptr) (SLAP_EV_LISTENER(ptr) ? \ + ((Listener *)ptr)->sl_sd : (int *)(ptr) - slap_daemon.sd_index) + +#define SLAP_DEL_SOCK(s) do { \ + int fd, rc, index = SLAP_SOCK_IX(s); \ + rc = epoll_ctl(slap_daemon.sd_epfd, EPOLL_CTL_DEL, s, \ + &SLAP_SOCK_EP(s)); \ + slap_daemon.sd_epolls[index] = slap_daemon.sd_epolls[slap_daemon.sd_nfds-1]; \ + fd = SLAP_EV_PTRFD(slap_daemon.sd_epolls[index].data.ptr); \ + slap_daemon.sd_index[fd] = index; \ + slap_daemon.sd_index[s] = -1; \ + slap_daemon.sd_nfds--; \ +} while(0) + +#define SLAP_EVENT_CLR_READ(i) SLAP_CLR_EVENT(i, EPOLLIN) +#define SLAP_EVENT_CLR_WRITE(i) SLAP_CLR_EVENT(i, EPOLLOUT) + +#define SLAP_CHK_EVENT(i, mode) (revents[i].events & mode) + +#define SLAP_EVENT_IS_READ(i) SLAP_CHK_EVENT(i, EPOLLIN) +#define SLAP_EVENT_IS_WRITE(i) SLAP_CHK_EVENT(i, EPOLLOUT) +#define SLAP_EVENT_IS_LISTENER(i) SLAP_EV_LISTENER(revents[i].data.ptr) +#define SLAP_EVENT_LISTENER(i) (revents[i].data.ptr) + +#define SLAP_EVENT_FD(i) SLAP_EV_PTRFD(revents[i].data.ptr) +#define SLAP_SOCK_SET_MUTE(s) SLAP_SOCK_CLR_READ(s) +#define SLAP_SOCK_CLR_MUTE(s) SLAP_SOCK_SET_READ(s) +#define SLAP_SOCK_IS_MUTE(s) !SLAP_SOCK_IS_READ(s) + +#define SLAP_SOCK_SET_INIT \ + slap_daemon.sd_epolls = ch_malloc(sizeof(struct epoll_event) * dtblsize * 2); \ + slap_daemon.sd_index = ch_malloc(sizeof(int) * dtblsize); \ + slap_daemon.sd_epfd = epoll_create( dtblsize ); \ + for (i=0; itv_sec * 1000 : -1 ) + +#else + +/* select */ +#define SLAP_EVENTS_ARE_INDEXED 1 +#define SLAP_EVENT_DECL \ + fd_set readfds, writefds + +#define SLAP_EVENT_INIT \ + AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) ); \ + if ( nwriters ) \ + AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) ) + +#ifdef FD_SETSIZE +#define CHK_SETSIZE \ + if (dtblsize > FD_SETSIZE) dtblsize = FD_SETSIZE +#else +#define CHK_SETSIZE +#endif + +#define SLAP_SOCK_SET_INIT \ + CHK_SETSIZE; \ + FD_ZERO(&slap_daemon.sd_readers); \ + FD_ZERO(&slap_daemon.sd_writers) + +#define SLAP_SOCK_IS_ACTIVE(fd) FD_ISSET(fd, &slap_daemon.sd_actives) + +#define SLAP_SOCK_IS_READ(fd) FD_ISSET(fd, &slap_daemon.sd_readers) +#define SLAP_SOCK_IS_WRITE(fd) FD_ISSET(fd, &slap_daemon.sd_writers) + +#define SLAP_SOCK_NOT_ACTIVE(fd) (!SLAP_SOCK_IS_ACTIVE(fd) && \ + !SLAP_SOCK_IS_READ(fd) && !SLAP_SOCK_IS_WRITE(fd)) + +#ifdef HAVE_WINSOCK +#define SLAP_SOCK_SET_READ(fd) do { \ + if (!SLAP_SOCK_IS_READ(fd)) {FD_SET(fd, &slap_daemon.sd_readers);} \ +} while(0) +#define SLAP_SOCK_SET_WRITE(fd) do { \ + if (!SLAP_SOCK_IS_WRITE(fd)) {FD_SET(fd, &slap_daemon.sd_writers);} \ +} while(0) + +#define SLAP_ADDTEST(s) +#define SLAP_EVENT_MAX dtblsize +#else +#define SLAP_SOCK_SET_READ(fd) FD_SET(fd, &slap_daemon.sd_readers) +#define SLAP_SOCK_SET_WRITE(fd) FD_SET(fd, &slap_daemon.sd_writers) + +#define SLAP_EVENT_MAX slap_daemon.sd_nfds +#define SLAP_ADDTEST(s) if (s >= slap_daemon.sd_nfds) slap_daemon.sd_nfds = s+1 +#endif + +#define SLAP_SOCK_CLR_READ(fd) FD_CLR(fd, &slap_daemon.sd_readers) +#define SLAP_SOCK_CLR_WRITE(fd) FD_CLR(fd, &slap_daemon.sd_writers) + +#define SLAP_ADD_SOCK(s, l) do { \ + SLAP_ADDTEST(s); \ + FD_SET(s, &slap_daemon.sd_actives); \ + FD_SET(s, &slap_daemon.sd_readers); \ +} while(0) + +#define SLAP_DEL_SOCK(s) do { \ + FD_CLR(s, &slap_daemon.sd_actives); \ + FD_CLR(s, &slap_daemon.sd_readers); \ + FD_CLR(s, &slap_daemon.sd_writers); \ +} while(0) + +#define SLAP_EVENT_IS_READ(fd) FD_ISSET(fd, &readfds) +#define SLAP_EVENT_IS_WRITE(fd) FD_ISSET(fd, &writefds) + +#define SLAP_EVENT_CLR_READ(fd) FD_CLR(fd, &readfds) +#define SLAP_EVENT_CLR_WRITE(fd) FD_CLR(fd, &writefds) + +#define SLAP_EVENT_WAIT(tvp) \ + select( SLAP_EVENT_MAX, &readfds, \ + nwriters > 0 ? &writefds : NULL, NULL, tvp ) + +#define SLAP_SOCK_SET_MUTE(s) FD_CLR(s, &readfds) +#define SLAP_SOCK_CLR_MUTE(s) FD_SET(s, &readfds) +#define SLAP_SOCK_IS_MUTE(s) FD_ISSET(s, &readfds) + +#endif #ifdef HAVE_SLP @@ -94,6 +310,7 @@ static struct slap_daemon { #define LDAPS_SRVTYPE_PREFIX "service:ldaps://" static char** slapd_srvurls = NULL; static SLPHandle slapd_hslp = 0; +int slapd_register_slp = 0; void slapd_slp_init( const char* urls ) { int i; @@ -155,6 +372,8 @@ void slapd_slp_regreport( void slapd_slp_reg() { int i; + if( slapd_srvurls == NULL ) return; + for( i=0; slapd_srvurls[i] != NULL; i++ ) { if( strncmp( slapd_srvurls[i], LDAP_SRVTYPE_PREFIX, sizeof( LDAP_SRVTYPE_PREFIX ) - 1 ) == 0 || @@ -176,6 +395,8 @@ void slapd_slp_reg() { void slapd_slp_dereg() { int i; + if( slapd_srvurls == NULL ) return; + for( i=0; slapd_srvurls[i] != NULL; i++ ) { SLPDereg( slapd_hslp, slapd_srvurls[i], @@ -187,62 +408,70 @@ void slapd_slp_dereg() { /* * Add a descriptor to daemon control + * + * If isactive, the descriptor is a live server session and is subject + * to idletimeout control. Otherwise, the descriptor is a passive + * listener or an outbound client session, and not subject to + * idletimeout. The underlying event handler may record the Listener + * argument to differentiate Listener's from real sessions. */ -static void slapd_add(ber_socket_t s) { +static void slapd_add(ber_socket_t s, int isactive, Listener *sl) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - assert( !FD_ISSET( s, &slap_daemon.sd_actives )); - assert( !FD_ISSET( s, &slap_daemon.sd_readers )); - assert( !FD_ISSET( s, &slap_daemon.sd_writers )); + assert( SLAP_SOCK_NOT_ACTIVE(s) ); -#ifndef HAVE_WINSOCK - if (s >= slap_daemon.sd_nfds) { - slap_daemon.sd_nfds = s + 1; + if ( isactive ) { + slap_daemon.sd_nactives++; } -#endif - - slap_daemon.sd_nactives++; - FD_SET( s, &slap_daemon.sd_actives ); - FD_SET( s, &slap_daemon.sd_readers ); + SLAP_ADD_SOCK(s, sl); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL1, - "slapd_add: added %ld%s%s\n", (long)s, - FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "", - FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" ); -#else - Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n", - (long) s, - FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "", - FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" ); -#endif + Debug( LDAP_DEBUG_CONNS, "daemon: added %ldr\n", + (long) s, 0, 0 ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); } /* * Remove the descriptor from daemon control */ -void slapd_remove(ber_socket_t s, int wake) { +void slapd_remove(ber_socket_t s, int wasactive, int wake) { + int waswriter; ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - slap_daemon.sd_nactives--; + if ( wasactive ) { + slap_daemon.sd_nactives--; + } + waswriter = SLAP_SOCK_IS_WRITE(s); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL1, - "slapd_remove: removing %ld%s%s\n", (long) s, - FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "", - FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n", - (long) s, - FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "", - FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" ); -#endif - FD_CLR( s, &slap_daemon.sd_actives ); - FD_CLR( s, &slap_daemon.sd_readers ); - FD_CLR( s, &slap_daemon.sd_writers ); + (long) s, SLAP_SOCK_IS_READ(s) ? "r" : "", + waswriter ? "w" : "" ); + if ( waswriter ) slap_daemon.sd_nwriters--; + SLAP_DEL_SOCK(s); + + /* If we ran out of file descriptors, we dropped a listener from + * the select() loop. Now that we're removing a session from our + * control, we can try to resume a dropped listener to use. + */ + if ( emfile ) { + int i; + for ( i = 0; slap_listeners[i] != NULL; i++ ) { + if ( slap_listeners[i]->sl_sd != AC_SOCKET_INVALID ) { + if ( slap_listeners[i]->sl_sd == s ) continue; + if ( slap_listeners[i]->sl_is_mute ) { + slap_listeners[i]->sl_is_mute = 0; + emfile--; + break; + } + } + } + /* Walked the entire list without enabling anything; emfile + * counter is stale. Reset it. + */ + if ( slap_listeners[i] == NULL ) + emfile = 0; + } ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake || slapd_gentle_shutdown == 2); } @@ -250,8 +479,11 @@ void slapd_remove(ber_socket_t s, int wake) { void slapd_clr_write(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - assert( FD_ISSET( s, &slap_daemon.sd_actives) ); - FD_CLR( s, &slap_daemon.sd_writers ); + assert( SLAP_SOCK_IS_ACTIVE( s )); + if ( SLAP_SOCK_IS_WRITE( s )) { + SLAP_SOCK_CLR_WRITE( s ); + slap_daemon.sd_nwriters--; + } ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake); @@ -260,9 +492,11 @@ void slapd_clr_write(ber_socket_t s, int wake) { void slapd_set_write(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - assert( FD_ISSET( s, &slap_daemon.sd_actives) ); - if (!FD_ISSET(s, &slap_daemon.sd_writers)) - FD_SET( (unsigned) s, &slap_daemon.sd_writers ); + assert( SLAP_SOCK_IS_ACTIVE( s )); + if ( !SLAP_SOCK_IS_WRITE( s )) { + SLAP_SOCK_SET_WRITE( s ); + slap_daemon.sd_nwriters++; + } ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake); @@ -271,8 +505,8 @@ void slapd_set_write(ber_socket_t s, int wake) { void slapd_clr_read(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - assert( FD_ISSET( s, &slap_daemon.sd_actives) ); - FD_CLR( s, &slap_daemon.sd_readers ); + assert( SLAP_SOCK_IS_ACTIVE( s )); + SLAP_SOCK_CLR_READ( s ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake); @@ -281,21 +515,17 @@ void slapd_clr_read(ber_socket_t s, int wake) { void slapd_set_read(ber_socket_t s, int wake) { ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - assert( FD_ISSET( s, &slap_daemon.sd_actives) ); - if (!FD_ISSET(s, &slap_daemon.sd_readers)) - FD_SET( s, &slap_daemon.sd_readers ); + assert( SLAP_SOCK_IS_ACTIVE( s )); + if (!SLAP_SOCK_IS_READ( s )) + SLAP_SOCK_SET_READ( s ); ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); WAKE_LISTENER(wake); } static void slapd_close(ber_socket_t s) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL1, "slapd_close: closing %ld\n", (long)s, 0, 0); -#else Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n", (long) s, 0, 0 ); -#endif tcp_close(s); } @@ -420,15 +650,9 @@ static int slap_get_listener_addresses( if ( strlen(host) > (sizeof(((struct sockaddr_un *)*sap)->sun_path) - 1) ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_get_listener_addresses: domain socket path (%s) " - "too long in URL\n", host, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon: domain socket path (%s) too long in URL", host, 0, 0); -#endif goto errexit; } @@ -450,14 +674,8 @@ static int slap_get_listener_addresses( snprintf(serv, sizeof serv, "%d", port); if ( (err = getaddrinfo(host, serv, &hints, &res)) ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_get_listener_addresses: getaddrinfo failed: %s\n", - AC_GAI_STRERROR(err), 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed: %s\n", AC_GAI_STRERROR(err), 0, 0); -#endif return -1; } @@ -475,14 +693,8 @@ static int slap_get_listener_addresses( for ( sai=res; sai; sai=sai->ai_next ) { if( sai->ai_addr == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_get_listener_addresses: " - "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "slap_get_listener_addresses: " "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 ); -#endif freeaddrinfo(res); goto errexit; } @@ -532,13 +744,8 @@ static int slap_get_listener_addresses( } else if ( !inet_aton( host, &in ) ) { he = gethostbyname( host ); if( he == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_get_listener_addresses: invalid host %s\n", host, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon: invalid host %s", host, 0, 0); -#endif return -1; } for (n = 0; he->h_addr_list[n]; n++) ; @@ -600,30 +807,20 @@ static int slap_open_listener( rc = ldap_url_parse( url, &lud ); if( rc != LDAP_URL_SUCCESS ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slap_open_listener: listen URL \"%s\" parse error %d\n", - url, rc , 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon: listen URL \"%s\" parse error=%d\n", url, rc, 0 ); -#endif return rc; } l.sl_url.bv_val = NULL; + l.sl_is_mute = 0; #ifndef HAVE_TLS if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_open_listener: TLS is not supported (%s)\n", url, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon: TLS not supported (%s)\n", url, 0, 0 ); -#endif ldap_free_urldesc( lud ); return -1; } @@ -652,13 +849,8 @@ static int slap_open_listener( } #else -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_open_listener: URL scheme is not supported: %s\n", url, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s", url, 0, 0); -#endif ldap_free_urldesc( lud ); return -1; #endif @@ -679,7 +871,7 @@ static int slap_open_listener( if ( lud->lud_exts ) { err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit ); } else { - l.sl_perms = S_IRWXU; + l.sl_perms = S_IRWXU | S_IRWXO; } #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */ @@ -699,15 +891,21 @@ static int slap_open_listener( psal = sal; while ( *sal != NULL ) { + char *af; switch( (*sal)->sa_family ) { case AF_INET: + af = "IPv4"; + break; #ifdef LDAP_PF_INET6 case AF_INET6: + af = "IPv6"; + break; #endif #ifdef LDAP_PF_LOCAL case AF_LOCAL: -#endif + af = "Local"; break; +#endif default: sal++; continue; @@ -718,29 +916,17 @@ static int slap_open_listener( l.sl_sd = socket( (*sal)->sa_family, socktype, 0); if ( l.sl_sd == AC_SOCKET_INVALID ) { int err = sock_errno(); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slap_open_listener: socket() failed errno=%d (%s)\n", - err, sock_errstr(err), 0 ); -#else Debug( LDAP_DEBUG_ANY, - "daemon: socket() failed errno=%d (%s)\n", err, - sock_errstr(err), 0 ); -#endif + "daemon: %s socket() failed errno=%d (%s)\n", + af, err, sock_errstr(err) ); sal++; continue; } #ifndef HAVE_WINSOCK if ( l.sl_sd >= dtblsize ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slap_open_listener: listener descriptor %ld is too " - "great %ld\n", (long)l.sl_sd, (long)dtblsize, 0 ); -#else Debug( LDAP_DEBUG_ANY, - "daemon: listener descriptor %ld is too great %ld\n", - (long) l.sl_sd, (long) dtblsize, 0 ); -#endif + "daemon: listener descriptor %ld is too great %ld\n", + (long) l.sl_sd, (long) dtblsize, 0 ); tcp_close( l.sl_sd ); sal++; continue; @@ -756,19 +942,12 @@ static int slap_open_listener( /* enable address reuse */ tmp = 1; rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR, - (char *) &tmp, sizeof(tmp) ); + (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_open_listener: setsockopt( %ld, SO_REUSEADDR ) " - "failed errno %d (%s)\n", (long)l.sl_sd, err, - sock_errstr(err) ); -#else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n", (long) l.sl_sd, err, sock_errstr(err) ); -#endif } #endif } @@ -786,15 +965,9 @@ static int slap_open_listener( (char *) &tmp, sizeof(tmp) ); if ( rc == AC_SOCKET_ERROR ) { int err = sock_errno(); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_open_listener: setsockopt( %ld, IPV6_V6ONLY ) failed errno %d (%s)\n", - (long)l.sl_sd, err, sock_errstr(err) ); -#else Debug( LDAP_DEBUG_ANY, "slapd(%ld): setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n", (long) l.sl_sd, err, sock_errstr(err) ); -#endif } #endif addrlen = sizeof(struct sockaddr_in6); @@ -809,14 +982,8 @@ static int slap_open_listener( if (bind(l.sl_sd, *sal, addrlen)) { err = sock_errno(); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_open_listener: bind(%ld) failed errno=%d (%s)\n", - (long)l.sl_sd, err, sock_errstr(err) ); -#else Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n", (long) l.sl_sd, err, sock_errstr(err) ); -#endif tcp_close( l.sl_sd ); sal++; continue; @@ -826,20 +993,16 @@ static int slap_open_listener( #ifdef LDAP_PF_LOCAL case AF_LOCAL: { char *addr = ((struct sockaddr_un *)*sal)->sun_path; +#if 0 /* don't muck with socket perms */ if ( chmod( addr, l.sl_perms ) < 0 && crit ) { int err = sock_errno(); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_open_listener: fchmod(%ld) failed errno=%d (%s)\n", - (long)l.sl_sd, err, sock_errstr(err) ); -#else Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)", (long) l.sl_sd, err, sock_errstr(err) ); -#endif tcp_close( l.sl_sd ); slap_free_listener_addresses(psal); return -1; } +#endif l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1; l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 ); snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, @@ -880,14 +1043,8 @@ static int slap_open_listener( #endif /* LDAP_PF_INET6 */ default: -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_open_listener: unsupported address family (%d)\n", - (int)(*sal)->sa_family, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n", (int) (*sal)->sa_family, 0, 0 ); -#endif break; } @@ -905,24 +1062,13 @@ static int slap_open_listener( if ( l.sl_url.bv_val == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, RESULTS, - "slap_open_listener: failed on %s\n", url, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "slap_open_listener: failed on %s\n", url, 0, 0 ); -#endif return -1; } -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, RESULTS, - "slap_open_listener: daemon initialized %s\n", - l.sl_url.bv_val, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n", l.sl_url.bv_val, 0, 0 ); -#endif return 0; } @@ -934,13 +1080,8 @@ int slapd_daemon_init( const char *urls ) int i, j, n, rc; char **u; -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ARGS, - "slapd_daemon_init: %s\n", urls ? urls : "", 0, 0 ); -#else Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n", urls ? urls : "", 0, 0 ); -#endif if( (rc = sockinit()) != 0 ) { return rc; } @@ -953,30 +1094,18 @@ int slapd_daemon_init( const char *urls ) dtblsize = FD_SETSIZE; #endif -#ifdef FD_SETSIZE - if(dtblsize > FD_SETSIZE) { - dtblsize = FD_SETSIZE; - } -#endif /* !FD_SETSIZE */ - /* open a pipe (or something equivalent connected to itself). * we write a byte on this fd whenever we catch a signal. The main * loop will be select'ing on this socket, and will wake up when * this byte arrives. */ if( (rc = lutil_pair( wake_sds )) < 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slap_daemon_init: lutil_pair() failed rc=%d\n", rc, 0, 0); -#else Debug( LDAP_DEBUG_ANY, "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 ); -#endif return rc; } - FD_ZERO( &slap_daemon.sd_readers ); - FD_ZERO( &slap_daemon.sd_writers ); + SLAP_SOCK_SET_INIT; if( urls == NULL ) { urls = "ldap:///"; @@ -985,45 +1114,25 @@ int slapd_daemon_init( const char *urls ) u = ldap_str2charray( urls, " " ); if( u == NULL || u[0] == NULL ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slap_daemon_init: no urls (%s) provided.\n", urls, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n", urls, 0, 0 ); -#endif return -1; } for( i=0; u[i] != NULL; i++ ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL1, - "slap_daemon_init: listen on %s\n.", u[i], 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n", u[i], 0, 0 ); -#endif } if( i == 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_daemon_init: no listeners to open (%s)\n", urls, 0, 0 ); -#else Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n", urls, 0, 0 ); -#endif ldap_charray_free( u ); return -1; } -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slap_daemon_init: %d listeners to open...\n", i, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n", i, 0, 0 ); -#endif slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) ); for(n = 0, j = 0; u[n]; n++ ) { @@ -1034,17 +1143,14 @@ int slapd_daemon_init( const char *urls ) } slap_listeners[j] = NULL; -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL1, - "slap_daemon_init: %d listeners opened\n", i, 0, 0 ); -#else Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n", i, 0, 0 ); -#endif #ifdef HAVE_SLP - slapd_slp_init( urls ); - slapd_slp_reg(); + if( slapd_register_slp ) { + slapd_slp_init( urls ); + slapd_slp_reg(); + } #endif ldap_charray_free( u ); @@ -1062,8 +1168,10 @@ slapd_daemon_destroy(void) sockdestroy(); #ifdef HAVE_SLP - slapd_slp_dereg(); - slapd_slp_deinit(); + if( slapd_register_slp ) { + slapd_slp_dereg(); + slapd_slp_deinit(); + } #endif return 0; @@ -1080,7 +1188,7 @@ close_listeners( for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) { if ( remove ) - slapd_remove( slap_listeners[l]->sl_sd, 0 ); + slapd_remove( slap_listeners[l]->sl_sd, 0, 0 ); #ifdef LDAP_PF_LOCAL if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) { unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path ); @@ -1097,6 +1205,272 @@ close_listeners( } } +static int +slapd_handle_listener( + Listener *sl +) +{ + Sockaddr from; + + ber_socket_t s; + socklen_t len = sizeof(from); + long id; + slap_ssf_t ssf = 0; + struct berval authid = BER_BVNULL; +#ifdef SLAPD_RLOOKUPS + char hbuf[NI_MAXHOST]; +#endif + + char *dnsname = NULL; + char *peeraddr = NULL; +#ifdef LDAP_PF_LOCAL + char peername[MAXPATHLEN + sizeof("PATH=")]; +#elif defined(LDAP_PF_INET6) + char peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")]; +#else + char peername[sizeof("IP=255.255.255.255:65336")]; +#endif /* LDAP_PF_LOCAL */ + + peername[0] = '\0'; + +#ifdef LDAP_CONNECTIONLESS + if ( sl->sl_is_udp ) { + /* The first time we receive a query, we set this + * up as a "connection". It remains open for the life + * of the slapd. + */ + if ( sl->sl_is_udp < 2 ) { + id = connection_init( sl->sl_sd, sl, "", "", + CONN_IS_UDP, ssf, NULL ); + sl->sl_is_udp++; + } + return 1; + } +#endif + +# ifdef LDAP_PF_LOCAL + /* FIXME: apparently accept doesn't fill + * the sun_path sun_path member */ + from.sa_un_addr.sun_path[0] = '\0'; +# endif /* LDAP_PF_LOCAL */ + + s = accept( sl->sl_sd, (struct sockaddr *) &from, &len ); + if ( s == AC_SOCKET_INVALID ) { + int err = sock_errno(); + + if( +#ifdef EMFILE + err == EMFILE || +#endif +#ifdef ENFILE + err == ENFILE || +#endif + 0 ) + { + ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + emfile++; + /* Stop listening until an existing session closes */ + sl->sl_is_mute = 1; + ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + } + + Debug( LDAP_DEBUG_ANY, + "daemon: accept(%ld) failed errno=%d (%s)\n", + (long) sl->sl_sd, err, + sock_errstr(err) ); + ldap_pvt_thread_yield(); + return 0; + } + +#ifndef HAVE_WINSOCK + /* make sure descriptor number isn't too great */ + if ( s >= dtblsize ) { + Debug( LDAP_DEBUG_ANY, + "daemon: %ld beyond descriptor table size %ld\n", + (long) s, (long) dtblsize, 0 ); + + slapd_close(s); + ldap_pvt_thread_yield(); + return 0; + } +#endif + +#ifdef LDAP_DEBUG + ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); + + /* newly accepted stream should not be in any of the FD SETS */ + assert( SLAP_SOCK_NOT_ACTIVE( s )); + + ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); +#endif + +#if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) +#ifdef LDAP_PF_LOCAL + /* for IPv4 and IPv6 sockets only */ + if ( from.sa_addr.sa_family != AF_LOCAL ) +#endif /* LDAP_PF_LOCAL */ + { + int rc; + int tmp; +#ifdef SO_KEEPALIVE + /* enable keep alives */ + tmp = 1; + rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, + (char *) &tmp, sizeof(tmp) ); + if ( rc == AC_SOCKET_ERROR ) { + int err = sock_errno(); + Debug( LDAP_DEBUG_ANY, + "slapd(%ld): setsockopt(SO_KEEPALIVE) failed " + "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); + } +#endif +#ifdef TCP_NODELAY + /* enable no delay */ + tmp = 1; + rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY, + (char *)&tmp, sizeof(tmp) ); + if ( rc == AC_SOCKET_ERROR ) { + int err = sock_errno(); + Debug( LDAP_DEBUG_ANY, + "slapd(%ld): setsockopt(TCP_NODELAY) failed " + "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); + } +#endif + } +#endif + + Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n", + (long) s, 0, 0 ); + switch ( from.sa_addr.sa_family ) { +# ifdef LDAP_PF_LOCAL + case AF_LOCAL: + /* FIXME: apparently accept doesn't fill + * the sun_path sun_path member */ + if ( from.sa_un_addr.sun_path[0] == '\0' ) { + AC_MEMCPY( from.sa_un_addr.sun_path, + sl->sl_sa.sa_un_addr.sun_path, + sizeof( from.sa_un_addr.sun_path ) ); + } + + sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path ); + ssf = local_ssf; + { + uid_t uid; + gid_t gid; + + if( getpeereid( s, &uid, &gid ) == 0 ) { + authid.bv_val = ch_malloc( + sizeof("uidnumber=4294967295+gidnumber=4294967295," + "cn=peercred,cn=external,cn=auth")); + authid.bv_len = sprintf( authid.bv_val, + "uidnumber=%d+gidnumber=%d," + "cn=peercred,cn=external,cn=auth", + (int) uid, (int) gid); + } + } + dnsname = "local"; + break; +#endif /* LDAP_PF_LOCAL */ + +# ifdef LDAP_PF_INET6 + case AF_INET6: + if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) { + peeraddr = inet_ntoa( *((struct in_addr *) + &from.sa_in6_addr.sin6_addr.s6_addr[12]) ); + sprintf( peername, "IP=%s:%d", + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, + (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); + } else { + char addr[INET6_ADDRSTRLEN]; + + peeraddr = (char *) inet_ntop( AF_INET6, + &from.sa_in6_addr.sin6_addr, + addr, sizeof addr ); + sprintf( peername, "IP=%s %d", + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, + (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); + } + break; +# endif /* LDAP_PF_INET6 */ + + case AF_INET: + peeraddr = inet_ntoa( from.sa_in_addr.sin_addr ); + sprintf( peername, "IP=%s:%d", + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, + (unsigned) ntohs( from.sa_in_addr.sin_port ) ); + break; + + default: + slapd_close(s); + return 0; + } + + if ( ( from.sa_addr.sa_family == AF_INET ) +#ifdef LDAP_PF_INET6 + || ( from.sa_addr.sa_family == AF_INET6 ) +#endif + ) { +#ifdef SLAPD_RLOOKUPS + if ( use_reverse_lookup ) { + char *herr; + if (ldap_pvt_get_hname( (const struct sockaddr *)&from, len, hbuf, + sizeof(hbuf), &herr ) == 0) { + ldap_pvt_str2lower( hbuf ); + dnsname = hbuf; + } + } +#else + dnsname = NULL; +#endif /* SLAPD_RLOOKUPS */ + +#ifdef HAVE_TCPD + if ( !hosts_ctl("slapd", + dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, + SLAP_STRING_UNKNOWN )) + { + /* DENY ACCESS */ + Statslog( LDAP_DEBUG_STATS, + "fd=%ld DENIED from %s (%s)\n", + (long) s, + dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, + peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, + 0, 0 ); + slapd_close(s); + return 0; + } +#endif /* HAVE_TCPD */ + } + + id = connection_init(s, sl, + dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, + peername, +#ifdef HAVE_TLS + sl->sl_is_tls ? CONN_IS_TLS : 0, +#else + 0, +#endif + ssf, + authid.bv_val ? &authid : NULL ); + + if( authid.bv_val ) ch_free(authid.bv_val); + + if( id < 0 ) { + Debug( LDAP_DEBUG_ANY, + "daemon: connection_init(%ld, %s, %s) failed.\n", + (long) s, peername, sl->sl_name.bv_val ); + slapd_close(s); + return 0; + } + + Statslog( LDAP_DEBUG_STATS, + "conn=%ld fd=%ld ACCEPT from %s (%s)\n", + id, (long) s, peername, sl->sl_name.bv_val, + 0 ); + + slapd_add( s, 1, NULL ); + return 0; +} static void * slapd_daemon_task( @@ -1105,11 +1479,27 @@ slapd_daemon_task( { int l; time_t last_idle_check = 0; - time( &starttime ); + struct timeval idle; + int ebadf = 0; + +#define SLAPD_IDLE_CHECK_LIMIT 4 if ( global_idletimeout > 0 ) { last_idle_check = slap_get_time(); + /* Set the select timeout. + * Don't just truncate, preserve the fractions of + * seconds to prevent sleeping for zero time. + */ + idle.tv_sec = global_idletimeout/SLAPD_IDLE_CHECK_LIMIT; + idle.tv_usec = global_idletimeout - idle.tv_sec * SLAPD_IDLE_CHECK_LIMIT; + idle.tv_usec *= 1000000 / SLAPD_IDLE_CHECK_LIMIT; + } else { + idle.tv_sec = 0; + idle.tv_usec = 0; } + + slapd_add( wake_sds[0], 0, NULL ); + for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; @@ -1119,7 +1509,7 @@ slapd_daemon_task( * are unnecessary. */ if ( slap_listeners[l]->sl_is_udp ) { - slapd_add( slap_listeners[l]->sl_sd ); + slapd_add( slap_listeners[l]->sl_sd, 1, slap_listeners[l] ); continue; } #endif @@ -1148,14 +1538,9 @@ slapd_daemon_task( if ( i < l ) { /* We are already listening to in6addr_any */ -#ifdef NEW_LOGGING - LDAP_LOG(CONNECTION, WARNING, - "slapd_daemon_task: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", 0, 0, 0 ); -#endif slapd_close( slap_listeners[l]->sl_sd ); slap_listeners[l]->sl_sd = AC_SOCKET_INVALID; continue; @@ -1163,20 +1548,14 @@ slapd_daemon_task( } } #endif -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slapd_daemon_task: listen( %s, 5 ) failed errno=%d (%s)\n", - slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); -#else Debug( LDAP_DEBUG_ANY, "daemon: listen(%s, 5) failed errno=%d (%s)\n", slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) ); -#endif return( (void*)-1 ); } - slapd_add( slap_listeners[l]->sl_sd ); + slapd_add( slap_listeners[l]->sl_sd, 0, slap_listeners[l] ); } #ifdef HAVE_NT_SERVICE_MANAGER @@ -1188,34 +1567,30 @@ slapd_daemon_task( while ( !slapd_shutdown ) { ber_socket_t i; - int ns; + int ns, nwriters; int at; - ber_socket_t nfds; + ber_socket_t nfds, nrfds, nwfds; #define SLAPD_EBADF_LIMIT 16 - int ebadf = 0; - int emfile = 0; -#define SLAPD_IDLE_CHECK_LIMIT 4 time_t now; + SLAP_EVENT_DECL; - fd_set readfds; - fd_set writefds; - Sockaddr from; - - struct timeval zero; + struct timeval tv; struct timeval *tvp; - if( emfile ) { - now = slap_get_time(); + struct timeval *cat; + time_t tdelta = 1; + struct re_s* rtask; + now = slap_get_time(); + + if( ( global_idletimeout > 0 ) && + difftime( last_idle_check + + global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) { connections_timeout_idle( now ); + last_idle_check = now; } - else if ( global_idletimeout > 0 ) { - now = slap_get_time(); - if ( difftime( last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) { - connections_timeout_idle( now ); - } - } + tv = idle; #ifdef SIGHUP if( slapd_gentle_shutdown ) { @@ -1224,7 +1599,7 @@ slapd_daemon_task( if( slapd_gentle_shutdown == 1 ) { Debug( LDAP_DEBUG_ANY, "slapd gentle shutdown\n", 0, 0, 0 ); close_listeners( 1 ); - global_restrictops |= SLAP_RESTRICT_OP_WRITES; + frontendDB->be_restrictops |= SLAP_RESTRICT_OP_WRITES; slapd_gentle_shutdown = 2; } @@ -1238,78 +1613,79 @@ slapd_daemon_task( } #endif - FD_ZERO( &writefds ); - FD_ZERO( &readfds ); - - zero.tv_sec = 0; - zero.tv_usec = 0; + at = 0; ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); -#ifdef FD_SET_MANUAL_COPY - for( s = 0; s < nfds; s++ ) { - if(FD_ISSET( &slap_sd_readers, s )) { - FD_SET( s, &readfds ); - } - if(FD_ISSET( &slap_sd_writers, s )) { - FD_SET( s, &writefds ); - } - } -#else - AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) ); - AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) ); -#endif - assert(!FD_ISSET(wake_sds[0], &readfds)); - FD_SET( wake_sds[0], &readfds ); + nwriters = slap_daemon.sd_nwriters; + SLAP_EVENT_INIT; for ( l = 0; slap_listeners[l] != NULL; l++ ) { if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; - if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds)) - FD_SET( slap_listeners[l]->sl_sd, &readfds ); + if ( slap_listeners[l]->sl_is_mute ) + SLAP_SOCK_SET_MUTE( slap_listeners[l]->sl_sd ); + else + if ( SLAP_SOCK_IS_MUTE( slap_listeners[l]->sl_sd )) + SLAP_SOCK_CLR_MUTE( slap_listeners[l]->sl_sd ); } -#ifndef HAVE_WINSOCK - nfds = slap_daemon.sd_nfds; -#else - nfds = dtblsize; -#endif + nfds = SLAP_EVENT_MAX; - ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); + if ( global_idletimeout && slap_daemon.sd_nactives ) + at = 1; - at = ldap_pvt_thread_pool_backload(&connection_pool); + ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); -#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS ) - tvp = NULL; -#else - tvp = at ? &zero : NULL; + if ( at +#if defined(HAVE_YIELDING_SELECT) || defined(NO_THREADS) + && ( tv.tv_sec || tv.tv_usec ) #endif + ) + tvp = &tv; + else + tvp = NULL; + + ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex ); + rtask = ldap_pvt_runqueue_next_sched( &syncrepl_rq, &cat ); + while ( cat && cat->tv_sec && cat->tv_sec <= now ) { + if ( ldap_pvt_runqueue_isrunning( &syncrepl_rq, rtask )) { + ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, 0 ); + } else { + ldap_pvt_runqueue_runtask( &syncrepl_rq, rtask ); + ldap_pvt_runqueue_resched( &syncrepl_rq, rtask, 0 ); + ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex ); + ldap_pvt_thread_pool_submit( &connection_pool, + rtask->routine, (void *) rtask ); + ldap_pvt_thread_mutex_lock( &syncrepl_rq.rq_mutex ); + } + rtask = ldap_pvt_runqueue_next_sched( &syncrepl_rq, &cat ); + } + ldap_pvt_thread_mutex_unlock( &syncrepl_rq.rq_mutex ); + + if ( cat != NULL ) { + time_t diff = difftime( cat->tv_sec, now ); + if ( diff == 0 ) + diff = tdelta; + if ( tvp == NULL || diff < tv.tv_sec ) { + tv.tv_sec = diff; + tv.tv_usec = 0; + tvp = &tv; + } + } for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) + if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID || + slap_listeners[l]->sl_is_mute ) continue; -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL1, - "slapd_daemon_task: select: listen=%d " - "active_threads=%d tvp=%s\n", - slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "zero" ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: select: listen=%d active_threads=%d tvp=%s\n", slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "zero" ); -#endif } - switch(ns = select( nfds, &readfds, -#ifdef HAVE_WINSOCK - /* don't pass empty fd_set */ - ( writefds.fd_count > 0 ? &writefds : NULL ), -#else - &writefds, -#endif - NULL, tvp )) + switch(ns = SLAP_EVENT_WAIT(tvp)) { case -1: { /* failure - try again */ int err = sock_errno(); @@ -1325,15 +1701,9 @@ slapd_daemon_task( } if( err != EINTR ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slapd_daemon_task: select failed (%d): %s\n", - err, sock_errstr(err), 0 ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: select failed (%d): %s\n", err, sock_errstr(err), 0 ); -#endif slapd_shutdown = 2; } } @@ -1341,13 +1711,9 @@ slapd_daemon_task( case 0: /* timeout - let threads run */ ebadf = 0; -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - "slapd_daemon_task: select timeout - yielding\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n", 0, 0, 0 ); -#endif + ldap_pvt_thread_yield(); continue; @@ -1355,444 +1721,115 @@ slapd_daemon_task( if( slapd_shutdown ) continue; ebadf = 0; -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - "slapd_daemon_task: activity on %d descriptors\n", ns, 0, 0 ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n", ns, 0, 0 ); -#endif /* FALL THRU */ } - if( FD_ISSET( wake_sds[0], &readfds ) ) { + /* We don't need to examine the event status for wake_sds; + * if waking is set and we woke up, we'll read whatever + * we can. + */ + if ( waking ) { char c[BUFSIZ]; tcp_read( wake_sds[0], c, sizeof(c) ); -#if defined(NO_THREADS) || defined(HAVE_GNU_PTH) waking = 0; -#endif + ns--; continue; } +#if SLAP_EVENTS_ARE_INDEXED + /* The event slot equals the descriptor number - this is + * true for Unix select and poll. We treat Windows select + * like this too, even though it's a kludge. + */ for ( l = 0; slap_listeners[l] != NULL; l++ ) { - ber_socket_t s; - socklen_t len = sizeof(from); - long id; - slap_ssf_t ssf = 0; - char *authid = NULL; -#ifdef SLAPD_RLOOKUPS - char hbuf[NI_MAXHOST]; -#endif + int rc; - char *dnsname = NULL; - char *peeraddr = NULL; -#ifdef LDAP_PF_LOCAL - char peername[MAXPATHLEN + sizeof("PATH=")]; -#elif defined(LDAP_PF_INET6) - char peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")]; -#else - char peername[sizeof("IP=255.255.255.255:65336")]; -#endif /* LDAP_PF_LOCAL */ - - peername[0] = '\0'; + if ( ns <= 0 ) break; if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID ) continue; - if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) ) + if ( !SLAP_EVENT_IS_READ( slap_listeners[l]->sl_sd )) continue; + + ns--; -#ifdef LDAP_CONNECTIONLESS - if ( slap_listeners[l]->sl_is_udp ) { - /* The first time we receive a query, we set this - * up as a "connection". It remains open for the life - * of the slapd. - */ - if ( slap_listeners[l]->sl_is_udp < 2 ) { - id = connection_init( - slap_listeners[l]->sl_sd, - slap_listeners[l], "", "", - 2, ssf, authid ); - slap_listeners[l]->sl_is_udp++; - } - continue; - } -#endif + rc = slapd_handle_listener(slap_listeners[l]); - s = accept( slap_listeners[l]->sl_sd, - (struct sockaddr *) &from, &len ); - if ( s == AC_SOCKET_INVALID ) { - int err = sock_errno(); - -#ifdef EMFILE - if( err == EMFILE ) { - emfile++; - } else -#endif -#ifdef ENFILE - if( err == ENFILE ) { - emfile++; - } else -#endif - { - emfile=0; - } - - if( emfile < 3 ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n", - (long)slap_listeners[l]->sl_sd, - err, sock_errstr(err) ); -#else - Debug( LDAP_DEBUG_ANY, - "daemon: accept(%ld) failed errno=%d (%s)\n", - (long) slap_listeners[l]->sl_sd, err, - sock_errstr(err) ); -#endif - } else { - /* prevent busy loop */ -# ifdef HAVE_USLEEP - if( emfile % 4 == 3 ) usleep( 250 ); -# else - if( emfile % 8 == 7 ) sleep( 1 ); -# endif - } - - ldap_pvt_thread_yield(); - continue; - } - emfile = 0; - -#ifndef HAVE_WINSOCK - /* make sure descriptor number isn't too great */ - if ( s >= dtblsize ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slapd_daemon_task: %ld beyond descriptor table size %ld\n", - (long)s, (long)dtblsize, 0 ); -#else - Debug( LDAP_DEBUG_ANY, - "daemon: %ld beyond descriptor table size %ld\n", - (long) s, (long) dtblsize, 0 ); -#endif - - slapd_close(s); - ldap_pvt_thread_yield(); - continue; - } -#endif - -#ifdef LDAP_DEBUG - ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex ); - - /* newly accepted stream should not be in any of the FD SETS */ - assert( !FD_ISSET( s, &slap_daemon.sd_actives) ); - assert( !FD_ISSET( s, &slap_daemon.sd_readers) ); - assert( !FD_ISSET( s, &slap_daemon.sd_writers) ); - - ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex ); -#endif - -#if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY ) -#ifdef LDAP_PF_LOCAL - /* for IPv4 and IPv6 sockets only */ - if ( from.sa_addr.sa_family != AF_LOCAL ) -#endif /* LDAP_PF_LOCAL */ - { - int rc; - int tmp; -#ifdef SO_KEEPALIVE - /* enable keep alives */ - tmp = 1; - rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, - (char *) &tmp, sizeof(tmp) ); - if ( rc == AC_SOCKET_ERROR ) { - int err = sock_errno(); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slapd_daemon_task: setsockopt( %ld, SO_KEEPALIVE)" - " failed errno=%d (%s)\n", - (long)s, err, sock_errstr(err) ); -#else - Debug( LDAP_DEBUG_ANY, - "slapd(%ld): setsockopt(SO_KEEPALIVE) failed " - "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); -#endif - } -#endif -#ifdef TCP_NODELAY - /* enable no delay */ - tmp = 1; - rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY, - (char *)&tmp, sizeof(tmp) ); - if ( rc == AC_SOCKET_ERROR ) { - int err = sock_errno(); -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, ERR, - "slapd_daemon_task: setsockopt( %ld, " - "TCP_NODELAY) failed errno=%d (%s)\n", - (long)s, err, sock_errstr(err) ); -#else - Debug( LDAP_DEBUG_ANY, - "slapd(%ld): setsockopt(TCP_NODELAY) failed " - "errno=%d (%s)\n", (long) s, err, sock_errstr(err) ); -#endif - } -#endif - } -#endif - -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL1, - "slapd_daemon_task: new connection on %ld\n", (long)s, 0, 0 ); -#else - Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n", - (long) s, 0, 0 ); -#endif - switch ( from.sa_addr.sa_family ) { -# ifdef LDAP_PF_LOCAL - case AF_LOCAL: - sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path ); - ssf = LDAP_PVT_SASL_LOCAL_SSF; - { - uid_t uid; - gid_t gid; - - if( getpeereid( s, &uid, &gid ) == 0 ) { - authid = ch_malloc( - sizeof("uidnumber=4294967295+gidnumber=4294967295," - "cn=peercred,cn=external,cn=auth")); - sprintf(authid, "uidnumber=%d+gidnumber=%d," - "cn=peercred,cn=external,cn=auth", - (int) uid, (int) gid); - } - } - dnsname = "local"; - break; -#endif /* LDAP_PF_LOCAL */ - -# ifdef LDAP_PF_INET6 - case AF_INET6: - if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) { - peeraddr = inet_ntoa( *((struct in_addr *) - &from.sa_in6_addr.sin6_addr.s6_addr[12]) ); - sprintf( peername, "IP=%s:%d", - peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, - (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); - } else { - char addr[INET6_ADDRSTRLEN]; - - peeraddr = (char *) inet_ntop( AF_INET6, - &from.sa_in6_addr.sin6_addr, - addr, sizeof addr ); - sprintf( peername, "IP=%s %d", - peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, - (unsigned) ntohs( from.sa_in6_addr.sin6_port ) ); - } - break; -# endif /* LDAP_PF_INET6 */ - - case AF_INET: - peeraddr = inet_ntoa( from.sa_in_addr.sin_addr ); - sprintf( peername, "IP=%s:%d", - peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, - (unsigned) ntohs( from.sa_in_addr.sin_port ) ); - break; - - default: - slapd_close(s); - continue; - } - - if ( ( from.sa_addr.sa_family == AF_INET ) -#ifdef LDAP_PF_INET6 - || ( from.sa_addr.sa_family == AF_INET6 ) -#endif - ) { -#ifdef SLAPD_RLOOKUPS - if ( use_reverse_lookup ) { - char *herr; - if (ldap_pvt_get_hname( &from, len, hbuf, - sizeof(hbuf), &herr ) == 0) { - ldap_pvt_str2lower( hbuf ); - dnsname = hbuf; - } - } -#else - dnsname = NULL; -#endif /* SLAPD_RLOOKUPS */ - -#ifdef HAVE_TCPD - if ( !hosts_ctl("slapd", - dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, - peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, - SLAP_STRING_UNKNOWN )) - { - /* DENY ACCESS */ - Statslog( LDAP_DEBUG_STATS, - "fd=%ld DENIED from %s (%s)", - (long) s, - dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, - peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN, - 0, 0 ); - slapd_close(s); - continue; - } -#endif /* HAVE_TCPD */ - } - - id = connection_init(s, - slap_listeners[l], - dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN, - peername, -#ifdef HAVE_TLS - slap_listeners[l]->sl_is_tls, -#else - 0, -#endif - ssf, - authid ); - - if( authid ) ch_free(authid); - - if( id < 0 ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, INFO, - "slapd_daemon_task: " - "connection_init(%ld, %s, %s) " - "failed.\n", - (long)s, peername, - slap_listeners[l]->sl_name.bv_val ); -#else - Debug( LDAP_DEBUG_ANY, - "daemon: connection_init(%ld, %s, %s) " - "failed.\n", - (long) s, - peername, - slap_listeners[l]->sl_name.bv_val ); +#ifdef LDAP_CONNECTIONLESS + /* This is a UDP session, let the data loop process it */ + if ( rc ) continue; #endif - slapd_close(s); - continue; - } - Statslog( LDAP_DEBUG_STATS, - "conn=%ld fd=%ld ACCEPT from %s (%s)\n", - id, (long) s, - peername, - slap_listeners[l]->sl_name.bv_val, - 0 ); + /* Don't need to look at this in the data loops */ + SLAP_EVENT_CLR_READ( slap_listeners[l]->sl_sd ); + SLAP_EVENT_CLR_WRITE( slap_listeners[l]->sl_sd ); + } - slapd_add( s ); + /* bypass the following tests if no descriptors left */ + if ( ns <= 0 ) { + ldap_pvt_thread_yield(); continue; } -#ifdef LDAP_DEBUG -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - "slapd_daemon_task: activity on ", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 ); -#endif #ifdef HAVE_WINSOCK + nrfds = readfds.fd_count; + nwfds = writefds.fd_count; for ( i = 0; i < readfds.fd_count; i++ ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - " %d%s", readfds.fd_array[i], "r", 0, 0 ); -#else Debug( LDAP_DEBUG_CONNS, " %d%s", readfds.fd_array[i], "r", 0 ); -#endif } for ( i = 0; i < writefds.fd_count; i++ ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - " %d%s", writefds.fd_array[i], "w" , 0 ); -#else Debug( LDAP_DEBUG_CONNS, " %d%s", writefds.fd_array[i], "w", 0 ); -#endif } #else + nrfds = 0; + nwfds = 0; for ( i = 0; i < nfds; i++ ) { int r, w; - int is_listener = 0; - for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( i == slap_listeners[l]->sl_sd ) { -#ifdef LDAP_CONNECTIONLESS - /* The listener is the data port. Don't - * skip it. - */ - if (slap_listeners[l]->sl_is_udp) continue; -#endif - is_listener = 1; - break; - } - } - if ( is_listener ) { - continue; - } - r = FD_ISSET( i, &readfds ); - w = FD_ISSET( i, &writefds ); + r = SLAP_EVENT_IS_READ( i ); + w = SLAP_EVENT_IS_WRITE( i ); if ( r || w ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - " %d%s%s", i, r ? "r" : "", w ? "w" : "" ); -#else Debug( LDAP_DEBUG_CONNS, " %d%s%s", i, r ? "r" : "", w ? "w" : "" ); -#endif + if ( r ) { + nrfds++; + ns--; + } + if ( w ) { + nwfds++; + ns--; + } } + if ( ns <= 0 ) break; } #endif -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, "\n", 0, 0, 0 ); -#else Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 ); -#endif -#endif /* loop through the writers */ -#ifdef HAVE_WINSOCK - for ( i = 0; i < writefds.fd_count; i++ ) -#else - for ( i = 0; i < nfds; i++ ) -#endif + for ( i = 0; nwfds > 0; i++ ) { ber_socket_t wd; - int is_listener = 0; #ifdef HAVE_WINSOCK wd = writefds.fd_array[i]; #else - if( ! FD_ISSET( i, &writefds ) ) { + if( ! SLAP_EVENT_IS_WRITE( i ) ) { continue; } wd = i; #endif + nwfds--; - for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( i == slap_listeners[l]->sl_sd ) { -#ifdef LDAP_CONNECTIONLESS - if (slap_listeners[l]->sl_is_udp) continue; -#endif - is_listener = 1; - break; - } - } - if ( is_listener ) { - continue; - } -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - "slapd_daemon_task: write active on %d\n", wd, 0, 0 ); -#else Debug( LDAP_DEBUG_CONNS, "daemon: write active on %d\n", wd, 0, 0 ); -#endif /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. @@ -1801,49 +1838,29 @@ slapd_daemon_task( */ if ( connection_write( wd ) < 0 ) { - FD_CLR( (unsigned) wd, &readfds ); + if ( SLAP_EVENT_IS_READ( wd )) { + SLAP_EVENT_CLR_READ( (unsigned) wd ); + nrfds--; + } slapd_close( wd ); } } -#ifdef HAVE_WINSOCK - for ( i = 0; i < readfds.fd_count; i++ ) -#else - for ( i = 0; i < nfds; i++ ) -#endif + for ( i = 0; nrfds > 0; i++ ) { ber_socket_t rd; - int is_listener = 0; - #ifdef HAVE_WINSOCK rd = readfds.fd_array[i]; #else - if( ! FD_ISSET( i, &readfds ) ) { + if( ! SLAP_EVENT_IS_READ( i ) ) { continue; } rd = i; #endif + nrfds--; - for ( l = 0; slap_listeners[l] != NULL; l++ ) { - if ( rd == slap_listeners[l]->sl_sd ) { -#ifdef LDAP_CONNECTIONLESS - if (slap_listeners[l]->sl_is_udp) continue; -#endif - is_listener = 1; - break; - } - } - if ( is_listener ) { - continue; - } - -#ifdef NEW_LOGGING - LDAP_LOG( CONNECTION, DETAIL2, - "slapd_daemon_task: read activity on %d\n", rd, 0, 0 ); -#else Debug ( LDAP_DEBUG_CONNS, "daemon: read activity on %d\n", rd, 0, 0 ); -#endif /* * NOTE: it is possible that the connection was closed * and that the stream is now inactive. @@ -1855,51 +1872,110 @@ slapd_daemon_task( slapd_close( rd ); } } +#else /* !SLAP_EVENTS_ARE_INDEXED */ + /* FIXME */ + /* The events are returned in an arbitrary list. This is true + * for /dev/poll, epoll and kqueue. In order to prioritize things + * so that we can handle wake_sds first, listeners second, and then + * all other connections last (as we do for select), we would need + * to use multiple event handles and cascade them. + * + * That seems like a bit of hassle. So the wake_sds check has moved + * above. For epoll and kqueue we can associate arbitrary data with + * an event, so we could use pointers to the listener structure + * instead of just the file descriptor. For /dev/poll we have to + * search the listeners array for a matching descriptor. + */ +#ifdef LDAP_DEBUG + Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 ); + + for (i=0; isl_is_udp) +#endif + ) continue; + + r = SLAP_EVENT_IS_READ( i ); + w = SLAP_EVENT_IS_WRITE( i ); + if ( r || w ) { + Debug( LDAP_DEBUG_CONNS, " %d%s%s", SLAP_EVENT_FD(i), + r ? "r" : "", w ? "w" : "" ); + } + } +#endif + for (i=0; i