]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
bca5aed17b2b2f358647836dfacc36c3e1ec8a5d
[openldap] / servers / slapd / daemon.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/ctype.h>
12 #include <ac/errno.h>
13 #include <ac/signal.h>
14 #include <ac/socket.h>
15 #include <ac/string.h>
16 #include <ac/time.h>
17 #include <ac/unistd.h>
18
19 #include "ldap_pvt.h"
20 #include "lutil.h"
21 #include "slap.h"
22
23 #ifdef HAVE_TCPD
24 #include <tcpd.h>
25
26 int allow_severity = LOG_INFO;
27 int deny_severity = LOG_NOTICE;
28 #endif /* TCP Wrappers */
29
30 #ifdef LDAP_PF_LOCAL
31 #include <sys/stat.h>
32 #endif /* LDAP_PF_LOCAL */
33
34 /* globals */
35 time_t starttime;
36 ber_socket_t dtblsize;
37
38 typedef union slap_sockaddr {
39         struct sockaddr sa_addr;
40         struct sockaddr_in sa_in_addr;
41 #ifdef LDAP_PF_INET6
42         struct sockaddr_in6 sa_in6_addr;
43 #endif
44 #ifdef LDAP_PF_LOCAL
45         struct sockaddr_un sa_un_addr;
46 #endif
47 } Sockaddr;
48
49 typedef struct slap_listener {
50         char* sl_url;
51         char* sl_name;
52 #ifdef HAVE_TLS
53         int             sl_is_tls;
54 #endif
55         ber_socket_t            sl_sd;
56         Sockaddr sl_sa;
57 #define sl_addr sl_sa.sa_in_addr
58 } Listener;
59
60 Listener **slap_listeners = NULL;
61
62 static ber_socket_t wake_sds[2];
63
64 #ifdef NO_THREADS
65 static int waking;
66 #define WAKE_LISTENER(w) \
67 ((w && !waking) ? tcp_write( wake_sds[1], "0", 1 ), waking=1 : 0)
68 #else
69 #define WAKE_LISTENER(w) \
70 do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
71 #endif
72
73 #ifdef HAVE_NT_SERVICE_MANAGER
74 /* in nt_main.c */
75 extern ldap_pvt_thread_cond_t                   started_event;
76 extern int        is_NT_Service;
77 #endif
78
79 #ifndef HAVE_WINSOCK
80 static 
81 #endif
82 volatile sig_atomic_t slapd_shutdown = 0;
83
84 static ldap_pvt_thread_t        listener_tid;
85
86 static struct slap_daemon {
87         ldap_pvt_thread_mutex_t sd_mutex;
88
89         int sd_nactives;
90
91 #ifndef HAVE_WINSOCK
92         /* In winsock, accept() returns values higher than dtblsize
93                 so don't bother with this optimization */
94         int sd_nfds;
95 #endif
96
97         fd_set sd_actives;
98         fd_set sd_readers;
99         fd_set sd_writers;
100 } slap_daemon; 
101
102 /*
103  * Add a descriptor to daemon control
104  */
105 static void slapd_add(ber_socket_t s) {
106         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
107
108         assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
109         assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
110         assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
111
112 #ifndef HAVE_WINSOCK
113         if (s >= slap_daemon.sd_nfds) {
114                 slap_daemon.sd_nfds = s + 1;
115         }
116 #endif
117
118         FD_SET( s, &slap_daemon.sd_actives );
119         FD_SET( s, &slap_daemon.sd_readers );
120
121         Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
122                 (long) s,
123             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
124                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
125
126         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
127 }
128
129 /*
130  * Remove the descriptor from daemon control
131  */
132 void slapd_remove(ber_socket_t s, int wake) {
133         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
134
135         Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
136                 (long) s,
137             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
138                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
139
140         FD_CLR( s, &slap_daemon.sd_actives );
141         FD_CLR( s, &slap_daemon.sd_readers );
142         FD_CLR( s, &slap_daemon.sd_writers );
143
144         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
145         WAKE_LISTENER(wake);
146 }
147
148 void slapd_clr_write(ber_socket_t s, int wake) {
149         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
150
151         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
152         FD_CLR( s, &slap_daemon.sd_writers );
153
154         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
155         WAKE_LISTENER(wake);
156 }
157
158 void slapd_set_write(ber_socket_t s, int wake) {
159         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
160
161         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
162         if (!FD_ISSET(s, &slap_daemon.sd_writers))
163             FD_SET( (unsigned) s, &slap_daemon.sd_writers );
164
165         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
166         WAKE_LISTENER(wake);
167 }
168
169 void slapd_clr_read(ber_socket_t s, int wake) {
170         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
171
172         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
173         FD_CLR( s, &slap_daemon.sd_readers );
174
175         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
176         WAKE_LISTENER(wake);
177 }
178
179 void slapd_set_read(ber_socket_t s, int wake) {
180         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
181
182         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
183         if (!FD_ISSET(s, &slap_daemon.sd_readers))
184             FD_SET( s, &slap_daemon.sd_readers );
185
186         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
187         WAKE_LISTENER(wake);
188 }
189
190 static void slapd_close(ber_socket_t s) {
191         Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
192                 (long) s, 0, 0 );
193         tcp_close(s);
194 }
195
196
197 static Listener * open_listener( const char* url )
198 {
199         int     tmp, rc;
200         Listener l;
201         Listener *li;
202         LDAPURLDesc *lud;
203         char *s;
204         int port;
205 #ifdef HAVE_GETADDRINFO
206         char serv[7];
207         struct addrinfo hints, *res, *sai;
208         int err;
209 #endif
210
211         rc = ldap_url_parse( url, &lud );
212
213         if( rc != LDAP_URL_SUCCESS ) {
214                 Debug( LDAP_DEBUG_ANY,
215                         "daemon: listen URL \"%s\" parse error=%d\n",
216                         url, rc, 0 );
217                 return NULL;
218         }
219
220 #ifndef HAVE_TLS
221         if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
222                 Debug( LDAP_DEBUG_ANY,
223                         "daemon: TLS not supported (%s)\n",
224                         url, 0, 0 );
225                 ldap_free_urldesc( lud );
226                 return NULL;
227         }
228
229         if(! lud->lud_port ) {
230                 lud->lud_port = LDAP_PORT;
231         }
232
233 #else
234         l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );
235
236         if(! lud->lud_port ) {
237                 lud->lud_port = l.sl_is_tls ? LDAPS_PORT : LDAP_PORT;
238         }
239 #endif
240
241 #ifdef HAVE_GETADDRINFO
242         memset( &hints, '\0', sizeof(hints) );
243         hints.ai_flags = AI_PASSIVE;
244         hints.ai_family = AF_UNSPEC;
245         hints.ai_socktype = SOCK_STREAM;
246
247 #  ifdef LDAP_PF_LOCAL
248         if ( ldap_pvt_url_scheme2proto(lud->lud_scheme) == LDAP_PROTO_IPC ) {
249                 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
250                         err = getaddrinfo(NULL, LDAPI_SOCK, &hints, &res);
251                         if (!err)
252                                 unlink( LDAPI_SOCK );
253                 } else {
254                         err = getaddrinfo(NULL, lud->lud_host, &hints, &res);
255                         if (!err)
256                                 unlink( lud->lud_host );
257                 }
258         } else
259 #  endif /* LDAP_PF_LOCAL */
260         {
261                 snprintf(serv, sizeof serv, "%d", lud->lud_port);
262                 if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
263                         || strcmp(lud->lud_host, "*") == 0 )
264                 {
265                         err = getaddrinfo(NULL, serv, &hints, &res);
266                 } else {
267                         err = getaddrinfo(lud->lud_host, serv, &hints, &res);
268                 }
269         }
270
271         if ( err ) {
272                 Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed\n", 0, 0, 0);
273                 ldap_free_urldesc( lud );
274                 return NULL;
275         }
276
277         ldap_free_urldesc( lud );
278         sai = res;
279         do {
280                 if ( (sai->ai_family != AF_INET)
281 #  ifdef LDAP_PF_INET6
282                      && (sai->ai_family != AF_INET6)
283 #  endif
284 #  ifdef LDAP_PF_LOCAL
285                      && (sai->ai_family != AF_LOCAL)
286 #  endif
287                      )
288                         continue;
289                 l.sl_sd = socket( sai->ai_family, sai->ai_socktype, sai->ai_protocol);
290                 if ( l.sl_sd == AC_SOCKET_INVALID ) {
291                         int err = sock_errno();
292                         Debug( LDAP_DEBUG_ANY,
293                                 "daemon: socket() failed errno=%d (%s)\n", err,
294                                 sock_errstr(err), 0 );
295                         continue;
296                 }
297
298                 if ( sai->ai_family != AF_LOCAL ) {
299 #else
300
301         if ( ldap_pvt_url_scheme2proto(lud->lud_scheme) == LDAP_PROTO_IPC ) {
302 #ifdef LDAP_PF_LOCAL
303                 port = 0;
304                 (void) memset( (void *)&l.sl_sa.sa_un_addr, '\0', sizeof(l.sl_sa.sa_un_addr) );
305
306                 l.sl_sa.sa_un_addr.sun_family = AF_LOCAL;
307
308                 /* hack: overload the host to be the path */
309                 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
310                         strcpy( l.sl_sa.sa_un_addr.sun_path, LDAPI_SOCK );
311                 } else {
312                         if ( strlen(lud->lud_host) > (sizeof(l.sl_sa.sa_un_addr.sun_path) - 1) ) {
313                                 Debug( LDAP_DEBUG_ANY,
314                                         "daemon: domain socket path (%s) too long in URL: %s",
315                                         lud->lud_host, url, 0);
316                                 ldap_free_urldesc( lud );
317                                 return NULL;
318                         }
319                         strcpy( l.sl_sa.sa_un_addr.sun_path, lud->lud_host );
320                 }
321                 unlink( l.sl_sa.sa_un_addr.sun_path ); 
322 #if 0
323                 /* I don't think we need to set this. */
324                 l.sl_sa.sa_un_addr.sun_len = sizeof( l.sl_sa.sa_un_addr.sun_len ) +
325                         sizeof( l.sl_sa.sa_un_addr.sun_family ) +
326                         strlen( l.sl_sa.sa_un_addr.sun_path ) + 1;
327 #endif
328 #else
329                 Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s",
330                         url, 0, 0);
331                 ldap_free_urldesc( lud );
332                 return NULL;
333 #endif /* LDAP_PF_LOCAL */
334         } else {
335
336         port = lud->lud_port;
337
338         (void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
339
340         l.sl_addr.sin_family = AF_INET;
341         l.sl_addr.sin_port = htons( (unsigned short) lud->lud_port );
342
343         if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
344                 || strcmp(lud->lud_host, "*") == 0 )
345         {
346                 l.sl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
347
348         } else {
349                 /* host or address was specified */
350                 if( !inet_aton( lud->lud_host, &l.sl_addr.sin_addr ) ) {
351                         struct hostent *he = gethostbyname( lud->lud_host );
352                         if( he == NULL ) {
353                                 Debug( LDAP_DEBUG_ANY,
354                                         "daemon: invalid host (%s) in URL: %s",
355                                         lud->lud_host, url, 0);
356                                 ldap_free_urldesc( lud );
357                                 return NULL;
358                         }
359
360                         AC_MEMCPY( &l.sl_addr.sin_addr, he->h_addr,
361                                sizeof( l.sl_addr.sin_addr ) );
362                 }
363         }
364         }
365
366         ldap_free_urldesc( lud );
367
368         l.sl_sd = socket( l.sl_sa.sa_addr.sa_family, SOCK_STREAM, 0 );
369         if ( l.sl_sd == AC_SOCKET_INVALID ) {
370                 int err = sock_errno();
371                 Debug( LDAP_DEBUG_ANY,
372                         "daemon: socket() failed errno=%d (%s)\n", err,
373                         sock_errstr(err), 0 );
374                 return NULL;
375         }
376
377 #ifndef HAVE_WINSOCK
378         if ( l.sl_sd >= dtblsize ) {
379                 Debug( LDAP_DEBUG_ANY,
380                         "daemon: listener descriptor %ld is too great %ld\n",
381                         (long) l.sl_sd, (long) dtblsize, 0 );
382                 tcp_close( l.sl_sd );
383                 return NULL;
384         }
385 #endif
386
387 #ifdef LDAP_PF_LOCAL
388         /* for IPv4 and IPv6 sockets only */
389         if ( l.sl_sa.sa_addr.sa_family != AF_LOCAL ) {
390 #endif /* LDAP_PF_LOCAL */
391 #endif /* HAVE_GETADDRINFO */
392
393 #ifdef SO_REUSEADDR
394         /* enable address reuse */
395         tmp = 1;
396         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
397                 (char *) &tmp, sizeof(tmp) );
398         if ( rc == AC_SOCKET_ERROR ) {
399                 int err = sock_errno();
400                 Debug( LDAP_DEBUG_ANY,
401                "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
402                 (long) l.sl_sd, err, sock_errstr(err) );
403         }
404 #endif
405 #ifdef SO_KEEPALIVE
406         /* enable keep alives */
407         tmp = 1;
408         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_KEEPALIVE,
409                 (char *) &tmp, sizeof(tmp) );
410         if ( rc == AC_SOCKET_ERROR ) {
411                 int err = sock_errno();
412                 Debug( LDAP_DEBUG_ANY,
413                         "slapd(%ld): setsockopt(SO_KEEPALIVE) failed errno=%d (%s)\n",
414                 (long) l.sl_sd, err, sock_errstr(err) );
415         }
416 #endif
417 #ifdef TCP_NODELAY
418         /* enable no delay */
419         tmp = 1;
420         rc = setsockopt( l.sl_sd, IPPROTO_TCP, TCP_NODELAY,
421                 (char *)&tmp, sizeof(tmp) );
422         if ( rc == AC_SOCKET_ERROR ) {
423                 int err = sock_errno();
424                 Debug( LDAP_DEBUG_ANY,
425                         "slapd(%ld): setsockopt(TCP_NODELAY) failed errno=%d (%s)\n",
426                 (long) l.sl_sd, err, sock_errstr(err) );
427         }
428 #endif
429
430 #ifdef HAVE_GETADDRINFO
431                 } /* sai->ai_family != AF_LOCAL */
432                 if (!bind(l.sl_sd, sai->ai_addr, sai->ai_addrlen))
433                         break;
434                 err = sock_errno();
435                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
436                         (long) l.sl_sd, err, sock_errstr(err) );
437                 tcp_close( l.sl_sd );
438         } while ((sai = sai->ai_next) != NULL);
439
440         if (!sai) {
441                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed\n",
442                         (long) l.sl_sd, 0, 0 );
443                 return NULL;
444         }
445
446         switch ( sai->ai_family ) {
447 #  ifdef LDAP_PF_LOCAL
448         case AF_LOCAL:
449                 if ( chmod( (char *)sai->ai_addr, S_IRWXU ) < 0 ) {
450                         int err = sock_errno();
451                         Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
452                                 (long) l.sl_sd, err, sock_errstr(err) );
453                         tcp_close( l.sl_sd );
454                         return NULL;
455                 }
456                 l.sl_name = ch_malloc( strlen((char *)sai->ai_addr) + sizeof("PATH=") );
457                 sprintf( l.sl_name, "PATH=%s", sai->ai_addr );
458                 break;
459 #  endif /* LDAP_PF_LOCAL */
460
461         case AF_INET: {
462                 char addr[INET_ADDRSTRLEN];
463                 inet_ntop( AF_INET,
464                         &((struct sockaddr_in *)sai->ai_addr)->sin_addr,
465                         addr, sizeof(addr) );
466                 l.sl_name = ch_malloc( strlen(addr) + strlen(serv) + sizeof("IP=:") );
467                 sprintf( l.sl_name, "IP=%s:%s", addr, serv );
468         } break;
469
470 #  ifdef LDAP_PF_INET6
471         case AF_INET6: {
472                 char addr[INET6_ADDRSTRLEN];
473                 inet_ntop( AF_INET6,
474                         &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr,
475                         addr, sizeof addr);
476                 l.sl_name = ch_malloc( strlen(addr) + strlen(serv) + sizeof("IP= ") );
477                 sprintf( l.sl_name, "IP=%s %s", addr, serv );
478         } break;
479 #  endif /* LDAP_PF_INET6 */
480
481         default:
482                 Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
483                         (int) sai->ai_family, 0, 0 );
484                 break;
485         }
486 #else
487 #ifdef LDAP_PF_LOCAL
488         /* close conditional */
489         }
490 #endif /* LDAP_PF_LOCAL */
491
492         switch ( l.sl_sa.sa_addr.sa_family ) {
493 #ifdef LDAP_PF_LOCAL
494                 case AF_LOCAL:
495                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
496                                 sizeof(l.sl_sa.sa_un_addr) );
497                         break;
498 #endif
499
500                 case AF_INET:
501                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
502                                 sizeof(l.sl_sa.sa_in_addr) );
503                         break;
504
505                 default:
506                         rc = AC_SOCKET_ERROR;
507                         errno = EINVAL;
508                         break;
509         }
510
511         if ( rc == AC_SOCKET_ERROR ) {
512                 int err = sock_errno();
513                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
514                 (long) l.sl_sd, err, sock_errstr(err) );
515                 tcp_close( l.sl_sd );
516                 return NULL;
517         }
518
519         switch ( l.sl_sa.sa_addr.sa_family ) {
520 #ifdef LDAP_PF_LOCAL
521                 case AF_LOCAL:
522                         if ( chmod( l.sl_sa.sa_un_addr.sun_path, S_IRWXU ) < 0 ) {
523                                 int err = sock_errno();
524                                 Debug( LDAP_DEBUG_ANY,
525                                         "daemon: chmod(%ld) failed errno=%d (%s)",
526                                         (long) l.sl_sd, err, sock_errstr(err) );
527                                 tcp_close( l.sl_sd );
528                                 return NULL;
529                         }
530
531                         l.sl_name = ch_malloc( strlen(l.sl_sa.sa_un_addr.sun_path)
532                                 + sizeof("PATH=") );
533                         sprintf( l.sl_name, "PATH=%s", l.sl_sa.sa_un_addr.sun_path );
534                         break;
535 #endif /* LDAP_PF_LOCAL */
536
537                 case AF_INET:
538                         l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
539                         s = inet_ntoa( l.sl_addr.sin_addr );
540                         sprintf( l.sl_name, "IP=%s:%d",
541                                 s != NULL ? s : "unknown" , port );
542                         break;
543
544                 default:
545                         l.sl_name = ch_strdup( "UNKNOWN" );
546                         break;
547         }
548
549 #endif /* HAVE_GETADDRINFO */
550
551         l.sl_url = ch_strdup( url );
552         li = ch_malloc( sizeof( Listener ) );
553         *li = l;
554
555         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
556                 l.sl_url, 0, 0 );
557
558         return li;
559 }
560
561 static int sockinit(void);
562 static int sockdestroy(void);
563
564 int slapd_daemon_init( const char *urls )
565 {
566         int i, rc;
567         char **u;
568
569         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
570                 urls ? urls : "<null>", 0, 0 );
571
572         if( (rc = sockinit()) != 0 ) {
573                 return rc;
574         }
575
576 #ifdef HAVE_SYSCONF
577         dtblsize = sysconf( _SC_OPEN_MAX );
578 #elif HAVE_GETDTABLESIZE
579         dtblsize = getdtablesize();
580 #else
581         dtblsize = FD_SETSIZE;
582 #endif
583
584 #ifdef FD_SETSIZE
585         if(dtblsize > FD_SETSIZE) {
586                 dtblsize = FD_SETSIZE;
587         }
588 #endif  /* !FD_SETSIZE */
589
590         /* open a pipe (or something equivalent connected to itself).
591          * we write a byte on this fd whenever we catch a signal. The main
592          * loop will be select'ing on this socket, and will wake up when
593          * this byte arrives.
594          */
595         if( (rc = lutil_pair( wake_sds )) < 0 ) {
596                 Debug( LDAP_DEBUG_ANY,
597                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
598                 return rc;
599         }
600
601         FD_ZERO( &slap_daemon.sd_readers );
602         FD_ZERO( &slap_daemon.sd_writers );
603
604         if( urls == NULL ) {
605                 urls = "ldap:///";
606         }
607
608         u = str2charray( urls, " " );
609
610         if( u == NULL || u[0] == NULL ) {
611                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
612                         urls, 0, 0 );
613
614                 return -1;
615         }
616
617         for( i=0; u[i] != NULL; i++ ) {
618                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
619                         u[i], 0, 0 );
620         }
621
622         if( i == 0 ) {
623                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
624                         urls, 0, 0 );
625                 charray_free( u );
626                 return -1;
627         }
628
629         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
630                 i, 0, 0 );
631
632         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
633
634         for(i = 0; u[i] != NULL; i++ ) {
635                 slap_listeners[i] = open_listener( u[i] );
636
637                 if( slap_listeners[i] == NULL ) {
638                         charray_free( u );
639                         return -1;
640                 }
641         }
642         slap_listeners[i] = NULL;
643
644         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
645                 i, 0, 0 );
646
647         charray_free( u );
648         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
649         return !i;
650 }
651
652
653 int
654 slapd_daemon_destroy(void)
655 {
656         connections_destroy();
657         tcp_close( wake_sds[1] );
658         tcp_close( wake_sds[0] );
659         sockdestroy();
660         return 0;
661 }
662
663
664 static void *
665 slapd_daemon_task(
666         void *ptr
667 )
668 {
669         int l;
670         time_t  last_idle_check = slap_get_time();
671         time( &starttime );
672
673         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
674                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
675                         continue;
676
677                 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
678                         int err = sock_errno();
679                         Debug( LDAP_DEBUG_ANY,
680                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
681                                         slap_listeners[l]->sl_url, err,
682                                         sock_errstr(err) );
683                         return( (void*)-1 );
684                 }
685
686                 slapd_add( slap_listeners[l]->sl_sd );
687         }
688
689 #ifdef HAVE_NT_SERVICE_MANAGER
690         if ( started_event != NULL ) {
691                 ldap_pvt_thread_cond_signal( &started_event );
692         }
693 #endif
694         /* initialization complete. Here comes the loop. */
695
696         while ( !slapd_shutdown ) {
697                 ber_socket_t i;
698                 int ns;
699                 int at;
700                 ber_socket_t nfds;
701 #define SLAPD_EBADF_LIMIT 16
702                 int ebadf = 0;
703
704 #define SLAPD_IDLE_CHECK_LIMIT 4
705                 time_t  now = slap_get_time();
706
707
708                 fd_set                  readfds;
709                 fd_set                  writefds;
710                 Sockaddr                from;
711
712 #if defined(SLAPD_RLOOKUPS)
713         struct hostent          *hp;
714 #endif
715                 struct timeval          zero;
716                 struct timeval          *tvp;
717
718                 if( global_idletimeout > 0 && difftime(
719                         last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
720                         now ) < 0 )
721                 {
722                         connections_timeout_idle(now);
723                 }
724
725                 FD_ZERO( &writefds );
726                 FD_ZERO( &readfds );
727
728                 zero.tv_sec = 0;
729                 zero.tv_usec = 0;
730
731                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
732
733 #ifdef FD_SET_MANUAL_COPY
734                 for( s = 0; s < nfds; s++ ) {
735                         if(FD_ISSET( &slap_sd_readers, s )) {
736                                 FD_SET( s, &readfds );
737                         }
738                         if(FD_ISSET( &slap_sd_writers, s )) {
739                                 FD_SET( s, &writefds );
740                         }
741                 }
742 #else
743                 AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
744                 AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
745 #endif
746                 assert(!FD_ISSET(wake_sds[0], &readfds));
747                 FD_SET( wake_sds[0], &readfds );
748
749                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
750                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
751                                 continue;
752                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
753                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
754                 }
755
756 #ifndef HAVE_WINSOCK
757                 nfds = slap_daemon.sd_nfds;
758 #else
759                 nfds = dtblsize;
760 #endif
761
762                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
763
764                 at = ldap_pvt_thread_pool_backload(&connection_pool);
765
766 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
767                 tvp = NULL;
768 #else
769                 tvp = at ? &zero : NULL;
770 #endif
771
772                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
773                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
774                                 continue;
775
776                         Debug( LDAP_DEBUG_CONNS,
777                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
778                                         slap_listeners[l]->sl_sd, at,
779                                         tvp == NULL ? "NULL" : "zero" );
780                 }
781
782                 switch(ns = select( nfds, &readfds,
783 #ifdef HAVE_WINSOCK
784                         /* don't pass empty fd_set */
785                         ( writefds.fd_count > 0 ? &writefds : NULL ),
786 #else
787                         &writefds,
788 #endif
789                         NULL, tvp ))
790                 {
791                 case -1: {      /* failure - try again */
792                                 int err = sock_errno();
793
794                                 if( err == EBADF 
795 #ifdef WSAENOTSOCK
796                                         /* you'd think this would be EBADF */
797                                         || err == WSAENOTSOCK
798 #endif
799                                 ) {
800                                         if (++ebadf < SLAPD_EBADF_LIMIT)
801                                                 continue;
802                                 }
803
804                                 if( err != EINTR ) {
805                                         Debug( LDAP_DEBUG_CONNS,
806                                                 "daemon: select failed (%d): %s\n",
807                                                 err, sock_errstr(err), 0 );
808
809                                         slapd_shutdown = -1;
810                                 }
811                         }
812                         continue;
813
814                 case 0:         /* timeout - let threads run */
815                         ebadf = 0;
816                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
817                             0, 0, 0 );
818                 ldap_pvt_thread_yield();
819                         continue;
820
821                 default:        /* something happened - deal with it */
822                         ebadf = 0;
823                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
824                                 ns, 0, 0 );
825                         /* FALL THRU */
826                 }
827
828                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
829                         char c[BUFSIZ];
830                         tcp_read( wake_sds[0], c, sizeof(c) );
831 #ifdef NO_THREADS
832                         waking = 0;
833 #endif
834                         continue;
835                 }
836
837                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
838                         ber_int_t s;
839                         socklen_t len = sizeof(from);
840                         long id;
841                         slap_ssf_t ssf = 0;
842                         char *authid = NULL;
843
844                         char    *dnsname;
845                         char    *peeraddr;
846 #ifdef LDAP_PF_LOCAL
847                         char    peername[MAXPATHLEN + sizeof("PATH=")];
848 #elif defined(LDAP_PF_INET6)
849                         char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
850 #else
851                         char    peername[sizeof("IP=255.255.255.255:65336")];
852 #endif /* LDAP_PF_LOCAL */
853
854                         peername[0] = '\0';
855
856                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
857                                 continue;
858
859                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
860                                 continue;
861
862                         if ( (s = accept( slap_listeners[l]->sl_sd,
863                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
864                         {
865                                 int err = sock_errno();
866                                 Debug( LDAP_DEBUG_ANY,
867                                     "daemon: accept(%ld) failed errno=%d (%s)\n",
868                                     (long) slap_listeners[l]->sl_sd, err,
869                                     sock_errstr(err) );
870                                 continue;
871                         }
872
873 #ifndef HAVE_WINSOCK
874                         /* make sure descriptor number isn't too great */
875                         if ( s >= dtblsize ) {
876                                 Debug( LDAP_DEBUG_ANY,
877                                         "daemon: %ld beyond descriptor table size %ld\n",
878                                         (long) s, (long) dtblsize, 0 );
879                                 slapd_close(s);
880                                 continue;
881                         }
882 #endif
883
884 #ifdef LDAP_DEBUG
885                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
886
887                         /* newly accepted stream should not be in any of the FD SETS */
888                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
889                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
890                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
891
892                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
893 #endif
894
895                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
896                                 (long) s, 0, 0 );
897
898                         len = sizeof(from);
899
900                         if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
901                                 int err = sock_errno();
902                                 Debug( LDAP_DEBUG_ANY,
903                                         "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
904                                         (long) s, err, sock_errstr(err) );
905                                 slapd_close(s);
906                                 continue;
907                         }
908
909                         switch ( from.sa_addr.sa_family ) {
910 #  ifdef LDAP_PF_LOCAL
911                         case AF_LOCAL:
912                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
913                                 ssf = LDAP_PVT_SASL_LOCAL_SSF;
914                                 break;
915 #endif /* LDAP_PF_LOCAL */
916
917 #  ifdef LDAP_PF_INET6
918                         case AF_INET6:
919                         if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
920                                 peeraddr = inet_ntoa( *((struct in_addr *)
921                                                         &from.sa_in6_addr.sin6_addr.s6_addr[12]) );
922                                 sprintf( peername, "IP=%s:%d",
923                                          peeraddr != NULL ? peeraddr : "unknown",
924                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
925                         } else {
926                                 char addr[INET6_ADDRSTRLEN];
927                                 sprintf( peername, "IP=%s %d",
928                                          inet_ntop( AF_INET6,
929                                                     &from.sa_in6_addr.sin6_addr,
930                                                     addr, sizeof addr) ? addr : "unknown",
931                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
932                         }
933                         break;
934 #  endif /* LDAP_PF_INET6 */
935
936                         case AF_INET:
937                         peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
938                         sprintf( peername, "IP=%s:%d",
939                                 peeraddr != NULL ? peeraddr : "unknown",
940                                 (unsigned) ntohs( from.sa_in_addr.sin_port ) );
941                                 break;
942
943                         default:
944                                 slapd_close(s);
945                                 continue;
946                         }
947                         if ( ( from.sa_addr.sa_family == AF_INET ) 
948 #ifdef LDAP_PF_INET6
949                                 || ( from.sa_addr.sa_family == AF_INET6 )
950 #endif
951                         ) {
952 #ifdef SLAPD_RLOOKUPS
953 #  ifdef LDAP_PF_INET6
954                                 if ( from.sa_addr.sa_family == AF_INET6 )
955                                         hp = gethostbyaddr(
956                                                 (char *)&(from.sa_in6_addr.sin6_addr),
957                                                 sizeof(from.sa_in6_addr.sin6_addr),
958                                                 AF_INET6 );
959                                 else
960 #  endif LDAP_PF_INET6
961                                 hp = gethostbyaddr(
962                                         (char *) &(from.sa_in_addr.sin_addr),
963                                         sizeof(from.sa_in_addr.sin_addr),
964                                         AF_INET );
965                                 dnsname = hp ? ldap_pvt_str2lower( hp->h_name ) : NULL;
966 #else
967                                 dnsname = NULL;
968 #endif /* SLAPD_RLOOKUPS */
969
970 #ifdef HAVE_TCPD
971                                 if ( !hosts_ctl("slapd",
972                                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
973                                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
974                                                 STRING_UNKNOWN ))
975                                 {
976                                         /* DENY ACCESS */
977                                         Statslog( LDAP_DEBUG_ANY,
978                                                 "fd=%ld host access from %s (%s) denied.\n",
979                                                 (long) s,
980                                                 dnsname != NULL ? dnsname : "unknown",
981                                                 peeraddr != NULL ? peeraddr : "unknown",
982                                                 0, 0 );
983                                         slapd_close(s);
984                                         continue;
985                                 }
986 #endif /* HAVE_TCPD */
987                         }
988
989                         id = connection_init(s,
990                                 slap_listeners[l]->sl_url,
991                                 dnsname != NULL ? dnsname : "unknown",
992                                 peername,
993                                 slap_listeners[l]->sl_name,
994 #ifdef HAVE_TLS
995                                 slap_listeners[l]->sl_is_tls,
996 #else
997                                 0,
998 #endif
999                                 ssf,
1000                                 authid );
1001
1002                         if( authid ) ch_free(authid);
1003
1004                         if( id < 0 ) {
1005                                 Debug( LDAP_DEBUG_ANY,
1006                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
1007                                         (long) s,
1008                                         peername,
1009                                         slap_listeners[l]->sl_name );
1010                                 slapd_close(s);
1011                                 continue;
1012                         }
1013
1014                         Statslog( LDAP_DEBUG_STATS,
1015                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
1016                                 id, (long) s,
1017                                 peername,
1018                                 slap_listeners[l]->sl_name,
1019                                 0 );
1020
1021                         slapd_add( s );
1022                         continue;
1023                 }
1024
1025 #ifdef LDAP_DEBUG
1026                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
1027 #ifdef HAVE_WINSOCK
1028                 for ( i = 0; i < readfds.fd_count; i++ ) {
1029                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1030                                 readfds.fd_array[i], "r", 0 );
1031                 }
1032                 for ( i = 0; i < writefds.fd_count; i++ ) {
1033                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1034                                 writefds.fd_array[i], "w", 0 );
1035                 }
1036 #else
1037                 for ( i = 0; i < nfds; i++ ) {
1038                         int     r, w;
1039                         int     is_listener = 0;
1040
1041                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1042                                 if ( i == slap_listeners[l]->sl_sd ) {
1043                                         is_listener = 1;
1044                                         break;
1045                                 }
1046                         }
1047                         if ( is_listener ) {
1048                                 continue;
1049                         }
1050                         r = FD_ISSET( i, &readfds );
1051                         w = FD_ISSET( i, &writefds );
1052                         if ( r || w ) {
1053                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
1054                                     r ? "r" : "", w ? "w" : "" );
1055                         }
1056                 }
1057 #endif
1058                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
1059 #endif
1060
1061                 /* loop through the writers */
1062 #ifdef HAVE_WINSOCK
1063                 for ( i = 0; i < writefds.fd_count; i++ )
1064 #else
1065                 for ( i = 0; i < nfds; i++ )
1066 #endif
1067                 {
1068                         ber_socket_t wd;
1069                         int is_listener = 0;
1070 #ifdef HAVE_WINSOCK
1071                         wd = writefds.fd_array[i];
1072 #else
1073                         if( ! FD_ISSET( i, &writefds ) ) {
1074                                 continue;
1075                         }
1076                         wd = i;
1077 #endif
1078
1079                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1080                                 if ( i == slap_listeners[l]->sl_sd ) {
1081                                         is_listener = 1;
1082                                         break;
1083                                 }
1084                         }
1085                         if ( is_listener ) {
1086                                 continue;
1087                         }
1088                         Debug( LDAP_DEBUG_CONNS,
1089                                 "daemon: write active on %d\n",
1090                                 wd, 0, 0 );
1091
1092                         /*
1093                          * NOTE: it is possible that the connection was closed
1094                          * and that the stream is now inactive.
1095                          * connection_write() must valid the stream is still
1096                          * active.
1097                          */
1098
1099                         if ( connection_write( wd ) < 0 ) {
1100                                 FD_CLR( (unsigned) wd, &readfds );
1101                                 slapd_close( wd );
1102                         }
1103                 }
1104
1105 #ifdef HAVE_WINSOCK
1106                 for ( i = 0; i < readfds.fd_count; i++ )
1107 #else
1108                 for ( i = 0; i < nfds; i++ )
1109 #endif
1110                 {
1111                         ber_socket_t rd;
1112                         int is_listener = 0;
1113
1114 #ifdef HAVE_WINSOCK
1115                         rd = readfds.fd_array[i];
1116 #else
1117                         if( ! FD_ISSET( i, &readfds ) ) {
1118                                 continue;
1119                         }
1120                         rd = i;
1121 #endif
1122
1123                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1124                                 if ( rd == slap_listeners[l]->sl_sd ) {
1125                                         is_listener = 1;
1126                                         break;
1127                                 }
1128                         }
1129                         if ( is_listener ) {
1130                                 continue;
1131                         }
1132
1133                         Debug ( LDAP_DEBUG_CONNS,
1134                                 "daemon: read activity on %d\n", rd, 0, 0 );
1135
1136                         /*
1137                          * NOTE: it is possible that the connection was closed
1138                          * and that the stream is now inactive.
1139                          * connection_read() must valid the stream is still
1140                          * active.
1141                          */
1142
1143                         if ( connection_read( rd ) < 0 ) {
1144                                 slapd_close( rd );
1145                         }
1146                 }
1147                 ldap_pvt_thread_yield();
1148         }
1149
1150         if( slapd_shutdown > 0 ) {
1151                 Debug( LDAP_DEBUG_TRACE,
1152                         "daemon: shutdown requested and initiated.\n",
1153                         0, 0, 0 );
1154
1155         } else if ( slapd_shutdown < 0 ) {
1156 #ifdef HAVE_NT_SERVICE_MANAGER
1157                 if (slapd_shutdown == -1)
1158                     Debug( LDAP_DEBUG_TRACE,
1159                           "daemon: shutdown initiated by Service Manager.\n",
1160                           0, 0, 0);
1161                 else
1162 #endif
1163                 Debug( LDAP_DEBUG_TRACE,
1164                         "daemon: abnormal condition, shutdown initiated.\n",
1165                         0, 0, 0 );
1166         } else {
1167                 Debug( LDAP_DEBUG_TRACE,
1168                         "daemon: no active streams, shutdown initiated.\n",
1169                         0, 0, 0 );
1170         }
1171
1172         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1173                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1174 #ifdef LDAP_PF_LOCAL
1175                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
1176                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1177                         }
1178 #endif /* LDAP_PF_LOCAL */
1179                         slapd_close( slap_listeners[l]->sl_sd );
1180                         break;
1181                 }
1182         }
1183
1184         Debug( LDAP_DEBUG_ANY,
1185             "slapd shutdown: waiting for %d threads to terminate\n",
1186             ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
1187
1188         ldap_pvt_thread_pool_destroy(&connection_pool, 1);
1189
1190         return NULL;
1191 }
1192
1193
1194 int slapd_daemon( void )
1195 {
1196         int rc;
1197
1198         connections_init();
1199
1200 #define SLAPD_LISTENER_THREAD 1
1201 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
1202
1203         /* listener as a separate THREAD */
1204         rc = ldap_pvt_thread_create( &listener_tid,
1205                 0, slapd_daemon_task, NULL );
1206
1207         if ( rc != 0 ) {
1208                 Debug( LDAP_DEBUG_ANY,
1209                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1210                 return rc;
1211         }
1212
1213         /* wait for the listener thread to complete */
1214         ldap_pvt_thread_join( listener_tid, (void *) NULL );
1215 #else
1216         /* expermimental code */
1217         listener_tid = pthread_self();
1218         slapd_daemon_task( NULL );
1219 #endif
1220
1221         return 0;
1222
1223 }
1224
1225 int sockinit(void)
1226 {
1227 #if defined( HAVE_WINSOCK2 )
1228     WORD wVersionRequested;
1229         WSADATA wsaData;
1230         int err;
1231  
1232         wVersionRequested = MAKEWORD( 2, 0 );
1233  
1234         err = WSAStartup( wVersionRequested, &wsaData );
1235         if ( err != 0 ) {
1236                 /* Tell the user that we couldn't find a usable */
1237                 /* WinSock DLL.                                  */
1238                 return -1;
1239         }
1240  
1241         /* Confirm that the WinSock DLL supports 2.0.*/
1242         /* Note that if the DLL supports versions greater    */
1243         /* than 2.0 in addition to 2.0, it will still return */
1244         /* 2.0 in wVersion since that is the version we      */
1245         /* requested.                                        */
1246  
1247         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1248                 HIBYTE( wsaData.wVersion ) != 0 )
1249         {
1250             /* Tell the user that we couldn't find a usable */
1251             /* WinSock DLL.                                  */
1252             WSACleanup();
1253             return -1; 
1254         }
1255
1256         /* The WinSock DLL is acceptable. Proceed. */
1257 #elif defined( HAVE_WINSOCK )
1258         WSADATA wsaData;
1259         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1260             return -1;
1261         }
1262 #endif
1263         return 0;
1264 }
1265
1266 int sockdestroy(void)
1267 {
1268 #if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
1269         WSACleanup();
1270 #endif
1271         return 0;
1272 }
1273
1274 RETSIGTYPE
1275 slap_sig_shutdown( int sig )
1276 {
1277         Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
1278
1279         /*
1280          * If the NT Service Manager is controlling the server, we don't
1281          * want SIGBREAK to kill the server. For some strange reason,
1282          * SIGBREAK is generated when a user logs out.
1283          */
1284
1285 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
1286         if (is_NT_Service && sig == SIGBREAK)
1287             Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
1288                   0, 0, 0);
1289         else
1290 #endif
1291         slapd_shutdown = sig;
1292
1293         WAKE_LISTENER(1);
1294
1295         /* reinstall self */
1296         (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
1297 }
1298
1299 RETSIGTYPE
1300 slap_sig_wake( int sig )
1301 {
1302         WAKE_LISTENER(1);
1303
1304         /* reinstall self */
1305         (void) SIGNAL_REINSTALL( sig, slap_sig_wake );
1306 }