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