2 //#include "portable_err.h"
10 #include <ac/string.h>
12 #include <ac/unistd.h>
14 #include "ldap_defaults.h"
20 int allow_severity = LOG_INFO;
21 int deny_severity = LOG_NOTICE;
22 #endif /* TCP Wrappers */
30 extern ldap_pvt_thread_cond_t started_event;
31 /* forward reference */
34 char *WSAGetLastErrorString();
35 static ldap_pvt_thread_t hit_tid;
37 #define WAKE_LISTENER(w) \
40 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
45 #define WAKE_LISTENER(w) \
48 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
56 volatile sig_atomic_t slapd_shutdown = 0;
58 static int daemon_initialized = 0;
59 static ldap_pvt_thread_t listener_tid;
60 static volatile sig_atomic_t slapd_listener = 0;
64 ldap_pvt_thread_mutex_t sd_mutex;
69 /* In winsock, accept() returns values higher than dtblsize
70 so don't bother with this optimization */
80 * Add a descriptor to daemon control
82 static void slapd_add(int s) {
83 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
85 assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
86 assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
87 assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
90 if (s >= slap_daemon.sd_nfds) {
91 slap_daemon.sd_nfds = s + 1;
95 FD_SET( (unsigned) s, &slap_daemon.sd_actives );
96 FD_SET( (unsigned) s, &slap_daemon.sd_readers );
98 Debug( LDAP_DEBUG_CONNS, "daemon: added %d%s%s\n", s,
99 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
100 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
102 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
106 * Remove the descriptor from daemon control
108 void slapd_remove(int s, int wake) {
109 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
112 Debug( LDAP_DEBUG_CONNS, "daemon: removing %d%s%s\n", s,
113 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
114 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
116 FD_CLR( (unsigned) s, &slap_daemon.sd_actives );
117 FD_CLR( (unsigned) s, &slap_daemon.sd_readers );
118 FD_CLR( (unsigned) s, &slap_daemon.sd_writers );
120 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
123 void slapd_clr_write(int s, int wake) {
124 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
127 assert( FD_ISSET( (unsigned) s, &slap_daemon.sd_actives) );
128 FD_CLR( (unsigned) s, &slap_daemon.sd_writers );
130 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
133 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
137 void slapd_set_write(int s, int wake) {
138 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
141 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
142 FD_SET( (unsigned) s, &slap_daemon.sd_writers );
144 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
147 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
151 void slapd_clr_read(int s, int wake) {
152 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
155 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
156 FD_CLR( (unsigned) s, &slap_daemon.sd_readers );
158 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
161 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
165 void slapd_set_read(int s, int wake) {
166 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
169 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
170 FD_SET( (unsigned) s, &slap_daemon.sd_readers );
172 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
175 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
179 static void slapd_close(int s) {
180 Debug( LDAP_DEBUG_CONNS, "daemon: closing %d\n", s, 0, 0 );
187 set_socket( struct sockaddr_in *addr )
190 if ( !daemon_initialized ) sockinit();
193 dtblsize = sysconf( _SC_OPEN_MAX );
194 #elif HAVE_GETDTABLESIZE
195 dtblsize = getdtablesize();
197 dtblsize = FD_SETSIZE;
201 if(dtblsize > FD_SETSIZE) {
202 dtblsize = FD_SETSIZE;
204 #endif /* !FD_SETSIZE */
209 if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
212 Debug( LDAP_DEBUG_ANY,
213 "daemon: socket() failed errno %d (%s)\n", err,
214 err > -1 && err < sys_nerr ? sys_errlist[err] :
217 Debug( LDAP_DEBUG_ANY,
218 "daemon: socket() failed errno %d (%s)\n",
220 WSAGetLastErrorString(), 0 );
226 if ( tcps >= dtblsize ) {
227 Debug( LDAP_DEBUG_ANY,
228 "daemon: listener descriptor %d is too great\n",
236 if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR,
237 (char *) &tmp, sizeof(tmp) ) == -1 )
240 Debug( LDAP_DEBUG_ANY,
241 "slapd(%d): setsockopt() failed errno %d (%s)\n",
243 err > -1 && err < sys_nerr
244 ? sys_errlist[err] : "unknown" );
249 if ( setsockopt( tcps, SOL_SOCKET, SO_KEEPALIVE,
250 (char *) &tmp, sizeof(tmp) ) == -1 )
253 Debug( LDAP_DEBUG_ANY,
254 "slapd(%d): setsockopt(KEEPALIVE) failed errno %d (%s)\n",
256 err > -1 && err < sys_nerr
257 ? sys_errlist[err] : "unknown" );
262 if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
264 Debug( LDAP_DEBUG_ANY, "daemon: bind(%d) failed errno %d (%s)\n",
266 err > -1 && err < sys_nerr
267 ? sys_errlist[err] : "unknown" );
281 struct slapd_args *args = (struct slapd_args *) ptr;
282 struct sockaddr_in *slapd_addr = args->addr;
287 inetd = ( slapd_addr == NULL);
288 if ( !daemon_initialized ) sockinit();
292 ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
293 FD_ZERO( &slap_daemon.sd_readers );
294 FD_ZERO( &slap_daemon.sd_writers );
297 if ( listen( tcps, 5 ) == -1 ) {
299 Debug( LDAP_DEBUG_ANY,
300 "daemon: listen(%d, 5) failed errno %d (%s)\n",
302 err > -1 && err < sys_nerr
303 ? sys_errlist[err] : "unknown" );
310 if( connection_init( 0, NULL, NULL ) ) {
311 Debug( LDAP_DEBUG_ANY,
312 "connection_init(%d) failed.\n",
322 if ( started_event != NULL )
323 ldap_pvt_thread_cond_signal( &started_event );
325 // initialization complete. Here comes the loop.
326 while ( !slapd_shutdown ) {
330 #define SLAPD_EBADF_LIMIT 10
335 struct sockaddr_in from;
336 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
345 FD_ZERO( &writefds );
351 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
353 #ifdef FD_SET_MANUAL_COPY
354 for( s = 0; s < nfds; s++ ) {
355 if(FD_ISSET( &slap_sd_writers, s )) {
356 FD_SET( &writefds, s );
358 if(FD_ISSET( &slap_sd_writers, s )) {
359 FD_SET( &writefds, s );
363 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
364 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
367 FD_SET( (unsigned) tcps, &readfds );
370 nfds = slap_daemon.sd_nfds;
375 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
377 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
378 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
381 tvp = active_threads ? &zero : NULL;
384 Debug( LDAP_DEBUG_CONNS,
385 "daemon: select: tcps=%d active_threads=%d tvp=%s\n",
386 tcps, active_threads,
387 tvp == NULL ? "NULL" : "zero" );
390 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
392 switch(ns = select( nfds, &readfds, &writefds, 0, tvp )) {
393 case -1: { /* failure - try again */
395 int err = WSAGetLastError();
400 if( err == EBADF && ++ebadf < SLAPD_EBADF_LIMIT) {
405 Debug( LDAP_DEBUG_CONNS,
406 "daemon: select failed (%d): %s\n",
408 err >= 0 && err < sys_nerr
409 ? sys_errlist[err] : "unknown",
418 case 0: /* timeout - let threads run */
420 Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
422 ldap_pvt_thread_yield();
425 default: /* something happened - deal with it */
427 Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
432 if ( FD_ISSET( tcps, &readfds ) ) {
434 int len = sizeof(from);
437 if ( (s = accept( tcps,
438 (struct sockaddr *) &from, &len )) == -1 )
441 Debug( LDAP_DEBUG_ANY,
442 "daemon: accept(%d) failed errno %d (%s)\n", err,
443 tcps, err >= 0 && err < sys_nerr ?
444 sys_errlist[err] : "unknown");
449 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
451 /* newly accepted stream should not be in any of the FD SETS */
453 assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
454 assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
455 assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
457 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
461 /* make sure descriptor number isn't too great */
462 if ( s >= dtblsize ) {
463 Debug( LDAP_DEBUG_ANY,
464 "daemon: %d beyond descriptor table size %d\n",
471 Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %d\n",
475 if ( getpeername( s, (struct sockaddr *) &from, &len ) == 0 ) {
476 client_addr = inet_ntoa( from.sin_addr );
478 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
479 hp = gethostbyaddr( (char *)
480 &(from.sin_addr.s_addr),
481 sizeof(from.sin_addr.s_addr), AF_INET );
485 client_name = hp->h_name;
487 /* normalize the domain */
488 for ( p = client_name; *p; p++ ) {
489 *p = TOLOWER( (unsigned char) *p );
505 if(!hosts_ctl("slapd",
506 client_name != NULL ? client_name : STRING_UNKNOWN,
507 client_addr != NULL ? client_addr : STRING_UNKNOWN,
511 Statslog( LDAP_DEBUG_ANY,
512 "fd=%d connection from %s (%s) denied.\n",
514 client_name == NULL ? "unknown" : client_name,
515 client_addr == NULL ? "unknown" : client_addr,
521 #endif /* HAVE_TCPD */
523 if( (id = connection_init(s, client_name, client_addr)) < 0 ) {
524 Debug( LDAP_DEBUG_ANY,
525 "daemon: connection_init(%d, %s, %s) failed.\n",
527 client_name == NULL ? "unknown" : client_name,
528 client_addr == NULL ? "unknown" : client_addr);
533 Statslog( LDAP_DEBUG_STATS,
534 "daemon: conn=%d fd=%d connection from %s (%s) accepted.\n",
536 client_name == NULL ? "unknown" : client_name,
537 client_addr == NULL ? "unknown" : client_addr,
545 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
547 for ( i = 0; i < readfds.fd_count; i++ ) {
548 Debug( LDAP_DEBUG_CONNS, " %d%s", readfds.fd_array[i], "r" );
550 for ( i = 0; i < writefds.fd_count; i++ ) {
551 Debug( LDAP_DEBUG_CONNS, " %d%s", writefds.fd_array[i], "w" );
554 for ( i = 0; i < nfds; i++ ) {
557 r = FD_ISSET( i, &readfds );
558 w = FD_ISSET( i, &writefds );
559 if ( i != tcps && (r || w) ) {
560 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
561 r ? "r" : "", w ? "w" : "" );
565 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
568 /* loop through the writers */
570 for ( i = 0; i < writefds.fd_count; i++ )
572 for ( i = 0; i < nfds; i++ )
578 wd = writefds.fd_array[i];
580 if( ! FD_ISSET( i, &writefds ) ) {
589 Debug( LDAP_DEBUG_CONNS,
590 "daemon: write active on %d\n",
594 * NOTE: it is possible that the connection was closed
595 * and that the stream is now inactive.
596 * connection_write() must valid the stream is still
600 if ( connection_write( wd ) < 0 ) {
601 FD_CLR( (unsigned) wd, &readfds );
607 for ( i = 0; i < readfds.fd_count; i++ )
609 for ( i = 0; i < nfds; i++ )
615 rd = readfds.fd_array[i];
617 if( ! FD_ISSET( i, &readfds ) ) {
627 Debug ( LDAP_DEBUG_CONNS,
628 "daemon: read activity on %d\n", rd, 0, 0 );
631 * NOTE: it is possible that the connection was closed
632 * and that the stream is now inactive.
633 * connection_read() must valid the stream is still
637 if ( connection_read( rd ) < 0 ) {
641 ldap_pvt_thread_yield();
644 if( slapd_shutdown > 0 ) {
645 Debug( LDAP_DEBUG_TRACE,
646 "daemon: shutdown requested and initiated.\n",
649 } else if ( slapd_shutdown < 0 ) {
650 Debug( LDAP_DEBUG_TRACE,
651 "daemon: abnormal condition, shutdown initiated.\n",
654 Debug( LDAP_DEBUG_TRACE,
655 "daemon: no active streams, shutdown initiated.\n",
663 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
664 Debug( LDAP_DEBUG_ANY,
665 "slapd shutdown: waiting for %d threads to terminate\n",
666 active_threads, 0, 0 );
667 while ( active_threads > 0 ) {
668 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
670 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
676 int slapd_daemon( struct slapd_args *args )
680 if ( !daemon_initialized ) sockinit();
684 #define SLAPD_LISTENER_THREAD 1
685 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
687 /* listener as a separate THREAD */
688 rc = ldap_pvt_thread_create( &listener_tid,
689 0, slapd_daemon_task, args );
692 Debug( LDAP_DEBUG_ANY,
693 "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
697 /* wait for the listener thread to complete */
698 ldap_pvt_thread_join( listener_tid, (void *) NULL );
700 /* expermimental code */
701 listener_tid = pthread_self();
702 slapd_daemon_task( args );
708 connections_destroy();
720 WORD wVersionRequested;
724 wVersionRequested = MAKEWORD( 2, 0 );
726 err = WSAStartup( wVersionRequested, &wsaData );
728 /* Tell the user that we couldn't find a usable */
733 /* Confirm that the WinSock DLL supports 2.0.*/
734 /* Note that if the DLL supports versions greater */
735 /* than 2.0 in addition to 2.0, it will still return */
736 /* 2.0 in wVersion since that is the version we */
739 if ( LOBYTE( wsaData.wVersion ) != 2 ||
740 HIBYTE( wsaData.wVersion ) != 0 )
742 /* Tell the user that we couldn't find a usable */
747 daemon_initialized = 1;
748 } /* The WinSock DLL is acceptable. Proceed. */
753 extern struct sockaddr_in bind_addr;
755 /* throw something at the socket to terminate the select() in the daemon thread. */
756 if (( s = socket( AF_INET, SOCK_STREAM, 0 )) == INVALID_SOCKET )
757 Debug( LDAP_DEBUG_ANY,
758 "slap_set_shutdown: socket failed\n\tWSAGetLastError=%d (%s)\n",
759 WSAGetLastError(), WSAGetLastErrorString(), 0 );
761 if ( ioctlsocket( s, FIONBIO, &on ) == -1 )
762 Debug( LDAP_DEBUG_ANY,
763 "slap_set_shutdown:FIONBIO ioctl on %d faled\n\tWSAGetLastError=%d (%s)\n",
764 s, WSAGetLastError(), WSAGetLastError() );
766 bind_addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
768 if ( connect( s, (struct sockaddr *)&bind_addr, sizeof( struct sockaddr_in )) == SOCKET_ERROR ) {
769 Debug( LDAP_DEBUG_ANY,
770 "hit_socket: error on connect: %d\n", WSAGetLastError(), 0 );
771 /* we can probably expect some error to occur here, mostly WSAEWOULDBLOCK */
780 if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
783 daemon_initialized = 1;
788 daemon_initialized = 1;
794 slap_set_shutdown( int sig )
796 slapd_shutdown = sig;
799 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
802 Debug( LDAP_DEBUG_TRACE, "Shutdown %d ordered", sig, 0 );
803 // trying to "hit" the socket seems to always get a
804 // EWOULDBLOCK error, so just close the listen socket to
805 // break out of the select since we're shutting down anyway
809 (void) SIGNAL( sig, slap_set_shutdown );
813 slap_do_nothing( int sig )
816 (void) SIGNAL( sig, slap_do_nothing );