11 #include <ac/unistd.h>
13 #include "ldapconfig.h"
16 #ifdef HAVE_SYS_FILIO_H
17 #include <sys/filio.h>
18 #elif HAVE_SYS_IOCTL_H
19 #include <sys/ioctl.h>
25 int allow_severity = LOG_INFO;
26 int deny_severity = LOG_NOTICE;
27 #endif /* TCP Wrappers */
32 static ldap_pvt_thread_t listener_tid;
33 static volatile sig_atomic_t slapd_shutdown = 0;
36 ldap_pvt_thread_mutex_t sd_mutex;
41 /* In winsock, accept() returns values higher than dtblsize
42 so don't bother with this optimization */
52 * Add a descriptor to daemon control
54 static void slapd_add(int s) {
55 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
57 assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
58 assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
59 assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
62 if (s >= slap_daemon.sd_nfds) {
63 slap_daemon.sd_nfds = s + 1;
67 FD_SET( s, &slap_daemon.sd_actives );
68 FD_SET( s, &slap_daemon.sd_readers );
70 Debug( LDAP_DEBUG_CONNS, "daemon: added %d%s%s\n", s,
71 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
72 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
74 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
78 * Remove the descriptor from daemon control
80 void slapd_remove(int s) {
81 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
83 assert( FD_ISSET( s, &slap_daemon.sd_actives ));
85 Debug( LDAP_DEBUG_CONNS, "daemon: removing %d%s%s\n", s,
86 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
87 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
89 FD_CLR( s, &slap_daemon.sd_actives );
90 FD_CLR( s, &slap_daemon.sd_readers );
91 FD_CLR( s, &slap_daemon.sd_writers );
93 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
96 void slapd_clr_write(int s, int wake) {
97 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
99 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
100 FD_CLR( s, &slap_daemon.sd_writers );
102 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
105 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
109 void slapd_set_write(int s, int wake) {
110 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
112 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
113 FD_SET( s, &slap_daemon.sd_writers );
115 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
118 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
122 void slapd_clr_read(int s, int wake) {
123 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
125 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
126 FD_CLR( s, &slap_daemon.sd_readers );
128 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
131 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
135 void slapd_set_read(int s, int wake) {
136 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
138 assert( FD_ISSET( s, &slap_daemon.sd_actives) );
139 FD_SET( s, &slap_daemon.sd_readers );
141 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
144 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
148 static void slapd_close(int s) {
151 Debug( LDAP_DEBUG_CONNS, "daemon: closing %d\n", s, 0, 0 );
160 struct sockaddr_in *addr = ptr;
164 dtblsize = sysconf( _SC_OPEN_MAX );
165 #elif HAVE_GETDTABLESIZE
166 dtblsize = getdtablesize();
168 dtblsize = FD_SETSIZE
172 if(dtblsize > FD_SETSIZE) {
173 dtblsize = FD_SETSIZE;
175 #endif /* !FD_SETSIZE */
179 ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
180 FD_ZERO( &slap_daemon.sd_readers );
181 FD_ZERO( &slap_daemon.sd_writers );
186 if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
187 Debug( LDAP_DEBUG_ANY,
188 "daemon: socket() failed errno %d (%s)", errno,
189 errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
195 if ( tcps >= dtblsize ) {
196 Debug( LDAP_DEBUG_ANY,
197 "daemon: listener descriptor %d is too great",
204 if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR,
205 (char *) &tmp, sizeof(tmp) ) == -1 )
207 Debug( LDAP_DEBUG_ANY,
208 "slapd(%d): setsockopt() failed errno %d (%s)",
210 errno > -1 && errno < sys_nerr
211 ? sys_errlist[errno] : "unknown" );
216 if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
217 Debug( LDAP_DEBUG_ANY, "daemon: bind(%d) failed errno %d (%s)\n",
219 errno > -1 && errno < sys_nerr
220 ? sys_errlist[errno] : "unknown" );
224 if ( listen( tcps, 5 ) == -1 ) {
225 Debug( LDAP_DEBUG_ANY,
226 "daemon: listen(%d, 5) failed errno %d (%s)\n",
228 errno > -1 && errno < sys_nerr
229 ? sys_errlist[errno] : "unknown" );
236 if( connection_init( 0, NULL, NULL ) ) {
237 Debug( LDAP_DEBUG_ANY,
238 "connection_init(%d) failed.\n",
247 while ( !slapd_shutdown ) {
253 struct sockaddr_in from;
261 FD_ZERO( &writefds );
267 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
269 #ifdef FD_SET_MANUAL_COPY
270 for( s = 0; s < nfds; s++ ) {
271 if(FD_ISSET( &slap_sd_writers, s )) {
272 FD_SET( &writefds, s );
274 if(FD_ISSET( &slap_sd_writers, s )) {
275 FD_SET( &writefds, s );
279 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
280 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
283 FD_SET( tcps, &readfds );
286 nfds = slap_daemon.sd_nfds;
291 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
293 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
294 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
297 tvp = active_threads ? &zero : NULL;
300 Debug( LDAP_DEBUG_CONNS,
301 "daemon: select: tcps=%d active_threads=%d tvp=%s\n",
302 tcps, active_threads,
303 tvp == NULL ? "NULL" : "zero" );
306 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
308 switch(ns = select( nfds, &readfds, &writefds, 0, tvp )) {
309 case -1: /* failure - try again */
310 if( errno != EINTR ) {
311 Debug( LDAP_DEBUG_CONNS,
312 "daemon: select failed (%d): %s\n",
314 errno >= 0 && errno < sys_nerr
315 ? sys_errlist[errno] : "unknown",
323 case 0: /* timeout - let threads run */
324 Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
326 ldap_pvt_thread_yield();
329 default: /* something happened - deal with it */
330 Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
335 if ( FD_ISSET( tcps, &readfds ) ) {
337 int len = sizeof(from);
340 if ( (s = accept( tcps,
341 (struct sockaddr *) &from, &len )) == -1 )
343 Debug( LDAP_DEBUG_ANY,
344 "daemon: accept(%d) failed errno %d (%s)", errno,
345 tcps, errno >= 0 && errno < sys_nerr ?
346 sys_errlist[errno] : "unknown");
350 assert( !FD_ISSET( 0, &slap_daemon.sd_actives) );
351 assert( !FD_ISSET( 0, &slap_daemon.sd_readers) );
352 assert( !FD_ISSET( 0, &slap_daemon.sd_writers) );
355 /* make sure descriptor number isn't too great */
356 if ( s >= dtblsize ) {
357 Debug( LDAP_DEBUG_ANY,
358 "daemon: %d beyond descriptor table size %d\n",
365 Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %d\n",
369 if ( getpeername( s, (struct sockaddr *) &from, &len ) == 0 ) {
370 client_addr = inet_ntoa( from.sin_addr );
372 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
373 hp = gethostbyaddr( (char *)
374 &(from.sin_addr.s_addr),
375 sizeof(from.sin_addr.s_addr), AF_INET );
379 client_name = hp->h_name;
381 /* normalize the domain */
382 for ( p = client_name; *p; p++ ) {
383 *p = TOLOWER( (unsigned char) *p );
399 if(!hosts_ctl("slapd",
400 client_name != NULL ? client_name : STRING_UNKNOWN,
401 client_addr != NULL ? client_addr : STRING_UNKNOWN,
405 Statslog( LDAP_DEBUG_ANY,
406 "fd=%d connection from %s (%s) denied.\n",
408 client_name == NULL ? "unknown" : client_name,
409 client_addr == NULL ? "unknown" : client_addr,
415 #endif /* HAVE_TCPD */
417 if( (id = connection_init(s, client_name, client_addr)) < 0 ) {
418 Debug( LDAP_DEBUG_ANY,
419 "daemon: connection_init(%d, %s, %s) failed.\n",
421 client_name == NULL ? "unknown" : client_name,
422 client_addr == NULL ? "unknown" : client_addr);
427 Statslog( LDAP_DEBUG_STATS,
428 "daemon: conn=%d fd=%d connection from %s (%s) accepted.\n",
430 client_name == NULL ? "unknown" : client_name,
431 client_addr == NULL ? "unknown" : client_addr,
439 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
441 for ( i = 0; i < nfds; i++ ) {
444 r = FD_ISSET( i, &readfds );
445 w = FD_ISSET( i, &writefds );
446 if ( i != tcps && (r || w) ) {
447 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
448 r ? "r" : "", w ? "w" : "" );
452 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
455 /* loop through the writers */
456 for ( i = 0; i < nfds; i++ ) {
461 if ( FD_ISSET( i, &writefds ) ) {
462 Debug( LDAP_DEBUG_CONNS,
463 "daemon: signaling write waiter on %d\n", i, 0, 0 );
465 assert( FD_ISSET( 0, &slap_daemon.sd_actives) );
467 /* clear the write flag */
468 slapd_clr_write( i, 0 );
470 if( connection_write( i ) < 0 ) {
471 FD_CLR( i, &readfds );
477 for ( i = 0; i < nfds; i++ ) {
482 if ( FD_ISSET( i, &readfds ) ) {
483 Debug( LDAP_DEBUG_CONNS,
484 "daemon: read activity on %d\n", i, 0, 0 );
486 assert( FD_ISSET( i, &slap_daemon.sd_actives) );
488 if( connection_read( i ) < 0) {
494 ldap_pvt_thread_yield();
497 if( slapd_shutdown > 0 ) {
498 Debug( LDAP_DEBUG_TRACE,
499 "daemon: shutdown requested and initiated.\n",
502 } else if ( slapd_shutdown < 0 ) {
503 Debug( LDAP_DEBUG_TRACE,
504 "daemon: abnormal condition, shutdown initiated.\n",
507 Debug( LDAP_DEBUG_TRACE,
508 "daemon: no active streams, shutdown initiated.\n",
516 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
517 Debug( LDAP_DEBUG_ANY,
518 "slapd shutdown: waiting for %d threads to terminate\n",
519 active_threads, 0, 0 );
520 while ( active_threads > 0 ) {
521 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
523 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
528 int slapd_daemon( struct sockaddr_in *addr )
532 status = ldap_pvt_thread_create( &listener_tid, 0,
533 slapd_daemon_task, addr );
536 Debug( LDAP_DEBUG_ANY,
537 "listener ldap_pvt_thread_create failed (%d)\n", status, 0, 0 );
540 /* wait for the listener thread to complete */
541 ldap_pvt_thread_join( listener_tid, (void *) NULL );
548 slap_set_shutdown( int sig )
551 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
554 (void) SIGNAL( sig, slap_set_shutdown );
558 slap_do_nothing( int sig )
561 (void) SIGNAL( sig, slap_do_nothing );