3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
13 #include <ac/signal.h>
14 #include <ac/socket.h>
15 #include <ac/string.h>
17 #include <ac/unistd.h>
26 int allow_severity = LOG_INFO;
27 int deny_severity = LOG_NOTICE;
28 #endif /* TCP Wrappers */
32 #endif /* LDAP_PF_LOCAL */
36 ber_socket_t dtblsize;
39 typedef union slap_sockaddr {
40 struct sockaddr sa_addr;
41 struct sockaddr_in sa_in_addr;
42 struct sockaddr_un sa_un_addr;
44 #endif /* LDAP_PF_LOCAL */
46 typedef struct slap_listener {
55 #define sl_addr sl_sa.sa_in_addr
57 struct sockaddr_in sl_addr;
58 #endif /* LDAP_PF_LOCAL */
61 Listener **slap_listeners = NULL;
63 static ber_socket_t wake_sds[2];
67 #define WAKE_LISTENER(w) \
68 ((w && !waking) ? tcp_write( wake_sds[1], "0", 1 ), waking=1 : 0)
70 #define WAKE_LISTENER(w) \
71 do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
74 #ifdef HAVE_NT_SERVICE_MANAGER
76 extern ldap_pvt_thread_cond_t started_event;
77 extern int is_NT_Service;
83 volatile sig_atomic_t slapd_shutdown = 0;
85 static ldap_pvt_thread_t listener_tid;
87 static struct slap_daemon {
88 ldap_pvt_thread_mutex_t sd_mutex;
93 /* In winsock, accept() returns values higher than dtblsize
94 so don't bother with this optimization */
104 * Add a descriptor to daemon control
106 static void slapd_add(ber_socket_t s) {
107 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
109 assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
110 assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
111 assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
114 if (s >= slap_daemon.sd_nfds) {
115 slap_daemon.sd_nfds = s + 1;
119 FD_SET( s, &slap_daemon.sd_actives );
120 FD_SET( s, &slap_daemon.sd_readers );
122 Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
124 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
125 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
127 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
131 * Remove the descriptor from daemon control
133 void slapd_remove(ber_socket_t s, int wake) {
134 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
136 Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
138 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
139 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
141 FD_CLR( s, &slap_daemon.sd_actives );
142 FD_CLR( s, &slap_daemon.sd_readers );
143 FD_CLR( s, &slap_daemon.sd_writers );
145 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
149 void slapd_clr_write(ber_socket_t s, int wake) {
150 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
152 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
153 FD_CLR( s, &slap_daemon.sd_writers );
155 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
159 void slapd_set_write(ber_socket_t s, int wake) {
160 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
162 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
163 if (!FD_ISSET(s, &slap_daemon.sd_writers))
164 FD_SET( (unsigned) s, &slap_daemon.sd_writers );
166 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
170 void slapd_clr_read(ber_socket_t s, int wake) {
171 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
173 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
174 FD_CLR( s, &slap_daemon.sd_readers );
176 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
180 void slapd_set_read(ber_socket_t s, int wake) {
181 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
183 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
184 if (!FD_ISSET(s, &slap_daemon.sd_readers))
185 FD_SET( s, &slap_daemon.sd_readers );
187 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
191 static void slapd_close(ber_socket_t s) {
192 Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
198 static Listener * open_listener( const char* url )
207 rc = ldap_url_parse( url, &lud );
209 if( rc != LDAP_URL_SUCCESS ) {
210 Debug( LDAP_DEBUG_ANY,
211 "daemon: listen URL \"%s\" parse error=%d\n",
217 if( lud->lud_properties & LDAP_URL_USE_SSL ) {
218 Debug( LDAP_DEBUG_ANY,
219 "daemon: TLS not supported (%s)\n",
221 ldap_free_urldesc( lud );
225 if(! lud->lud_port ) {
226 lud->lud_port = LDAP_PORT;
230 l.sl_is_tls = (lud->lud_properties & LDAP_URL_USE_SSL);
232 if(! lud->lud_port ) {
233 lud->lud_port = (lud->lud_properties & LDAP_URL_USE_SSL) ? LDAPS_PORT : LDAP_PORT;
238 if (lud->lud_protocol == LDAP_PROTO_LOCAL) {
240 (void) memset( (void *)&l.sl_sa.sa_un_addr, '\0', sizeof(l.sl_sa.sa_un_addr) );
242 l.sl_sa.sa_un_addr.sun_family = AF_UNIX;
244 /* hack: overload the host to be the path */
245 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
246 strcpy( l.sl_sa.sa_un_addr.sun_path, "/tmp/.ldap-sock" );
248 if ( strlen(lud->lud_host) > (sizeof(l.sl_sa.sa_un_addr.sun_path) - 1) ) {
249 Debug( LDAP_DEBUG_ANY, "domain socket path (%s) too long in URL: %s",
250 lud->lud_host, url, 0);
251 ldap_free_urldesc( lud );
254 strcpy( l.sl_sa.sa_un_addr.sun_path, lud->lud_host );
256 unlink( l.sl_sa.sa_un_addr.sun_path );
258 /* I don't think we need to set this. */
259 l.sl_sa.sa_un_addr.sun_len = sizeof( l.sl_sa.sa_un_addr.sun_len ) +
260 sizeof( l.sl_sa.sa_un_addr.sun_family ) +
261 strlen( l.sl_sa.sa_un_addr.sun_path ) + 1;
264 #endif /* LDAP_PF_LOCAL */
266 port = lud->lud_port;
268 (void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
270 l.sl_addr.sin_family = AF_INET;
271 l.sl_addr.sin_port = htons( (unsigned short) lud->lud_port );
273 if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
274 || strcmp(lud->lud_host, "*") == 0 )
276 l.sl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
279 /* host or address was specified */
280 if( !inet_aton( lud->lud_host, &l.sl_addr.sin_addr ) ) {
281 struct hostent *he = gethostbyname( lud->lud_host );
283 Debug( LDAP_DEBUG_ANY, "invalid host (%s) in URL: %s",
284 lud->lud_host, url, 0);
285 ldap_free_urldesc( lud );
289 memcpy( &l.sl_addr.sin_addr, he->h_addr,
290 sizeof( l.sl_addr.sin_addr ) );
295 #endif /* LDAP_PF_LOCAL */
297 ldap_free_urldesc( lud );
300 l.sl_sd = socket( l.sl_sa.sa_addr.sa_family, SOCK_STREAM, 0 );
301 if ( l.sl_sd == AC_SOCKET_INVALID ) {
303 if ( (l.sl_sd = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID ) {
304 #endif /* LDAP_PF_LOCAL */
305 int err = sock_errno();
306 Debug( LDAP_DEBUG_ANY,
307 "daemon: socket() failed errno=%d (%s)\n", err,
308 sock_errstr(err), 0 );
313 if ( l.sl_sd >= dtblsize ) {
314 Debug( LDAP_DEBUG_ANY,
315 "daemon: listener descriptor %ld is too great %ld\n",
316 (long) l.sl_sd, (long) dtblsize, 0 );
317 tcp_close( l.sl_sd );
323 /* for IP sockets only */
324 if ( l.sl_sa.sa_addr.sa_family == AF_INET ) {
325 #endif /* LDAP_PF_LOCAL */
328 /* enable address reuse */
330 rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
331 (char *) &tmp, sizeof(tmp) );
332 if ( rc == AC_SOCKET_ERROR ) {
333 int err = sock_errno();
334 Debug( LDAP_DEBUG_ANY,
335 "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
336 (long) l.sl_sd, err, sock_errstr(err) );
340 /* enable keep alives */
342 rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_KEEPALIVE,
343 (char *) &tmp, sizeof(tmp) );
344 if ( rc == AC_SOCKET_ERROR ) {
345 int err = sock_errno();
346 Debug( LDAP_DEBUG_ANY,
347 "slapd(%ld): setsockopt(SO_KEEPALIVE) failed errno=%d (%s)\n",
348 (long) l.sl_sd, err, sock_errstr(err) );
352 /* enable no delay */
354 rc = setsockopt( l.sl_sd, IPPROTO_TCP, TCP_NODELAY,
355 (char *)&tmp, sizeof(tmp) );
356 if ( rc == AC_SOCKET_ERROR ) {
357 int err = sock_errno();
358 Debug( LDAP_DEBUG_ANY,
359 "slapd(%ld): setsockopt(TCP_NODELAY) failed errno=%d (%s)\n",
360 (long) l.sl_sd, err, sock_errstr(err) );
365 /* close conditional */
368 switch ( l.sl_sa.sa_addr.sa_family ) {
370 rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
371 sizeof(l.sl_sa.sa_un_addr) );
374 rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
375 sizeof(l.sl_sa.sa_in_addr) );
378 rc = AC_SOCKET_ERROR;
383 rc = bind( l.sl_sd, (struct sockaddr *) &l.sl_addr, sizeof(l.sl_addr) );
384 #endif /* LDAP_PF_LOCAL */
385 if ( rc == AC_SOCKET_ERROR ) {
386 int err = sock_errno();
387 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
388 (long) l.sl_sd, err, sock_errstr(err) );
389 tcp_close( l.sl_sd );
393 if ( l.sl_sa.sa_addr.sa_family == AF_UNIX ) {
394 if ( chmod( l.sl_sa.sa_un_addr.sun_path, S_IRWXU ) < 0 ) {
395 int err = sock_errno();
396 Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
397 (long) l.sl_sd, err, sock_errstr(err) );
398 tcp_close( l.sl_sd );
402 #endif /* LDAP_PF_LOACL */
403 l.sl_url = ch_strdup( url );
405 switch ( l.sl_sa.sa_addr.sa_family ) {
407 l.sl_name = ch_malloc( strlen(l.sl_sa.sa_un_addr.sun_path) + sizeof("PATH=") );
408 sprintf( l.sl_name, "PATH=%s", l.sl_sa.sa_un_addr.sun_path );
411 l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
412 s = inet_ntoa( l.sl_addr.sin_addr );
413 sprintf( l.sl_name, "IP=%s:%d",
414 s != NULL ? s : "unknown" , port );
417 l.sl_name = ch_strdup( "UNKNOWN" );
421 l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
422 s = inet_ntoa( l.sl_addr.sin_addr );
423 sprintf( l.sl_name, "IP=%s:%d",
424 s != NULL ? s : "unknown" , port );
425 #endif /* LDAP_PF_LOCAL */
427 li = ch_malloc( sizeof( Listener ) );
430 Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
436 static int sockinit(void);
437 static int sockdestroy(void);
439 int slapd_daemon_init( const char *urls )
444 Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
445 urls ? urls : "<null>", 0, 0 );
447 if( (rc = sockinit()) != 0 ) {
452 dtblsize = sysconf( _SC_OPEN_MAX );
453 #elif HAVE_GETDTABLESIZE
454 dtblsize = getdtablesize();
456 dtblsize = FD_SETSIZE;
460 if(dtblsize > FD_SETSIZE) {
461 dtblsize = FD_SETSIZE;
463 #endif /* !FD_SETSIZE */
465 /* open a pipe (or something equivalent connected to itself).
466 * we write a byte on this fd whenever we catch a signal. The main
467 * loop will be select'ing on this socket, and will wake up when
470 if( (rc = lutil_pair( wake_sds )) < 0 ) {
471 Debug( LDAP_DEBUG_ANY,
472 "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
476 FD_ZERO( &slap_daemon.sd_readers );
477 FD_ZERO( &slap_daemon.sd_writers );
483 u = str2charray( urls, " " );
485 if( u == NULL || u[0] == NULL ) {
486 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
492 for( i=0; u[i] != NULL; i++ ) {
493 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
498 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
504 Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
507 slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
509 for(i = 0; u[i] != NULL; i++ ) {
510 slap_listeners[i] = open_listener( u[i] );
512 if( slap_listeners[i] == NULL ) {
517 slap_listeners[i] = NULL;
519 Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
523 ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
529 slapd_daemon_destroy(void)
531 connections_destroy();
532 tcp_close( wake_sds[1] );
533 tcp_close( wake_sds[0] );
545 time_t last_idle_check = slap_get_time();
548 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
549 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
552 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
553 int err = sock_errno();
554 Debug( LDAP_DEBUG_ANY,
555 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
556 slap_listeners[l]->sl_url, err,
561 slapd_add( slap_listeners[l]->sl_sd );
564 #ifdef HAVE_NT_SERVICE_MANAGER
565 if ( started_event != NULL ) {
566 ldap_pvt_thread_cond_signal( &started_event );
569 /* initialization complete. Here comes the loop. */
571 while ( !slapd_shutdown ) {
576 #define SLAPD_EBADF_LIMIT 10
579 #define SLAPD_IDLE_CHECK_LIMIT 4
580 time_t now = slap_get_time();
587 /* minimize impact, undefine later. */
588 #define sin_addr sa_in_addr.sin_addr
589 #define sin_port sa_in_addr.sin_port
591 struct sockaddr_in from;
592 #endif /* LDAP_PF_LOCAL */
593 #if defined(SLAPD_RLOOKUPS)
599 if( global_idletimeout > 0 && difftime(
600 last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
603 connections_timeout_idle(now);
606 FD_ZERO( &writefds );
612 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
614 #ifdef FD_SET_MANUAL_COPY
615 for( s = 0; s < nfds; s++ ) {
616 if(FD_ISSET( &slap_sd_readers, s )) {
617 FD_SET( s, &readfds );
619 if(FD_ISSET( &slap_sd_writers, s )) {
620 FD_SET( s, &writefds );
624 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
625 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
627 assert(!FD_ISSET(wake_sds[0], &readfds));
628 FD_SET( wake_sds[0], &readfds );
630 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
631 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
633 if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
634 FD_SET( slap_listeners[l]->sl_sd, &readfds );
638 nfds = slap_daemon.sd_nfds;
643 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
645 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
647 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
649 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
652 tvp = at ? &zero : NULL;
655 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
656 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
659 Debug( LDAP_DEBUG_CONNS,
660 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
661 slap_listeners[l]->sl_sd, at,
662 tvp == NULL ? "NULL" : "zero" );
665 switch(ns = select( nfds, &readfds,
667 /* don't pass empty fd_set */
668 ( writefds.fd_count > 0 ? &writefds : NULL ),
674 case -1: { /* failure - try again */
675 int err = sock_errno();
679 || err == WSAENOTSOCK /* you'd think this would be EBADF */
682 if (++ebadf < SLAPD_EBADF_LIMIT)
687 Debug( LDAP_DEBUG_CONNS,
688 "daemon: select failed (%d): %s\n",
689 err, sock_errstr(err), 0 );
696 case 0: /* timeout - let threads run */
698 Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
700 ldap_pvt_thread_yield();
703 default: /* something happened - deal with it */
705 Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
710 if( FD_ISSET( wake_sds[0], &readfds ) ) {
712 tcp_read( wake_sds[0], c, sizeof(c) );
719 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
721 socklen_t len = sizeof(from);
727 char peername[MAXPATHLEN + sizeof("PATH=")];
729 char peername[sizeof("IP=255.255.255.255:65336")];
730 #endif /* LDAP_PF_LOCAL */
731 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
734 if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
737 if ( (s = accept( slap_listeners[l]->sl_sd,
738 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
740 int err = sock_errno();
741 Debug( LDAP_DEBUG_ANY,
742 "daemon: accept(%ld) failed errno=%d (%s)\n",
743 (long) slap_listeners[l]->sl_sd, err,
749 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
751 /* newly accepted stream should not be in any of the FD SETS */
753 assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
754 assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
755 assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
757 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
761 /* make sure descriptor number isn't too great */
762 if ( s >= dtblsize ) {
763 Debug( LDAP_DEBUG_ANY,
764 "daemon: %ld beyond descriptor table size %ld\n",
765 (long) s, (long) dtblsize, 0 );
771 Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
776 if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
777 int err = sock_errno();
778 Debug( LDAP_DEBUG_ANY,
779 "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
780 (long) s, err, sock_errstr(err) );
786 switch ( from.sa_addr.sa_family ) {
788 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
791 #endif /* LDAP_PF_LOCAL */
792 peeraddr = inet_ntoa( from.sin_addr );
793 sprintf( peername, "IP=%s:%d",
794 peeraddr != NULL ? peeraddr : "unknown",
795 (unsigned) ntohs( from.sin_port ) );
797 #if defined(SLAPD_RLOOKUPS)
798 hp = gethostbyaddr( (char *)
800 sizeof(from.sin_addr), AF_INET );
803 dnsname = ldap_pvt_str2lower( hp->h_name );
813 if( !hosts_ctl("slapd",
814 dnsname != NULL ? dnsname : STRING_UNKNOWN,
815 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
819 Statslog( LDAP_DEBUG_ANY,
820 "fd=%ld connection from %s (%s) denied.\n",
822 dnsname != NULL ? dnsname : "unknown",
823 peeraddr != NULL ? peeraddr : "unknown",
829 #endif /* HAVE_TCPD */
838 #endif /* LDAP_PF_LOCAL */
840 if( (id = connection_init(s,
841 slap_listeners[l]->sl_url,
842 dnsname != NULL ? dnsname : "unknown",
844 slap_listeners[l]->sl_name,
846 slap_listeners[l]->sl_is_tls
852 Debug( LDAP_DEBUG_ANY,
853 "daemon: connection_init(%ld, %s, %s) failed.\n",
856 slap_listeners[l]->sl_name );
861 Statslog( LDAP_DEBUG_STATS,
862 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
865 slap_listeners[l]->sl_name,
873 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
875 for ( i = 0; i < readfds.fd_count; i++ ) {
876 Debug( LDAP_DEBUG_CONNS, " %d%s",
877 readfds.fd_array[i], "r", 0 );
879 for ( i = 0; i < writefds.fd_count; i++ ) {
880 Debug( LDAP_DEBUG_CONNS, " %d%s",
881 writefds.fd_array[i], "w", 0 );
884 for ( i = 0; i < nfds; i++ ) {
888 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
889 if ( i == slap_listeners[l]->sl_sd ) {
897 r = FD_ISSET( i, &readfds );
898 w = FD_ISSET( i, &writefds );
900 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
901 r ? "r" : "", w ? "w" : "" );
905 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
908 /* loop through the writers */
910 for ( i = 0; i < writefds.fd_count; i++ )
912 for ( i = 0; i < nfds; i++ )
918 wd = writefds.fd_array[i];
920 if( ! FD_ISSET( i, &writefds ) ) {
926 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
927 if ( i == slap_listeners[l]->sl_sd ) {
935 Debug( LDAP_DEBUG_CONNS,
936 "daemon: write active on %d\n",
940 * NOTE: it is possible that the connection was closed
941 * and that the stream is now inactive.
942 * connection_write() must valid the stream is still
946 if ( connection_write( wd ) < 0 ) {
947 FD_CLR( (unsigned) wd, &readfds );
953 for ( i = 0; i < readfds.fd_count; i++ )
955 for ( i = 0; i < nfds; i++ )
962 rd = readfds.fd_array[i];
964 if( ! FD_ISSET( i, &readfds ) ) {
970 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
971 if ( rd == slap_listeners[l]->sl_sd ) {
980 Debug ( LDAP_DEBUG_CONNS,
981 "daemon: read activity on %d\n", rd, 0, 0 );
984 * NOTE: it is possible that the connection was closed
985 * and that the stream is now inactive.
986 * connection_read() must valid the stream is still
990 if ( connection_read( rd ) < 0 ) {
994 ldap_pvt_thread_yield();
997 if( slapd_shutdown > 0 ) {
998 Debug( LDAP_DEBUG_TRACE,
999 "daemon: shutdown requested and initiated.\n",
1002 } else if ( slapd_shutdown < 0 ) {
1003 #ifdef HAVE_NT_SERVICE_MANAGER
1004 if (slapd_shutdown == -1)
1005 Debug( LDAP_DEBUG_TRACE,
1006 "daemon: shutdown initiated by Service Manager.\n",
1010 Debug( LDAP_DEBUG_TRACE,
1011 "daemon: abnormal condition, shutdown initiated.\n",
1014 Debug( LDAP_DEBUG_TRACE,
1015 "daemon: no active streams, shutdown initiated.\n",
1019 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1020 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1021 #ifdef LDAP_PF_LOCAL
1022 if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_UNIX ) {
1023 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1025 #endif /* LDAP_PF_LOCAL */
1026 slapd_close( slap_listeners[l]->sl_sd );
1031 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
1032 Debug( LDAP_DEBUG_ANY,
1033 "slapd shutdown: waiting for %d threads to terminate\n",
1034 active_threads, 0, 0 );
1035 while ( active_threads > 0 ) {
1036 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
1038 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
1044 int slapd_daemon( void )
1050 #define SLAPD_LISTENER_THREAD 1
1051 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
1053 /* listener as a separate THREAD */
1054 rc = ldap_pvt_thread_create( &listener_tid,
1055 0, slapd_daemon_task, NULL );
1058 Debug( LDAP_DEBUG_ANY,
1059 "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1063 /* wait for the listener thread to complete */
1064 ldap_pvt_thread_join( listener_tid, (void *) NULL );
1066 /* expermimental code */
1067 listener_tid = pthread_self();
1068 slapd_daemon_task( NULL );
1075 #ifdef HAVE_WINSOCK2
1078 WORD wVersionRequested;
1082 wVersionRequested = MAKEWORD( 2, 0 );
1084 err = WSAStartup( wVersionRequested, &wsaData );
1086 /* Tell the user that we couldn't find a usable */
1091 /* Confirm that the WinSock DLL supports 2.0.*/
1092 /* Note that if the DLL supports versions greater */
1093 /* than 2.0 in addition to 2.0, it will still return */
1094 /* 2.0 in wVersion since that is the version we */
1097 if ( LOBYTE( wsaData.wVersion ) != 2 ||
1098 HIBYTE( wsaData.wVersion ) != 0 )
1100 /* Tell the user that we couldn't find a usable */
1106 /* The WinSock DLL is acceptable. Proceed. */
1110 int sockdestroy(void)
1117 static int sockinit(void)
1120 if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1125 static int sockdestroy(void)
1132 static int sockinit(void)
1136 static int sockdestroy(void)
1143 slap_sig_shutdown( int sig )
1145 Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
1148 * If the NT Service Manager is controlling the server, we don't
1149 * want SIGBREAK to kill the server. For some strange reason,
1150 * SIGBREAK is generated when a user logs out.
1153 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
1154 if (is_NT_Service && sig == SIGBREAK)
1155 Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
1159 slapd_shutdown = sig;
1163 /* reinstall self */
1164 (void) SIGNAL( sig, slap_sig_shutdown );
1168 slap_sig_wake( int sig )
1172 /* reinstall self */
1173 (void) SIGNAL( sig, slap_sig_wake );