]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
57c93e5e6180cba19ddc0eb1284e89445f12c792
[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
406 #ifdef HAVE_GETADDRINFO
407                 } /* sai->ai_family != AF_LOCAL */
408                 if (!bind(l.sl_sd, sai->ai_addr, sai->ai_addrlen))
409                         break;
410                 err = sock_errno();
411                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
412                         (long) l.sl_sd, err, sock_errstr(err) );
413                 tcp_close( l.sl_sd );
414         } while ((sai = sai->ai_next) != NULL);
415
416         if (!sai) {
417                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed\n",
418                         (long) l.sl_sd, 0, 0 );
419                 return NULL;
420         }
421
422         switch ( sai->ai_family ) {
423 #  ifdef LDAP_PF_LOCAL
424         case AF_LOCAL:
425                 if ( chmod( (char *)sai->ai_addr, S_IRWXU ) < 0 ) {
426                         int err = sock_errno();
427                         Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
428                                 (long) l.sl_sd, err, sock_errstr(err) );
429                         tcp_close( l.sl_sd );
430                         return NULL;
431                 }
432                 l.sl_name = ch_malloc( strlen((char *)sai->ai_addr) + sizeof("PATH=") );
433                 sprintf( l.sl_name, "PATH=%s", sai->ai_addr );
434                 break;
435 #  endif /* LDAP_PF_LOCAL */
436
437         case AF_INET: {
438                 char addr[INET_ADDRSTRLEN];
439                 inet_ntop( AF_INET,
440                         &((struct sockaddr_in *)sai->ai_addr)->sin_addr,
441                         addr, sizeof(addr) );
442                 l.sl_name = ch_malloc( strlen(addr) + strlen(serv) + sizeof("IP=:") );
443                 sprintf( l.sl_name, "IP=%s:%s", addr, serv );
444         } break;
445
446 #  ifdef LDAP_PF_INET6
447         case AF_INET6: {
448                 char addr[INET6_ADDRSTRLEN];
449                 inet_ntop( AF_INET6,
450                         &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr,
451                         addr, sizeof addr);
452                 l.sl_name = ch_malloc( strlen(addr) + strlen(serv) + sizeof("IP= ") );
453                 sprintf( l.sl_name, "IP=%s %s", addr, serv );
454         } break;
455 #  endif /* LDAP_PF_INET6 */
456
457         default:
458                 Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
459                         (int) sai->ai_family, 0, 0 );
460                 break;
461         }
462 #else
463 #ifdef LDAP_PF_LOCAL
464         /* close conditional */
465         }
466 #endif /* LDAP_PF_LOCAL */
467
468         switch ( l.sl_sa.sa_addr.sa_family ) {
469 #ifdef LDAP_PF_LOCAL
470                 case AF_LOCAL:
471                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
472                                 sizeof(l.sl_sa.sa_un_addr) );
473                         break;
474 #endif
475
476                 case AF_INET:
477                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
478                                 sizeof(l.sl_sa.sa_in_addr) );
479                         break;
480
481                 default:
482                         rc = AC_SOCKET_ERROR;
483                         errno = EINVAL;
484                         break;
485         }
486
487         if ( rc == AC_SOCKET_ERROR ) {
488                 int err = sock_errno();
489                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
490                 (long) l.sl_sd, err, sock_errstr(err) );
491                 tcp_close( l.sl_sd );
492                 return NULL;
493         }
494
495         switch ( l.sl_sa.sa_addr.sa_family ) {
496 #ifdef LDAP_PF_LOCAL
497                 case AF_LOCAL:
498                         if ( chmod( l.sl_sa.sa_un_addr.sun_path, S_IRWXU ) < 0 ) {
499                                 int err = sock_errno();
500                                 Debug( LDAP_DEBUG_ANY,
501                                         "daemon: chmod(%ld) failed errno=%d (%s)",
502                                         (long) l.sl_sd, err, sock_errstr(err) );
503                                 tcp_close( l.sl_sd );
504                                 return NULL;
505                         }
506
507                         l.sl_name = ch_malloc( strlen(l.sl_sa.sa_un_addr.sun_path)
508                                 + sizeof("PATH=") );
509                         sprintf( l.sl_name, "PATH=%s", l.sl_sa.sa_un_addr.sun_path );
510                         break;
511 #endif /* LDAP_PF_LOCAL */
512
513                 case AF_INET:
514                         l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
515                         s = inet_ntoa( l.sl_addr.sin_addr );
516                         sprintf( l.sl_name, "IP=%s:%d",
517                                 s != NULL ? s : "unknown" , port );
518                         break;
519
520                 default:
521                         l.sl_name = ch_strdup( "UNKNOWN" );
522                         break;
523         }
524
525 #endif /* HAVE_GETADDRINFO */
526
527         l.sl_url = ch_strdup( url );
528         li = ch_malloc( sizeof( Listener ) );
529         *li = l;
530
531         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
532                 l.sl_url, 0, 0 );
533
534         return li;
535 }
536
537 static int sockinit(void);
538 static int sockdestroy(void);
539
540 int slapd_daemon_init( const char *urls )
541 {
542         int i, rc;
543         char **u;
544
545         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
546                 urls ? urls : "<null>", 0, 0 );
547
548         if( (rc = sockinit()) != 0 ) {
549                 return rc;
550         }
551
552 #ifdef HAVE_SYSCONF
553         dtblsize = sysconf( _SC_OPEN_MAX );
554 #elif HAVE_GETDTABLESIZE
555         dtblsize = getdtablesize();
556 #else
557         dtblsize = FD_SETSIZE;
558 #endif
559
560 #ifdef FD_SETSIZE
561         if(dtblsize > FD_SETSIZE) {
562                 dtblsize = FD_SETSIZE;
563         }
564 #endif  /* !FD_SETSIZE */
565
566         /* open a pipe (or something equivalent connected to itself).
567          * we write a byte on this fd whenever we catch a signal. The main
568          * loop will be select'ing on this socket, and will wake up when
569          * this byte arrives.
570          */
571         if( (rc = lutil_pair( wake_sds )) < 0 ) {
572                 Debug( LDAP_DEBUG_ANY,
573                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
574                 return rc;
575         }
576
577         FD_ZERO( &slap_daemon.sd_readers );
578         FD_ZERO( &slap_daemon.sd_writers );
579
580         if( urls == NULL ) {
581                 urls = "ldap:///";
582         }
583
584         u = str2charray( urls, " " );
585
586         if( u == NULL || u[0] == NULL ) {
587                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
588                         urls, 0, 0 );
589
590                 return -1;
591         }
592
593         for( i=0; u[i] != NULL; i++ ) {
594                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
595                         u[i], 0, 0 );
596         }
597
598         if( i == 0 ) {
599                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
600                         urls, 0, 0 );
601                 charray_free( u );
602                 return -1;
603         }
604
605         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
606                 i, 0, 0 );
607
608         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
609
610         for(i = 0; u[i] != NULL; i++ ) {
611                 slap_listeners[i] = open_listener( u[i] );
612
613                 if( slap_listeners[i] == NULL ) {
614                         charray_free( u );
615                         return -1;
616                 }
617         }
618         slap_listeners[i] = NULL;
619
620         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
621                 i, 0, 0 );
622
623         charray_free( u );
624         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
625         return !i;
626 }
627
628
629 int
630 slapd_daemon_destroy(void)
631 {
632         connections_destroy();
633         tcp_close( wake_sds[1] );
634         tcp_close( wake_sds[0] );
635         sockdestroy();
636         return 0;
637 }
638
639
640 static void *
641 slapd_daemon_task(
642         void *ptr
643 )
644 {
645         int rc, tmp;
646         int l;
647         time_t  last_idle_check = slap_get_time();
648         time( &starttime );
649
650         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
651                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
652                         continue;
653
654                 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
655                         int err = sock_errno();
656                         Debug( LDAP_DEBUG_ANY,
657                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
658                                         slap_listeners[l]->sl_url, err,
659                                         sock_errstr(err) );
660                         return( (void*)-1 );
661                 }
662
663                 slapd_add( slap_listeners[l]->sl_sd );
664         }
665
666 #ifdef HAVE_NT_SERVICE_MANAGER
667         if ( started_event != NULL ) {
668                 ldap_pvt_thread_cond_signal( &started_event );
669         }
670 #endif
671         /* initialization complete. Here comes the loop. */
672
673         while ( !slapd_shutdown ) {
674                 ber_socket_t i;
675                 int ns;
676                 int at;
677                 ber_socket_t nfds;
678 #define SLAPD_EBADF_LIMIT 16
679                 int ebadf = 0;
680
681 #define SLAPD_IDLE_CHECK_LIMIT 4
682                 time_t  now = slap_get_time();
683
684
685                 fd_set                  readfds;
686                 fd_set                  writefds;
687                 Sockaddr                from;
688
689 #if defined(SLAPD_RLOOKUPS)
690         struct hostent          *hp;
691 #endif
692                 struct timeval          zero;
693                 struct timeval          *tvp;
694
695                 if( global_idletimeout > 0 && difftime(
696                         last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
697                         now ) < 0 )
698                 {
699                         connections_timeout_idle(now);
700                 }
701
702                 FD_ZERO( &writefds );
703                 FD_ZERO( &readfds );
704
705                 zero.tv_sec = 0;
706                 zero.tv_usec = 0;
707
708                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
709
710 #ifdef FD_SET_MANUAL_COPY
711                 for( s = 0; s < nfds; s++ ) {
712                         if(FD_ISSET( &slap_sd_readers, s )) {
713                                 FD_SET( s, &readfds );
714                         }
715                         if(FD_ISSET( &slap_sd_writers, s )) {
716                                 FD_SET( s, &writefds );
717                         }
718                 }
719 #else
720                 AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
721                 AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
722 #endif
723                 assert(!FD_ISSET(wake_sds[0], &readfds));
724                 FD_SET( wake_sds[0], &readfds );
725
726                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
727                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
728                                 continue;
729                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
730                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
731                 }
732
733 #ifndef HAVE_WINSOCK
734                 nfds = slap_daemon.sd_nfds;
735 #else
736                 nfds = dtblsize;
737 #endif
738
739                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
740
741                 at = ldap_pvt_thread_pool_backload(&connection_pool);
742
743 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
744                 tvp = NULL;
745 #else
746                 tvp = at ? &zero : NULL;
747 #endif
748
749                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
750                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
751                                 continue;
752
753                         Debug( LDAP_DEBUG_CONNS,
754                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
755                                         slap_listeners[l]->sl_sd, at,
756                                         tvp == NULL ? "NULL" : "zero" );
757                 }
758
759                 switch(ns = select( nfds, &readfds,
760 #ifdef HAVE_WINSOCK
761                         /* don't pass empty fd_set */
762                         ( writefds.fd_count > 0 ? &writefds : NULL ),
763 #else
764                         &writefds,
765 #endif
766                         NULL, tvp ))
767                 {
768                 case -1: {      /* failure - try again */
769                                 int err = sock_errno();
770
771                                 if( err == EBADF 
772 #ifdef WSAENOTSOCK
773                                         /* you'd think this would be EBADF */
774                                         || err == WSAENOTSOCK
775 #endif
776                                 ) {
777                                         if (++ebadf < SLAPD_EBADF_LIMIT)
778                                                 continue;
779                                 }
780
781                                 if( err != EINTR ) {
782                                         Debug( LDAP_DEBUG_CONNS,
783                                                 "daemon: select failed (%d): %s\n",
784                                                 err, sock_errstr(err), 0 );
785
786                                         slapd_shutdown = -1;
787                                 }
788                         }
789                         continue;
790
791                 case 0:         /* timeout - let threads run */
792                         ebadf = 0;
793                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
794                             0, 0, 0 );
795                 ldap_pvt_thread_yield();
796                         continue;
797
798                 default:        /* something happened - deal with it */
799                         ebadf = 0;
800                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
801                                 ns, 0, 0 );
802                         /* FALL THRU */
803                 }
804
805                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
806                         char c[BUFSIZ];
807                         tcp_read( wake_sds[0], c, sizeof(c) );
808 #ifdef NO_THREADS
809                         waking = 0;
810 #endif
811                         continue;
812                 }
813
814                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
815                         ber_int_t s;
816                         socklen_t len = sizeof(from);
817                         long id;
818                         slap_ssf_t ssf = 0;
819                         char *authid = NULL;
820
821                         char    *dnsname;
822                         char    *peeraddr;
823 #ifdef LDAP_PF_LOCAL
824                         char    peername[MAXPATHLEN + sizeof("PATH=")];
825 #elif defined(LDAP_PF_INET6)
826                         char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
827 #else
828                         char    peername[sizeof("IP=255.255.255.255:65336")];
829 #endif /* LDAP_PF_LOCAL */
830
831                         peername[0] = '\0';
832
833                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
834                                 continue;
835
836                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
837                                 continue;
838
839                         if ( (s = accept( slap_listeners[l]->sl_sd,
840                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
841                         {
842                                 int err = sock_errno();
843                                 Debug( LDAP_DEBUG_ANY,
844                                     "daemon: accept(%ld) failed errno=%d (%s)\n",
845                                     (long) slap_listeners[l]->sl_sd, err,
846                                     sock_errstr(err) );
847                                 continue;
848                         }
849
850 #ifndef HAVE_WINSOCK
851                         /* make sure descriptor number isn't too great */
852                         if ( s >= dtblsize ) {
853                                 Debug( LDAP_DEBUG_ANY,
854                                         "daemon: %ld beyond descriptor table size %ld\n",
855                                         (long) s, (long) dtblsize, 0 );
856                                 slapd_close(s);
857                                 continue;
858                         }
859 #endif
860
861 #ifdef SO_KEEPALIVE
862                         /* enable keep alives */
863                         rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
864                                 (char *) &tmp, sizeof(tmp) );
865                         if ( rc == AC_SOCKET_ERROR ) {
866                                 int err = sock_errno();
867                                 Debug( LDAP_DEBUG_ANY,
868                                         "slapd(%ld): setsockopt(SO_KEEPALIVE) failed "
869                                         "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
870                         }
871 #endif
872 #ifdef TCP_NODELAY
873                         /* enable no delay */
874                         tmp = 1;
875                         rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
876                                 (char *)&tmp, sizeof(tmp) );
877                         if ( rc == AC_SOCKET_ERROR ) {
878                                 int err = sock_errno();
879                                 Debug( LDAP_DEBUG_ANY,
880                                         "slapd(%ld): setsockopt(TCP_NODELAY) failed "
881                                         "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
882                         }
883 #endif
884
885
886 #ifdef LDAP_DEBUG
887                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
888
889                         /* newly accepted stream should not be in any of the FD SETS */
890                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
891                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
892                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
893
894                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
895 #endif
896
897                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
898                                 (long) s, 0, 0 );
899
900                         len = sizeof(from);
901
902                         if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
903                                 int err = sock_errno();
904                                 Debug( LDAP_DEBUG_ANY,
905                                         "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
906                                         (long) s, err, sock_errstr(err) );
907                                 slapd_close(s);
908                                 continue;
909                         }
910
911                         switch ( from.sa_addr.sa_family ) {
912 #  ifdef LDAP_PF_LOCAL
913                         case AF_LOCAL:
914                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
915                                 ssf = LDAP_PVT_SASL_LOCAL_SSF;
916                                 break;
917 #endif /* LDAP_PF_LOCAL */
918
919 #  ifdef LDAP_PF_INET6
920                         case AF_INET6:
921                         if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
922                                 peeraddr = inet_ntoa( *((struct in_addr *)
923                                                         &from.sa_in6_addr.sin6_addr.s6_addr[12]) );
924                                 sprintf( peername, "IP=%s:%d",
925                                          peeraddr != NULL ? peeraddr : "unknown",
926                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
927                         } else {
928                                 char addr[INET6_ADDRSTRLEN];
929                                 sprintf( peername, "IP=%s %d",
930                                          inet_ntop( AF_INET6,
931                                                     &from.sa_in6_addr.sin6_addr,
932                                                     addr, sizeof addr) ? addr : "unknown",
933                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
934                         }
935                         break;
936 #  endif /* LDAP_PF_INET6 */
937
938                         case AF_INET:
939                         peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
940                         sprintf( peername, "IP=%s:%d",
941                                 peeraddr != NULL ? peeraddr : "unknown",
942                                 (unsigned) ntohs( from.sa_in_addr.sin_port ) );
943                                 break;
944
945                         default:
946                                 slapd_close(s);
947                                 continue;
948                         }
949                         if ( ( from.sa_addr.sa_family == AF_INET ) 
950 #ifdef LDAP_PF_INET6
951                                 || ( from.sa_addr.sa_family == AF_INET6 )
952 #endif
953                         ) {
954 #ifdef SLAPD_RLOOKUPS
955 #  ifdef LDAP_PF_INET6
956                                 if ( from.sa_addr.sa_family == AF_INET6 )
957                                         hp = gethostbyaddr(
958                                                 (char *)&(from.sa_in6_addr.sin6_addr),
959                                                 sizeof(from.sa_in6_addr.sin6_addr),
960                                                 AF_INET6 );
961                                 else
962 #  endif LDAP_PF_INET6
963                                 hp = gethostbyaddr(
964                                         (char *) &(from.sa_in_addr.sin_addr),
965                                         sizeof(from.sa_in_addr.sin_addr),
966                                         AF_INET );
967                                 dnsname = hp ? ldap_pvt_str2lower( hp->h_name ) : NULL;
968 #else
969                                 dnsname = NULL;
970 #endif /* SLAPD_RLOOKUPS */
971
972 #ifdef HAVE_TCPD
973                                 if ( !hosts_ctl("slapd",
974                                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
975                                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
976                                                 STRING_UNKNOWN ))
977                                 {
978                                         /* DENY ACCESS */
979                                         Statslog( LDAP_DEBUG_ANY,
980                                                 "fd=%ld host access from %s (%s) denied.\n",
981                                                 (long) s,
982                                                 dnsname != NULL ? dnsname : "unknown",
983                                                 peeraddr != NULL ? peeraddr : "unknown",
984                                                 0, 0 );
985                                         slapd_close(s);
986                                         continue;
987                                 }
988 #endif /* HAVE_TCPD */
989                         }
990
991                         id = connection_init(s,
992                                 slap_listeners[l]->sl_url,
993                                 dnsname != NULL ? dnsname : "unknown",
994                                 peername,
995                                 slap_listeners[l]->sl_name,
996 #ifdef HAVE_TLS
997                                 slap_listeners[l]->sl_is_tls,
998 #else
999                                 0,
1000 #endif
1001                                 ssf,
1002                                 authid );
1003
1004                         if( authid ) ch_free(authid);
1005
1006                         if( id < 0 ) {
1007                                 Debug( LDAP_DEBUG_ANY,
1008                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
1009                                         (long) s,
1010                                         peername,
1011                                         slap_listeners[l]->sl_name );
1012                                 slapd_close(s);
1013                                 continue;
1014                         }
1015
1016                         Statslog( LDAP_DEBUG_STATS,
1017                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
1018                                 id, (long) s,
1019                                 peername,
1020                                 slap_listeners[l]->sl_name,
1021                                 0 );
1022
1023                         slapd_add( s );
1024                         continue;
1025                 }
1026
1027 #ifdef LDAP_DEBUG
1028                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
1029 #ifdef HAVE_WINSOCK
1030                 for ( i = 0; i < readfds.fd_count; i++ ) {
1031                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1032                                 readfds.fd_array[i], "r", 0 );
1033                 }
1034                 for ( i = 0; i < writefds.fd_count; i++ ) {
1035                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1036                                 writefds.fd_array[i], "w", 0 );
1037                 }
1038 #else
1039                 for ( i = 0; i < nfds; i++ ) {
1040                         int     r, w;
1041                         int     is_listener = 0;
1042
1043                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1044                                 if ( i == slap_listeners[l]->sl_sd ) {
1045                                         is_listener = 1;
1046                                         break;
1047                                 }
1048                         }
1049                         if ( is_listener ) {
1050                                 continue;
1051                         }
1052                         r = FD_ISSET( i, &readfds );
1053                         w = FD_ISSET( i, &writefds );
1054                         if ( r || w ) {
1055                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
1056                                     r ? "r" : "", w ? "w" : "" );
1057                         }
1058                 }
1059 #endif
1060                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
1061 #endif
1062
1063                 /* loop through the writers */
1064 #ifdef HAVE_WINSOCK
1065                 for ( i = 0; i < writefds.fd_count; i++ )
1066 #else
1067                 for ( i = 0; i < nfds; i++ )
1068 #endif
1069                 {
1070                         ber_socket_t wd;
1071                         int is_listener = 0;
1072 #ifdef HAVE_WINSOCK
1073                         wd = writefds.fd_array[i];
1074 #else
1075                         if( ! FD_ISSET( i, &writefds ) ) {
1076                                 continue;
1077                         }
1078                         wd = i;
1079 #endif
1080
1081                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1082                                 if ( i == slap_listeners[l]->sl_sd ) {
1083                                         is_listener = 1;
1084                                         break;
1085                                 }
1086                         }
1087                         if ( is_listener ) {
1088                                 continue;
1089                         }
1090                         Debug( LDAP_DEBUG_CONNS,
1091                                 "daemon: write active on %d\n",
1092                                 wd, 0, 0 );
1093
1094                         /*
1095                          * NOTE: it is possible that the connection was closed
1096                          * and that the stream is now inactive.
1097                          * connection_write() must valid the stream is still
1098                          * active.
1099                          */
1100
1101                         if ( connection_write( wd ) < 0 ) {
1102                                 FD_CLR( (unsigned) wd, &readfds );
1103                                 slapd_close( wd );
1104                         }
1105                 }
1106
1107 #ifdef HAVE_WINSOCK
1108                 for ( i = 0; i < readfds.fd_count; i++ )
1109 #else
1110                 for ( i = 0; i < nfds; i++ )
1111 #endif
1112                 {
1113                         ber_socket_t rd;
1114                         int is_listener = 0;
1115
1116 #ifdef HAVE_WINSOCK
1117                         rd = readfds.fd_array[i];
1118 #else
1119                         if( ! FD_ISSET( i, &readfds ) ) {
1120                                 continue;
1121                         }
1122                         rd = i;
1123 #endif
1124
1125                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1126                                 if ( rd == slap_listeners[l]->sl_sd ) {
1127                                         is_listener = 1;
1128                                         break;
1129                                 }
1130                         }
1131                         if ( is_listener ) {
1132                                 continue;
1133                         }
1134
1135                         Debug ( LDAP_DEBUG_CONNS,
1136                                 "daemon: read activity on %d\n", rd, 0, 0 );
1137
1138                         /*
1139                          * NOTE: it is possible that the connection was closed
1140                          * and that the stream is now inactive.
1141                          * connection_read() must valid the stream is still
1142                          * active.
1143                          */
1144
1145                         if ( connection_read( rd ) < 0 ) {
1146                                 slapd_close( rd );
1147                         }
1148                 }
1149                 ldap_pvt_thread_yield();
1150         }
1151
1152         if( slapd_shutdown > 0 ) {
1153                 Debug( LDAP_DEBUG_TRACE,
1154                         "daemon: shutdown requested and initiated.\n",
1155                         0, 0, 0 );
1156
1157         } else if ( slapd_shutdown < 0 ) {
1158 #ifdef HAVE_NT_SERVICE_MANAGER
1159                 if (slapd_shutdown == -1)
1160                     Debug( LDAP_DEBUG_TRACE,
1161                           "daemon: shutdown initiated by Service Manager.\n",
1162                           0, 0, 0);
1163                 else
1164 #endif
1165                 Debug( LDAP_DEBUG_TRACE,
1166                         "daemon: abnormal condition, shutdown initiated.\n",
1167                         0, 0, 0 );
1168         } else {
1169                 Debug( LDAP_DEBUG_TRACE,
1170                         "daemon: no active streams, shutdown initiated.\n",
1171                         0, 0, 0 );
1172         }
1173
1174         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1175                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1176 #ifdef LDAP_PF_LOCAL
1177                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
1178                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1179                         }
1180 #endif /* LDAP_PF_LOCAL */
1181                         slapd_close( slap_listeners[l]->sl_sd );
1182                         break;
1183                 }
1184         }
1185
1186         Debug( LDAP_DEBUG_ANY,
1187             "slapd shutdown: waiting for %d threads to terminate\n",
1188             ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
1189
1190         ldap_pvt_thread_pool_destroy(&connection_pool, 1);
1191
1192         return NULL;
1193 }
1194
1195
1196 int slapd_daemon( void )
1197 {
1198         int rc;
1199
1200         connections_init();
1201
1202 #define SLAPD_LISTENER_THREAD 1
1203 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
1204
1205         /* listener as a separate THREAD */
1206         rc = ldap_pvt_thread_create( &listener_tid,
1207                 0, slapd_daemon_task, NULL );
1208
1209         if ( rc != 0 ) {
1210                 Debug( LDAP_DEBUG_ANY,
1211                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1212                 return rc;
1213         }
1214
1215         /* wait for the listener thread to complete */
1216         ldap_pvt_thread_join( listener_tid, (void *) NULL );
1217 #else
1218         /* expermimental code */
1219         listener_tid = pthread_self();
1220         slapd_daemon_task( NULL );
1221 #endif
1222
1223         return 0;
1224
1225 }
1226
1227 int sockinit(void)
1228 {
1229 #if defined( HAVE_WINSOCK2 )
1230     WORD wVersionRequested;
1231         WSADATA wsaData;
1232         int err;
1233  
1234         wVersionRequested = MAKEWORD( 2, 0 );
1235  
1236         err = WSAStartup( wVersionRequested, &wsaData );
1237         if ( err != 0 ) {
1238                 /* Tell the user that we couldn't find a usable */
1239                 /* WinSock DLL.                                  */
1240                 return -1;
1241         }
1242  
1243         /* Confirm that the WinSock DLL supports 2.0.*/
1244         /* Note that if the DLL supports versions greater    */
1245         /* than 2.0 in addition to 2.0, it will still return */
1246         /* 2.0 in wVersion since that is the version we      */
1247         /* requested.                                        */
1248  
1249         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1250                 HIBYTE( wsaData.wVersion ) != 0 )
1251         {
1252             /* Tell the user that we couldn't find a usable */
1253             /* WinSock DLL.                                  */
1254             WSACleanup();
1255             return -1; 
1256         }
1257
1258         /* The WinSock DLL is acceptable. Proceed. */
1259 #elif defined( HAVE_WINSOCK )
1260         WSADATA wsaData;
1261         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1262             return -1;
1263         }
1264 #endif
1265         return 0;
1266 }
1267
1268 int sockdestroy(void)
1269 {
1270 #if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
1271         WSACleanup();
1272 #endif
1273         return 0;
1274 }
1275
1276 RETSIGTYPE
1277 slap_sig_shutdown( int sig )
1278 {
1279         Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
1280
1281         /*
1282          * If the NT Service Manager is controlling the server, we don't
1283          * want SIGBREAK to kill the server. For some strange reason,
1284          * SIGBREAK is generated when a user logs out.
1285          */
1286
1287 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
1288         if (is_NT_Service && sig == SIGBREAK)
1289             Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
1290                   0, 0, 0);
1291         else
1292 #endif
1293         slapd_shutdown = sig;
1294
1295         WAKE_LISTENER(1);
1296
1297         /* reinstall self */
1298         (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
1299 }
1300
1301 RETSIGTYPE
1302 slap_sig_wake( int sig )
1303 {
1304         WAKE_LISTENER(1);
1305
1306         /* reinstall self */
1307         (void) SIGNAL_REINSTALL( sig, slap_sig_wake );
1308 }
1309
1310
1311 void slapd_add_internal(ber_socket_t s) {
1312         slapd_add(s);
1313 }