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