]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
676e174420d01f487a3da80846f5771b09fdbeda
[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 l;
646         time_t  last_idle_check = slap_get_time();
647         time( &starttime );
648
649         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
650                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
651                         continue;
652
653                 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
654                         int err = sock_errno();
655                         Debug( LDAP_DEBUG_ANY,
656                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
657                                         slap_listeners[l]->sl_url, err,
658                                         sock_errstr(err) );
659                         return( (void*)-1 );
660                 }
661
662                 slapd_add( slap_listeners[l]->sl_sd );
663         }
664
665 #ifdef HAVE_NT_SERVICE_MANAGER
666         if ( started_event != NULL ) {
667                 ldap_pvt_thread_cond_signal( &started_event );
668         }
669 #endif
670         /* initialization complete. Here comes the loop. */
671
672         while ( !slapd_shutdown ) {
673                 ber_socket_t i;
674                 int ns;
675                 int at;
676                 ber_socket_t nfds;
677 #define SLAPD_EBADF_LIMIT 16
678                 int ebadf = 0;
679
680 #define SLAPD_IDLE_CHECK_LIMIT 4
681                 time_t  now = slap_get_time();
682
683
684                 fd_set                  readfds;
685                 fd_set                  writefds;
686                 Sockaddr                from;
687
688 #if defined(SLAPD_RLOOKUPS)
689         struct hostent          *hp;
690 #endif
691                 struct timeval          zero;
692                 struct timeval          *tvp;
693
694                 if( global_idletimeout > 0 && difftime(
695                         last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
696                         now ) < 0 )
697                 {
698                         connections_timeout_idle(now);
699                 }
700
701                 FD_ZERO( &writefds );
702                 FD_ZERO( &readfds );
703
704                 zero.tv_sec = 0;
705                 zero.tv_usec = 0;
706
707                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
708
709 #ifdef FD_SET_MANUAL_COPY
710                 for( s = 0; s < nfds; s++ ) {
711                         if(FD_ISSET( &slap_sd_readers, s )) {
712                                 FD_SET( s, &readfds );
713                         }
714                         if(FD_ISSET( &slap_sd_writers, s )) {
715                                 FD_SET( s, &writefds );
716                         }
717                 }
718 #else
719                 AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
720                 AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
721 #endif
722                 assert(!FD_ISSET(wake_sds[0], &readfds));
723                 FD_SET( wake_sds[0], &readfds );
724
725                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
726                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
727                                 continue;
728                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
729                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
730                 }
731
732 #ifndef HAVE_WINSOCK
733                 nfds = slap_daemon.sd_nfds;
734 #else
735                 nfds = dtblsize;
736 #endif
737
738                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
739
740                 at = ldap_pvt_thread_pool_backload(&connection_pool);
741
742 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
743                 tvp = NULL;
744 #else
745                 tvp = at ? &zero : NULL;
746 #endif
747
748                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
749                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
750                                 continue;
751
752                         Debug( LDAP_DEBUG_CONNS,
753                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
754                                         slap_listeners[l]->sl_sd, at,
755                                         tvp == NULL ? "NULL" : "zero" );
756                 }
757
758                 switch(ns = select( nfds, &readfds,
759 #ifdef HAVE_WINSOCK
760                         /* don't pass empty fd_set */
761                         ( writefds.fd_count > 0 ? &writefds : NULL ),
762 #else
763                         &writefds,
764 #endif
765                         NULL, tvp ))
766                 {
767                 case -1: {      /* failure - try again */
768                                 int err = sock_errno();
769
770                                 if( err == EBADF 
771 #ifdef WSAENOTSOCK
772                                         /* you'd think this would be EBADF */
773                                         || err == WSAENOTSOCK
774 #endif
775                                 ) {
776                                         if (++ebadf < SLAPD_EBADF_LIMIT)
777                                                 continue;
778                                 }
779
780                                 if( err != EINTR ) {
781                                         Debug( LDAP_DEBUG_CONNS,
782                                                 "daemon: select failed (%d): %s\n",
783                                                 err, sock_errstr(err), 0 );
784
785                                         slapd_shutdown = -1;
786                                 }
787                         }
788                         continue;
789
790                 case 0:         /* timeout - let threads run */
791                         ebadf = 0;
792                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
793                             0, 0, 0 );
794                 ldap_pvt_thread_yield();
795                         continue;
796
797                 default:        /* something happened - deal with it */
798                         ebadf = 0;
799                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
800                                 ns, 0, 0 );
801                         /* FALL THRU */
802                 }
803
804                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
805                         char c[BUFSIZ];
806                         tcp_read( wake_sds[0], c, sizeof(c) );
807 #ifdef NO_THREADS
808                         waking = 0;
809 #endif
810                         continue;
811                 }
812
813                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
814                         ber_int_t s;
815                         socklen_t len = sizeof(from);
816                         long id;
817                         slap_ssf_t ssf = 0;
818                         char *authid = NULL;
819
820                         char    *dnsname;
821                         char    *peeraddr;
822 #ifdef LDAP_PF_LOCAL
823                         char    peername[MAXPATHLEN + sizeof("PATH=")];
824 #elif defined(LDAP_PF_INET6)
825                         char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
826 #else
827                         char    peername[sizeof("IP=255.255.255.255:65336")];
828 #endif /* LDAP_PF_LOCAL */
829
830                         peername[0] = '\0';
831
832                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
833                                 continue;
834
835                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
836                                 continue;
837
838                         if ( (s = accept( slap_listeners[l]->sl_sd,
839                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
840                         {
841                                 int err = sock_errno();
842                                 Debug( LDAP_DEBUG_ANY,
843                                     "daemon: accept(%ld) failed errno=%d (%s)\n",
844                                     (long) slap_listeners[l]->sl_sd, err,
845                                     sock_errstr(err) );
846                                 continue;
847                         }
848
849 #ifndef HAVE_WINSOCK
850                         /* make sure descriptor number isn't too great */
851                         if ( s >= dtblsize ) {
852                                 Debug( LDAP_DEBUG_ANY,
853                                         "daemon: %ld beyond descriptor table size %ld\n",
854                                         (long) s, (long) dtblsize, 0 );
855                                 slapd_close(s);
856                                 continue;
857                         }
858 #endif
859
860 #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY )
861 #ifdef LDAP_PF_LOCAL
862                         /* for IPv4 and IPv6 sockets only */
863                         if ( from.sa_addr.sa_family != AF_LOCAL )
864 #endif /* LDAP_PF_LOCAL */
865                         {
866                                 int rc;
867                                 int tmp;
868 #ifdef SO_KEEPALIVE
869                                 /* enable keep alives */
870                                 tmp = 1;
871                                 rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
872                                         (char *) &tmp, sizeof(tmp) );
873                                 if ( rc == AC_SOCKET_ERROR ) {
874                                         int err = sock_errno();
875                                         Debug( LDAP_DEBUG_ANY,
876                                                 "slapd(%ld): setsockopt(SO_KEEPALIVE) failed "
877                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
878                                 }
879 #endif
880 #ifdef TCP_NODELAY
881                                 /* enable no delay */
882                                 tmp = 1;
883                                 rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
884                                         (char *)&tmp, sizeof(tmp) );
885                                 if ( rc == AC_SOCKET_ERROR ) {
886                                         int err = sock_errno();
887                                         Debug( LDAP_DEBUG_ANY,
888                                                 "slapd(%ld): setsockopt(TCP_NODELAY) failed "
889                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
890                                 }
891 #endif
892                         }
893 #endif
894
895
896 #ifdef LDAP_DEBUG
897                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
898
899                         /* newly accepted stream should not be in any of the FD SETS */
900                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
901                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
902                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
903
904                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
905 #endif
906
907                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
908                                 (long) s, 0, 0 );
909
910                         len = sizeof(from);
911
912                         if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
913                                 int err = sock_errno();
914                                 Debug( LDAP_DEBUG_ANY,
915                                         "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
916                                         (long) s, err, sock_errstr(err) );
917                                 slapd_close(s);
918                                 continue;
919                         }
920
921                         switch ( from.sa_addr.sa_family ) {
922 #  ifdef LDAP_PF_LOCAL
923                         case AF_LOCAL:
924                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
925                                 ssf = LDAP_PVT_SASL_LOCAL_SSF;
926                                 break;
927 #endif /* LDAP_PF_LOCAL */
928
929 #  ifdef LDAP_PF_INET6
930                         case AF_INET6:
931                         if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
932                                 peeraddr = inet_ntoa( *((struct in_addr *)
933                                                         &from.sa_in6_addr.sin6_addr.s6_addr[12]) );
934                                 sprintf( peername, "IP=%s:%d",
935                                          peeraddr != NULL ? peeraddr : "unknown",
936                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
937                         } else {
938                                 char addr[INET6_ADDRSTRLEN];
939                                 sprintf( peername, "IP=%s %d",
940                                          inet_ntop( AF_INET6,
941                                                     &from.sa_in6_addr.sin6_addr,
942                                                     addr, sizeof addr) ? addr : "unknown",
943                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
944                         }
945                         break;
946 #  endif /* LDAP_PF_INET6 */
947
948                         case AF_INET:
949                         peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
950                         sprintf( peername, "IP=%s:%d",
951                                 peeraddr != NULL ? peeraddr : "unknown",
952                                 (unsigned) ntohs( from.sa_in_addr.sin_port ) );
953                                 break;
954
955                         default:
956                                 slapd_close(s);
957                                 continue;
958                         }
959                         if ( ( from.sa_addr.sa_family == AF_INET ) 
960 #ifdef LDAP_PF_INET6
961                                 || ( from.sa_addr.sa_family == AF_INET6 )
962 #endif
963                         ) {
964 #ifdef SLAPD_RLOOKUPS
965 #  ifdef LDAP_PF_INET6
966                                 if ( from.sa_addr.sa_family == AF_INET6 )
967                                         hp = gethostbyaddr(
968                                                 (char *)&(from.sa_in6_addr.sin6_addr),
969                                                 sizeof(from.sa_in6_addr.sin6_addr),
970                                                 AF_INET6 );
971                                 else
972 #  endif LDAP_PF_INET6
973                                 hp = gethostbyaddr(
974                                         (char *) &(from.sa_in_addr.sin_addr),
975                                         sizeof(from.sa_in_addr.sin_addr),
976                                         AF_INET );
977                                 dnsname = hp ? ldap_pvt_str2lower( hp->h_name ) : NULL;
978 #else
979                                 dnsname = NULL;
980 #endif /* SLAPD_RLOOKUPS */
981
982 #ifdef HAVE_TCPD
983                                 if ( !hosts_ctl("slapd",
984                                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
985                                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
986                                                 STRING_UNKNOWN ))
987                                 {
988                                         /* DENY ACCESS */
989                                         Statslog( LDAP_DEBUG_ANY,
990                                                 "fd=%ld host access from %s (%s) denied.\n",
991                                                 (long) s,
992                                                 dnsname != NULL ? dnsname : "unknown",
993                                                 peeraddr != NULL ? peeraddr : "unknown",
994                                                 0, 0 );
995                                         slapd_close(s);
996                                         continue;
997                                 }
998 #endif /* HAVE_TCPD */
999                         }
1000
1001                         id = connection_init(s,
1002                                 slap_listeners[l]->sl_url,
1003                                 dnsname != NULL ? dnsname : "unknown",
1004                                 peername,
1005                                 slap_listeners[l]->sl_name,
1006 #ifdef HAVE_TLS
1007                                 slap_listeners[l]->sl_is_tls,
1008 #else
1009                                 0,
1010 #endif
1011                                 ssf,
1012                                 authid );
1013
1014                         if( authid ) ch_free(authid);
1015
1016                         if( id < 0 ) {
1017                                 Debug( LDAP_DEBUG_ANY,
1018                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
1019                                         (long) s,
1020                                         peername,
1021                                         slap_listeners[l]->sl_name );
1022                                 slapd_close(s);
1023                                 continue;
1024                         }
1025
1026                         Statslog( LDAP_DEBUG_STATS,
1027                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
1028                                 id, (long) s,
1029                                 peername,
1030                                 slap_listeners[l]->sl_name,
1031                                 0 );
1032
1033                         slapd_add( s );
1034                         continue;
1035                 }
1036
1037 #ifdef LDAP_DEBUG
1038                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
1039 #ifdef HAVE_WINSOCK
1040                 for ( i = 0; i < readfds.fd_count; i++ ) {
1041                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1042                                 readfds.fd_array[i], "r", 0 );
1043                 }
1044                 for ( i = 0; i < writefds.fd_count; i++ ) {
1045                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1046                                 writefds.fd_array[i], "w", 0 );
1047                 }
1048 #else
1049                 for ( i = 0; i < nfds; i++ ) {
1050                         int     r, w;
1051                         int     is_listener = 0;
1052
1053                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1054                                 if ( i == slap_listeners[l]->sl_sd ) {
1055                                         is_listener = 1;
1056                                         break;
1057                                 }
1058                         }
1059                         if ( is_listener ) {
1060                                 continue;
1061                         }
1062                         r = FD_ISSET( i, &readfds );
1063                         w = FD_ISSET( i, &writefds );
1064                         if ( r || w ) {
1065                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
1066                                     r ? "r" : "", w ? "w" : "" );
1067                         }
1068                 }
1069 #endif
1070                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
1071 #endif
1072
1073                 /* loop through the writers */
1074 #ifdef HAVE_WINSOCK
1075                 for ( i = 0; i < writefds.fd_count; i++ )
1076 #else
1077                 for ( i = 0; i < nfds; i++ )
1078 #endif
1079                 {
1080                         ber_socket_t wd;
1081                         int is_listener = 0;
1082 #ifdef HAVE_WINSOCK
1083                         wd = writefds.fd_array[i];
1084 #else
1085                         if( ! FD_ISSET( i, &writefds ) ) {
1086                                 continue;
1087                         }
1088                         wd = i;
1089 #endif
1090
1091                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1092                                 if ( i == slap_listeners[l]->sl_sd ) {
1093                                         is_listener = 1;
1094                                         break;
1095                                 }
1096                         }
1097                         if ( is_listener ) {
1098                                 continue;
1099                         }
1100                         Debug( LDAP_DEBUG_CONNS,
1101                                 "daemon: write active on %d\n",
1102                                 wd, 0, 0 );
1103
1104                         /*
1105                          * NOTE: it is possible that the connection was closed
1106                          * and that the stream is now inactive.
1107                          * connection_write() must valid the stream is still
1108                          * active.
1109                          */
1110
1111                         if ( connection_write( wd ) < 0 ) {
1112                                 FD_CLR( (unsigned) wd, &readfds );
1113                                 slapd_close( wd );
1114                         }
1115                 }
1116
1117 #ifdef HAVE_WINSOCK
1118                 for ( i = 0; i < readfds.fd_count; i++ )
1119 #else
1120                 for ( i = 0; i < nfds; i++ )
1121 #endif
1122                 {
1123                         ber_socket_t rd;
1124                         int is_listener = 0;
1125
1126 #ifdef HAVE_WINSOCK
1127                         rd = readfds.fd_array[i];
1128 #else
1129                         if( ! FD_ISSET( i, &readfds ) ) {
1130                                 continue;
1131                         }
1132                         rd = i;
1133 #endif
1134
1135                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1136                                 if ( rd == slap_listeners[l]->sl_sd ) {
1137                                         is_listener = 1;
1138                                         break;
1139                                 }
1140                         }
1141                         if ( is_listener ) {
1142                                 continue;
1143                         }
1144
1145                         Debug ( LDAP_DEBUG_CONNS,
1146                                 "daemon: read activity on %d\n", rd, 0, 0 );
1147
1148                         /*
1149                          * NOTE: it is possible that the connection was closed
1150                          * and that the stream is now inactive.
1151                          * connection_read() must valid the stream is still
1152                          * active.
1153                          */
1154
1155                         if ( connection_read( rd ) < 0 ) {
1156                                 slapd_close( rd );
1157                         }
1158                 }
1159                 ldap_pvt_thread_yield();
1160         }
1161
1162         if( slapd_shutdown > 0 ) {
1163                 Debug( LDAP_DEBUG_TRACE,
1164                         "daemon: shutdown requested and initiated.\n",
1165                         0, 0, 0 );
1166
1167         } else if ( slapd_shutdown < 0 ) {
1168 #ifdef HAVE_NT_SERVICE_MANAGER
1169                 if (slapd_shutdown == -1)
1170                     Debug( LDAP_DEBUG_TRACE,
1171                           "daemon: shutdown initiated by Service Manager.\n",
1172                           0, 0, 0);
1173                 else
1174 #endif
1175                 Debug( LDAP_DEBUG_TRACE,
1176                         "daemon: abnormal condition, shutdown initiated.\n",
1177                         0, 0, 0 );
1178         } else {
1179                 Debug( LDAP_DEBUG_TRACE,
1180                         "daemon: no active streams, shutdown initiated.\n",
1181                         0, 0, 0 );
1182         }
1183
1184         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1185                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1186 #ifdef LDAP_PF_LOCAL
1187                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
1188                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1189                         }
1190 #endif /* LDAP_PF_LOCAL */
1191                         slapd_close( slap_listeners[l]->sl_sd );
1192                         break;
1193                 }
1194         }
1195
1196         Debug( LDAP_DEBUG_ANY,
1197             "slapd shutdown: waiting for %d threads to terminate\n",
1198             ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
1199
1200         ldap_pvt_thread_pool_destroy(&connection_pool, 1);
1201
1202         return NULL;
1203 }
1204
1205
1206 int slapd_daemon( void )
1207 {
1208         int rc;
1209
1210         connections_init();
1211
1212 #define SLAPD_LISTENER_THREAD 1
1213 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
1214
1215         /* listener as a separate THREAD */
1216         rc = ldap_pvt_thread_create( &listener_tid,
1217                 0, slapd_daemon_task, NULL );
1218
1219         if ( rc != 0 ) {
1220                 Debug( LDAP_DEBUG_ANY,
1221                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1222                 return rc;
1223         }
1224
1225         /* wait for the listener thread to complete */
1226         ldap_pvt_thread_join( listener_tid, (void *) NULL );
1227 #else
1228         /* expermimental code */
1229         listener_tid = pthread_self();
1230         slapd_daemon_task( NULL );
1231 #endif
1232
1233         return 0;
1234
1235 }
1236
1237 int sockinit(void)
1238 {
1239 #if defined( HAVE_WINSOCK2 )
1240     WORD wVersionRequested;
1241         WSADATA wsaData;
1242         int err;
1243  
1244         wVersionRequested = MAKEWORD( 2, 0 );
1245  
1246         err = WSAStartup( wVersionRequested, &wsaData );
1247         if ( err != 0 ) {
1248                 /* Tell the user that we couldn't find a usable */
1249                 /* WinSock DLL.                                  */
1250                 return -1;
1251         }
1252  
1253         /* Confirm that the WinSock DLL supports 2.0.*/
1254         /* Note that if the DLL supports versions greater    */
1255         /* than 2.0 in addition to 2.0, it will still return */
1256         /* 2.0 in wVersion since that is the version we      */
1257         /* requested.                                        */
1258  
1259         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1260                 HIBYTE( wsaData.wVersion ) != 0 )
1261         {
1262             /* Tell the user that we couldn't find a usable */
1263             /* WinSock DLL.                                  */
1264             WSACleanup();
1265             return -1; 
1266         }
1267
1268         /* The WinSock DLL is acceptable. Proceed. */
1269 #elif defined( HAVE_WINSOCK )
1270         WSADATA wsaData;
1271         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1272             return -1;
1273         }
1274 #endif
1275         return 0;
1276 }
1277
1278 int sockdestroy(void)
1279 {
1280 #if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
1281         WSACleanup();
1282 #endif
1283         return 0;
1284 }
1285
1286 RETSIGTYPE
1287 slap_sig_shutdown( int sig )
1288 {
1289         Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
1290
1291         /*
1292          * If the NT Service Manager is controlling the server, we don't
1293          * want SIGBREAK to kill the server. For some strange reason,
1294          * SIGBREAK is generated when a user logs out.
1295          */
1296
1297 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
1298         if (is_NT_Service && sig == SIGBREAK)
1299             Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
1300                   0, 0, 0);
1301         else
1302 #endif
1303         slapd_shutdown = sig;
1304
1305         WAKE_LISTENER(1);
1306
1307         /* reinstall self */
1308         (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
1309 }
1310
1311 RETSIGTYPE
1312 slap_sig_wake( int sig )
1313 {
1314         WAKE_LISTENER(1);
1315
1316         /* reinstall self */
1317         (void) SIGNAL_REINSTALL( sig, slap_sig_wake );
1318 }
1319
1320
1321 void slapd_add_internal(ber_socket_t s) {
1322         slapd_add(s);
1323 }