]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
filter_candidate tweaks, search_stack tweaks
[openldap] / servers / slapd / daemon.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 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/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16 #include <ac/unistd.h>
17
18 #include "ldap_pvt.h"
19 #include "ldap_pvt_thread.h"
20 #include "lutil.h"
21 #include "slap.h"
22
23 #ifdef HAVE_TCPD
24 #include <tcpd.h>
25 #define SLAP_STRING_UNKNOWN     STRING_UNKNOWN
26
27 int allow_severity = LOG_INFO;
28 int deny_severity = LOG_NOTICE;
29 #else /* ! TCP Wrappers */
30 #define SLAP_STRING_UNKNOWN     "unknown"
31 #endif /* ! TCP Wrappers */
32
33 #ifdef LDAP_PF_LOCAL
34 #include <sys/stat.h>
35 /* this should go in <ldap.h> as soon as it is accepted */
36 #define LDAPI_MOD_URLEXT                "x-mod"
37 #endif /* LDAP_PF_LOCAL */
38
39 #ifdef LDAP_PF_INET6
40 int slap_inet4or6 = AF_UNSPEC;
41 #else
42 int slap_inet4or6 = AF_INET;
43 #endif
44
45 /* globals */
46 time_t starttime;
47 ber_socket_t dtblsize;
48
49 Listener **slap_listeners = NULL;
50
51 #define SLAPD_LISTEN 10
52
53 static ber_socket_t wake_sds[2];
54
55 #if defined(NO_THREADS) || defined(HAVE_GNU_PTH)
56 static int waking;
57 #define WAKE_LISTENER(w) \
58 ((w && !waking) ? tcp_write( wake_sds[1], "0", 1 ), waking=1 : 0)
59 #else
60 #define WAKE_LISTENER(w) \
61 do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
62 #endif
63
64 #ifndef HAVE_WINSOCK
65 static
66 #endif
67 volatile sig_atomic_t slapd_shutdown = 0, slapd_gentle_shutdown = 0;
68
69 static struct slap_daemon {
70         ldap_pvt_thread_mutex_t sd_mutex;
71
72         ber_socket_t sd_nactives;
73
74 #ifndef HAVE_WINSOCK
75         /* In winsock, accept() returns values higher than dtblsize
76                 so don't bother with this optimization */
77         int sd_nfds;
78 #endif
79
80         fd_set sd_actives;
81         fd_set sd_readers;
82         fd_set sd_writers;
83 } slap_daemon;
84
85
86
87 #ifdef HAVE_SLP
88 /*
89  * SLP related functions
90  */
91 #include <slp.h>
92
93 #define LDAP_SRVTYPE_PREFIX "service:ldap://"
94 #define LDAPS_SRVTYPE_PREFIX "service:ldaps://"
95 static char** slapd_srvurls = NULL;
96 static SLPHandle slapd_hslp = 0;
97
98 void slapd_slp_init( const char* urls ) {
99         int i;
100
101         slapd_srvurls = ldap_str2charray( urls, " " );
102
103         if( slapd_srvurls == NULL ) return;
104
105         /* find and expand INADDR_ANY URLs */
106         for( i=0; slapd_srvurls[i] != NULL; i++ ) {
107                 if( strcmp( slapd_srvurls[i], "ldap:///" ) == 0) {
108                         char *host = ldap_pvt_get_fqdn( NULL );
109                         if ( host != NULL ) {
110                                 slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
111                                         strlen( host ) +
112                                         sizeof( LDAP_SRVTYPE_PREFIX ) );
113                                 strcpy( lutil_strcopy(slapd_srvurls[i],
114                                         LDAP_SRVTYPE_PREFIX ), host );
115
116                                 ch_free( host );
117                         }
118
119                 } else if ( strcmp( slapd_srvurls[i], "ldaps:///" ) == 0) {
120                         char *host = ldap_pvt_get_fqdn( NULL );
121                         if ( host != NULL ) {
122                                 slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
123                                         strlen( host ) +
124                                         sizeof( LDAPS_SRVTYPE_PREFIX ) );
125                                 strcpy( lutil_strcopy(slapd_srvurls[i],
126                                         LDAPS_SRVTYPE_PREFIX ), host );
127
128                                 ch_free( host );
129                         }
130                 }
131         }
132
133         /* open the SLP handle */
134         SLPOpen( "en", 0, &slapd_hslp );
135 }
136
137 void slapd_slp_deinit() {
138         if( slapd_srvurls == NULL ) return;
139
140         ldap_charray_free( slapd_srvurls );
141         slapd_srvurls = NULL;
142
143         /* close the SLP handle */
144         SLPClose( slapd_hslp );
145 }
146
147 void slapd_slp_regreport(
148         SLPHandle hslp,
149         SLPError errcode,
150         void* cookie )
151 {
152         /* empty report */
153 }
154
155 void slapd_slp_reg() {
156         int i;
157
158         if( slapd_srvurls == NULL ) return;
159
160         for( i=0; slapd_srvurls[i] != NULL; i++ ) {
161                 if( strncmp( slapd_srvurls[i], LDAP_SRVTYPE_PREFIX,
162                                 sizeof( LDAP_SRVTYPE_PREFIX ) - 1 ) == 0 ||
163                     strncmp( slapd_srvurls[i], LDAPS_SRVTYPE_PREFIX,
164                                 sizeof( LDAPS_SRVTYPE_PREFIX ) - 1 ) == 0 )
165                 {
166                         SLPReg( slapd_hslp,
167                                 slapd_srvurls[i],
168                                 SLP_LIFETIME_MAXIMUM,
169                                 "ldap",
170                                 "",
171                                 1,
172                                 slapd_slp_regreport,
173                                 NULL );
174                 }
175         }
176 }
177
178 void slapd_slp_dereg() {
179         int i;
180
181         if( slapd_srvurls == NULL ) return;
182
183         for( i=0; slapd_srvurls[i] != NULL; i++ ) {
184                 SLPDereg( slapd_hslp,
185                         slapd_srvurls[i],
186                         slapd_slp_regreport,
187                         NULL );
188         }
189 }
190 #endif /* HAVE_SLP */
191
192 /*
193  * Add a descriptor to daemon control
194  */
195 static void slapd_add(ber_socket_t s) {
196         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
197
198         assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
199         assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
200         assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
201
202 #ifndef HAVE_WINSOCK
203         if (s >= slap_daemon.sd_nfds) {
204                 slap_daemon.sd_nfds = s + 1;
205         }
206 #endif
207
208         slap_daemon.sd_nactives++;
209
210         FD_SET( s, &slap_daemon.sd_actives );
211         FD_SET( s, &slap_daemon.sd_readers );
212
213 #ifdef NEW_LOGGING
214         LDAP_LOG( CONNECTION, DETAIL1, 
215                 "slapd_add: added %ld%s%s\n", (long)s,
216                 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
217                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
218 #else
219         Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
220                 (long) s,
221             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
222                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
223 #endif
224         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
225 }
226
227 /*
228  * Remove the descriptor from daemon control
229  */
230 void slapd_remove(ber_socket_t s, int wake) {
231         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
232
233         slap_daemon.sd_nactives--;
234
235 #ifdef NEW_LOGGING
236         LDAP_LOG( CONNECTION, DETAIL1, 
237                 "slapd_remove: removing %ld%s%s\n", (long) s,
238                 FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
239                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : ""  );
240 #else
241         Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
242                 (long) s,
243             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
244                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
245 #endif
246         FD_CLR( s, &slap_daemon.sd_actives );
247         FD_CLR( s, &slap_daemon.sd_readers );
248         FD_CLR( s, &slap_daemon.sd_writers );
249
250         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
251         WAKE_LISTENER(wake || slapd_gentle_shutdown == 2);
252 }
253
254 void slapd_clr_write(ber_socket_t s, int wake) {
255         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
256
257         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
258         FD_CLR( s, &slap_daemon.sd_writers );
259
260         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
261         WAKE_LISTENER(wake);
262 }
263
264 void slapd_set_write(ber_socket_t s, int wake) {
265         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
266
267         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
268         if (!FD_ISSET(s, &slap_daemon.sd_writers))
269             FD_SET( (unsigned) s, &slap_daemon.sd_writers );
270
271         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
272         WAKE_LISTENER(wake);
273 }
274
275 void slapd_clr_read(ber_socket_t s, int wake) {
276         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
277
278         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
279         FD_CLR( s, &slap_daemon.sd_readers );
280
281         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
282         WAKE_LISTENER(wake);
283 }
284
285 void slapd_set_read(ber_socket_t s, int wake) {
286         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
287
288         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
289         if (!FD_ISSET(s, &slap_daemon.sd_readers))
290             FD_SET( s, &slap_daemon.sd_readers );
291
292         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
293         WAKE_LISTENER(wake);
294 }
295
296 static void slapd_close(ber_socket_t s) {
297 #ifdef NEW_LOGGING
298         LDAP_LOG( CONNECTION, DETAIL1, "slapd_close: closing %ld\n", (long)s, 0, 0);
299 #else
300         Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
301                 (long) s, 0, 0 );
302 #endif
303         tcp_close(s);
304 }
305
306 static void slap_free_listener_addresses(struct sockaddr **sal)
307 {
308         struct sockaddr **sap;
309
310         if (sal == NULL) {
311                 return;
312         }
313
314         for (sap = sal; *sap != NULL; sap++) {
315                 ch_free(*sap);
316         }
317
318         ch_free(sal);
319 }
320
321 #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
322 static int get_url_perms(
323         char    **exts,
324         mode_t  *perms,
325         int     *crit )
326 {
327         int     i;
328
329         assert( exts );
330         assert( perms );
331         assert( crit );
332
333         *crit = 0;
334         for ( i = 0; exts[ i ]; i++ ) {
335                 char    *type = exts[ i ];
336                 int     c = 0;
337
338                 if ( type[ 0 ] == '!' ) {
339                         c = 1;
340                         type++;
341                 }
342
343                 if ( strncasecmp( type, LDAPI_MOD_URLEXT "=", sizeof(LDAPI_MOD_URLEXT "=") - 1 ) == 0 ) {
344                         char    *value = type
345                                 + ( sizeof(LDAPI_MOD_URLEXT "=") - 1 );
346                         mode_t  p = 0;
347                         int     j;
348
349                         switch (strlen(value)) {
350                         case 4:
351                                 /* skip leading '0' */
352                                 if ( value[ 0 ] != '0' ) {
353                                         return LDAP_OTHER;
354                                 }
355                                 value++;
356
357                         case 3:
358                                 for ( j = 0; j < 3; j++) {
359                                         int     v;
360
361                                         v = value[ j ] - '0';
362
363                                         if ( v < 0 || v > 7 ) {
364                                                 return LDAP_OTHER;
365                                         }
366
367                                         p |= v << 3*(2-j);
368                                 }
369                                 break;
370
371                         case 10:
372                                 for ( j = 1; j < 10; j++ ) {
373                                         static mode_t   m[] = { 0, 
374                                                 S_IRUSR, S_IWUSR, S_IXUSR,
375                                                 S_IRGRP, S_IWGRP, S_IXGRP,
376                                                 S_IROTH, S_IWOTH, S_IXOTH
377                                         };
378                                         static char     c[] = "-rwxrwxrwx"; 
379
380                                         if ( value[ j ] == c[ j ] ) {
381                                                 p |= m[ j ];
382         
383                                         } else if ( value[ j ] != '-' ) {
384                                                 return LDAP_OTHER;
385                                         }
386                                 }
387                                 break;
388
389                         default:
390                                 return LDAP_OTHER;
391                         } 
392
393                         *crit = c;
394                         *perms = p;
395
396                         return LDAP_SUCCESS;
397                 }
398         }
399
400         return LDAP_OTHER;
401 }
402 #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */
403
404 /* port = 0 indicates AF_LOCAL */
405 static int slap_get_listener_addresses(
406         const char *host,
407         unsigned short port,
408         struct sockaddr ***sal)
409 {
410         struct sockaddr **sap;
411
412 #ifdef LDAP_PF_LOCAL
413         if ( port == 0 ) {
414                 *sal = ch_malloc(2 * sizeof(void *));
415                 if (*sal == NULL) {
416                         return -1;
417                 }
418
419                 sap = *sal;
420                 *sap = ch_malloc(sizeof(struct sockaddr_un));
421                 if (*sap == NULL)
422                         goto errexit;
423                 sap[1] = NULL;
424
425                 if ( strlen(host) >
426                      (sizeof(((struct sockaddr_un *)*sap)->sun_path) - 1) ) {
427 #ifdef NEW_LOGGING
428                         LDAP_LOG( CONNECTION, INFO, 
429                                 "slap_get_listener_addresses: domain socket path (%s) "
430                                 "too long in URL\n", host, 0, 0 );
431 #else
432                         Debug( LDAP_DEBUG_ANY,
433                                "daemon: domain socket path (%s) too long in URL",
434                                host, 0, 0);
435 #endif
436                         goto errexit;
437                 }
438
439                 (void)memset( (void *)*sap, '\0', sizeof(struct sockaddr_un) );
440                 (*sap)->sa_family = AF_LOCAL;
441                 strcpy( ((struct sockaddr_un *)*sap)->sun_path, host );
442         } else
443 #endif
444         {
445 #ifdef HAVE_GETADDRINFO
446                 struct addrinfo hints, *res, *sai;
447                 int n, err;
448                 char serv[7];
449
450                 memset( &hints, '\0', sizeof(hints) );
451                 hints.ai_flags = AI_PASSIVE;
452                 hints.ai_socktype = SOCK_STREAM;
453                 hints.ai_family = slap_inet4or6;
454                 snprintf(serv, sizeof serv, "%d", port);
455
456                 if ( (err = getaddrinfo(host, serv, &hints, &res)) ) {
457 #ifdef NEW_LOGGING
458                         LDAP_LOG( CONNECTION, INFO, 
459                                    "slap_get_listener_addresses: getaddrinfo failed: %s\n",
460                                    AC_GAI_STRERROR(err), 0, 0 );
461 #else
462                         Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed: %s\n",
463                                 AC_GAI_STRERROR(err), 0, 0);
464 #endif
465                         return -1;
466                 }
467
468                 sai = res;
469                 for (n=2; (sai = sai->ai_next) != NULL; n++) {
470                         /* EMPTY */ ;
471                 }
472                 *sal = ch_calloc(n, sizeof(void *));
473                 if (*sal == NULL) {
474                         return -1;
475                 }
476
477                 sap = *sal;
478                 *sap = NULL;
479
480                 for ( sai=res; sai; sai=sai->ai_next ) {
481                         if( sai->ai_addr == NULL ) {
482 #ifdef NEW_LOGGING
483                                 LDAP_LOG( CONNECTION, INFO,
484                                         "slap_get_listener_addresses: "
485                                         "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 );
486 #else
487                                 Debug( LDAP_DEBUG_ANY, "slap_get_listener_addresses: "
488                                         "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 );
489 #endif
490                                 freeaddrinfo(res);
491                                 goto errexit;
492                         }
493
494                         switch (sai->ai_family) {
495 #  ifdef LDAP_PF_INET6
496                         case AF_INET6:
497                                 *sap = ch_malloc(sizeof(struct sockaddr_in6));
498                                 if (*sap == NULL) {
499                                         freeaddrinfo(res);
500                                         goto errexit;
501                                 }
502                                 *(struct sockaddr_in6 *)*sap =
503                                         *((struct sockaddr_in6 *)sai->ai_addr);
504                                 break;
505 #  endif
506                         case AF_INET:
507                                 *sap = ch_malloc(sizeof(struct sockaddr_in));
508                                 if (*sap == NULL) {
509                                         freeaddrinfo(res);
510                                         goto errexit;
511                                 }
512                                 *(struct sockaddr_in *)*sap =
513                                         *((struct sockaddr_in *)sai->ai_addr);
514                                 break;
515                         default:
516                                 *sap = NULL;
517                                 break;
518                         }
519
520                         if (*sap != NULL) {
521                                 (*sap)->sa_family = sai->ai_family;
522                                 sap++;
523                                 *sap = NULL;
524                         }
525                 }
526
527                 freeaddrinfo(res);
528 #else
529                 int i, n = 1;
530                 struct in_addr in;
531                 struct hostent *he = NULL;
532
533                 if ( host == NULL ) {
534                         in.s_addr = htonl(INADDR_ANY);
535
536                 } else if ( !inet_aton( host, &in ) ) {
537                         he = gethostbyname( host );
538                         if( he == NULL ) {
539 #ifdef NEW_LOGGING
540                                 LDAP_LOG( CONNECTION, INFO, 
541                                         "slap_get_listener_addresses: invalid host %s\n", host, 0, 0 );
542 #else
543                                 Debug( LDAP_DEBUG_ANY,
544                                        "daemon: invalid host %s", host, 0, 0);
545 #endif
546                                 return -1;
547                         }
548                         for (n = 0; he->h_addr_list[n]; n++) ;
549                 }
550
551                 *sal = ch_malloc((n+1) * sizeof(void *));
552                 if (*sal == NULL) {
553                         return -1;
554                 }
555
556                 sap = *sal;
557                 for ( i = 0; i<n; i++ ) {
558                         sap[i] = ch_malloc(sizeof(struct sockaddr_in));
559                         if (*sap == NULL) {
560                                 goto errexit;
561                         }
562                         (void)memset( (void *)sap[i], '\0', sizeof(struct sockaddr_in) );
563                         sap[i]->sa_family = AF_INET;
564                         ((struct sockaddr_in *)sap[i])->sin_port = htons(port);
565                         if (he) {
566                                 AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, he->h_addr_list[i], sizeof(struct in_addr) );
567                         } else {
568                                 AC_MEMCPY( &((struct sockaddr_in *)sap[i])->sin_addr, &in, sizeof(struct in_addr) );
569                         }
570                 }
571                 sap[i] = NULL;
572 #endif
573         }
574
575         return 0;
576
577 errexit:
578         slap_free_listener_addresses(*sal);
579         return -1;
580 }
581
582 static int slap_open_listener(
583         const char* url,
584         int *listeners,
585         int *cur
586         )
587 {
588         int     num, tmp, rc;
589         Listener l;
590         Listener *li;
591         LDAPURLDesc *lud;
592         unsigned short port;
593         int err, addrlen = 0;
594         struct sockaddr **sal, **psal;
595         int socktype = SOCK_STREAM;     /* default to COTS */
596
597 #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
598         /*
599          * use safe defaults
600          */
601         int     crit = 1;
602 #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */
603
604         rc = ldap_url_parse( url, &lud );
605
606         if( rc != LDAP_URL_SUCCESS ) {
607 #ifdef NEW_LOGGING
608                 LDAP_LOG( CONNECTION, ERR, 
609                         "slap_open_listener: listen URL \"%s\" parse error %d\n",
610                         url, rc , 0 );
611 #else
612                 Debug( LDAP_DEBUG_ANY,
613                         "daemon: listen URL \"%s\" parse error=%d\n",
614                         url, rc, 0 );
615 #endif
616                 return rc;
617         }
618
619         l.sl_url.bv_val = NULL;
620
621 #ifndef HAVE_TLS
622         if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
623 #ifdef NEW_LOGGING
624                 LDAP_LOG( CONNECTION, INFO, 
625                            "slap_open_listener: TLS is not supported (%s)\n", url, 0, 0 );
626 #else
627                 Debug( LDAP_DEBUG_ANY,
628                         "daemon: TLS not supported (%s)\n",
629                         url, 0, 0 );
630 #endif
631                 ldap_free_urldesc( lud );
632                 return -1;
633         }
634
635         if(! lud->lud_port ) {
636                 lud->lud_port = LDAP_PORT;
637         }
638
639 #else
640         l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );
641
642         if(! lud->lud_port ) {
643                 lud->lud_port = l.sl_is_tls ? LDAPS_PORT : LDAP_PORT;
644         }
645 #endif
646
647         port = (unsigned short) lud->lud_port;
648
649         tmp = ldap_pvt_url_scheme2proto(lud->lud_scheme);
650         if ( tmp == LDAP_PROTO_IPC ) {
651 #ifdef LDAP_PF_LOCAL
652                 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
653                         err = slap_get_listener_addresses(LDAPI_SOCK, 0, &sal);
654                 } else {
655                         err = slap_get_listener_addresses(lud->lud_host, 0, &sal);
656                 }
657 #else
658
659 #ifdef NEW_LOGGING
660                 LDAP_LOG( CONNECTION, INFO, 
661                         "slap_open_listener: URL scheme is not supported: %s\n", url, 0, 0 );
662 #else
663                 Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s",
664                         url, 0, 0);
665 #endif
666                 ldap_free_urldesc( lud );
667                 return -1;
668 #endif
669         } else {
670                 if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
671                         || strcmp(lud->lud_host, "*") == 0 )
672                 {
673                         err = slap_get_listener_addresses(NULL, port, &sal);
674                 } else {
675                         err = slap_get_listener_addresses(lud->lud_host, port, &sal);
676                 }
677         }
678 #ifdef LDAP_CONNECTIONLESS
679         l.sl_is_udp = ( tmp == LDAP_PROTO_UDP );
680 #endif
681
682 #if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
683         if ( lud->lud_exts ) {
684                 err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit );
685         } else {
686                 l.sl_perms = S_IRWXU | S_IRWXO;
687         }
688 #endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */
689
690         ldap_free_urldesc( lud );
691         if ( err ) {
692                 return -1;
693         }
694
695         /* If we got more than one address returned, we need to make space
696          * for it in the slap_listeners array.
697          */
698         for ( num=0; sal[num]; num++ );
699         if ( num > 1 ) {
700                 *listeners += num-1;
701                 slap_listeners = ch_realloc( slap_listeners, (*listeners + 1) * sizeof(Listener *) );
702         }
703
704         psal = sal;
705         while ( *sal != NULL ) {
706                 switch( (*sal)->sa_family ) {
707                 case AF_INET:
708 #ifdef LDAP_PF_INET6
709                 case AF_INET6:
710 #endif
711 #ifdef LDAP_PF_LOCAL
712                 case AF_LOCAL:
713 #endif
714                         break;
715                 default:
716                         sal++;
717                         continue;
718                 }
719 #ifdef LDAP_CONNECTIONLESS
720                 if( l.sl_is_udp ) socktype = SOCK_DGRAM;
721 #endif
722                 l.sl_sd = socket( (*sal)->sa_family, socktype, 0);
723                 if ( l.sl_sd == AC_SOCKET_INVALID ) {
724                         int err = sock_errno();
725 #ifdef NEW_LOGGING
726                         LDAP_LOG( CONNECTION, ERR, 
727                                 "slap_open_listener: socket() failed errno=%d (%s)\n",
728                                 err, sock_errstr(err), 0 );
729 #else
730                         Debug( LDAP_DEBUG_ANY,
731                                 "daemon: socket() failed errno=%d (%s)\n", err,
732                                 sock_errstr(err), 0 );
733 #endif
734                         sal++;
735                         continue;
736                 }
737 #ifndef HAVE_WINSOCK
738                 if ( l.sl_sd >= dtblsize ) {
739 #ifdef NEW_LOGGING
740                         LDAP_LOG( CONNECTION, ERR, 
741                                 "slap_open_listener: listener descriptor %ld is too "
742                                 "great %ld\n", (long)l.sl_sd, (long)dtblsize, 0 );
743 #else
744                         Debug( LDAP_DEBUG_ANY,
745                                "daemon: listener descriptor %ld is too great %ld\n",
746                                (long) l.sl_sd, (long) dtblsize, 0 );
747 #endif
748                         tcp_close( l.sl_sd );
749                         sal++;
750                         continue;
751                 }
752 #endif
753 #ifdef LDAP_PF_LOCAL
754                 if ( (*sal)->sa_family == AF_LOCAL ) {
755                         unlink ( ((struct sockaddr_un *)*sal)->sun_path );
756                 } else
757 #endif
758                 {
759 #ifdef SO_REUSEADDR
760                         /* enable address reuse */
761                         tmp = 1;
762                         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
763                                          (char *) &tmp, sizeof(tmp) );
764                         if ( rc == AC_SOCKET_ERROR ) {
765                                 int err = sock_errno();
766 #ifdef NEW_LOGGING
767                                 LDAP_LOG( CONNECTION, INFO, 
768                                         "slap_open_listener: setsockopt( %ld, SO_REUSEADDR ) "
769                                         "failed errno %d (%s)\n", (long)l.sl_sd, err, 
770                                         sock_errstr(err) );
771 #else
772                                 Debug( LDAP_DEBUG_ANY,
773                                        "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
774                                        (long) l.sl_sd, err, sock_errstr(err) );
775 #endif
776                         }
777 #endif
778                 }
779
780                 switch( (*sal)->sa_family ) {
781                 case AF_INET:
782                         addrlen = sizeof(struct sockaddr_in);
783                         break;
784 #ifdef LDAP_PF_INET6
785                 case AF_INET6:
786 #ifdef IPV6_V6ONLY
787                         /* Try to use IPv6 sockets for IPv6 only */
788                         tmp = 1;
789                         rc = setsockopt( l.sl_sd, IPPROTO_IPV6, IPV6_V6ONLY,
790                                          (char *) &tmp, sizeof(tmp) );
791                         if ( rc == AC_SOCKET_ERROR ) {
792                                 int err = sock_errno();
793 #ifdef NEW_LOGGING
794                                 LDAP_LOG( CONNECTION, INFO,
795                                            "slap_open_listener: setsockopt( %ld, IPV6_V6ONLY ) failed errno %d (%s)\n",
796                                            (long)l.sl_sd, err, sock_errstr(err) );
797 #else
798                                 Debug( LDAP_DEBUG_ANY,
799                                        "slapd(%ld): setsockopt(IPV6_V6ONLY) failed errno=%d (%s)\n",
800                                        (long) l.sl_sd, err, sock_errstr(err) );
801 #endif
802                         }
803 #endif
804                         addrlen = sizeof(struct sockaddr_in6);
805                         break;
806 #endif
807 #ifdef LDAP_PF_LOCAL
808                 case AF_LOCAL:
809                         addrlen = sizeof(struct sockaddr_un);
810                         break;
811 #endif
812                 }
813
814                 if (bind(l.sl_sd, *sal, addrlen)) {
815                         err = sock_errno();
816 #ifdef NEW_LOGGING
817                 LDAP_LOG( CONNECTION, INFO, 
818                         "slap_open_listener: bind(%ld) failed errno=%d (%s)\n",
819                         (long)l.sl_sd, err, sock_errstr(err) );
820 #else
821                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
822                        (long) l.sl_sd, err, sock_errstr(err) );
823 #endif
824                         tcp_close( l.sl_sd );
825                         sal++;
826                         continue;
827                 }
828
829         switch ( (*sal)->sa_family ) {
830 #ifdef LDAP_PF_LOCAL
831         case AF_LOCAL: {
832                 char *addr = ((struct sockaddr_un *)*sal)->sun_path;
833 #if 0 /* don't muck with socket perms */
834                 if ( chmod( addr, l.sl_perms ) < 0 && crit ) {
835                         int err = sock_errno();
836 #ifdef NEW_LOGGING
837                         LDAP_LOG( CONNECTION, INFO, 
838                                 "slap_open_listener: fchmod(%ld) failed errno=%d (%s)\n",
839                                 (long)l.sl_sd, err, sock_errstr(err) );
840 #else
841                         Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
842                                (long) l.sl_sd, err, sock_errstr(err) );
843 #endif
844                         tcp_close( l.sl_sd );
845                         slap_free_listener_addresses(psal);
846                         return -1;
847                 }
848 #endif
849                 l.sl_name.bv_len = strlen(addr) + sizeof("PATH=") - 1;
850                 l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len + 1 );
851                 snprintf( l.sl_name.bv_val, l.sl_name.bv_len + 1, 
852                                 "PATH=%s", addr );
853         } break;
854 #endif /* LDAP_PF_LOCAL */
855
856         case AF_INET: {
857                 char *s;
858 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
859                 char addr[INET_ADDRSTRLEN];
860                 inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr,
861                            addr, sizeof(addr) );
862                 s = addr;
863 #else
864                 s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr );
865 #endif
866                 port = ntohs( ((struct sockaddr_in *)*sal) ->sin_port );
867                 l.sl_name.bv_val = ber_memalloc( sizeof("IP=255.255.255.255:65535") );
868                 snprintf( l.sl_name.bv_val, sizeof("IP=255.255.255.255:65535"),
869                         "IP=%s:%d",
870                          s != NULL ? s : SLAP_STRING_UNKNOWN, port );
871                 l.sl_name.bv_len = strlen( l.sl_name.bv_val );
872         } break;
873
874 #ifdef LDAP_PF_INET6
875         case AF_INET6: {
876                 char addr[INET6_ADDRSTRLEN];
877                 inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
878                            addr, sizeof addr);
879                 port = ntohs( ((struct sockaddr_in6 *)*sal)->sin6_port );
880                 l.sl_name.bv_len = strlen(addr) + sizeof("IP= 65535");
881                 l.sl_name.bv_val = ber_memalloc( l.sl_name.bv_len );
882                 snprintf( l.sl_name.bv_val, l.sl_name.bv_len, "IP=%s %d", 
883                                 addr, port );
884                 l.sl_name.bv_len = strlen( l.sl_name.bv_val );
885         } break;
886 #endif /* LDAP_PF_INET6 */
887
888         default:
889 #ifdef NEW_LOGGING
890                 LDAP_LOG( CONNECTION, INFO, 
891                         "slap_open_listener: unsupported address family (%d)\n",
892                         (int)(*sal)->sa_family, 0, 0 );
893 #else
894                 Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
895                         (int) (*sal)->sa_family, 0, 0 );
896 #endif
897                 break;
898         }
899
900         AC_MEMCPY(&l.sl_sa, *sal, addrlen);
901         ber_str2bv( url, 0, 1, &l.sl_url);
902         li = ch_malloc( sizeof( Listener ) );
903         *li = l;
904         slap_listeners[*cur] = li;
905         (*cur)++;
906         sal++;
907
908         } /* while ( *sal != NULL ) */
909
910         slap_free_listener_addresses(psal);
911
912         if ( l.sl_url.bv_val == NULL )
913         {
914 #ifdef NEW_LOGGING
915                 LDAP_LOG( CONNECTION, RESULTS, 
916                         "slap_open_listener: failed on %s\n", url, 0, 0 );
917 #else
918                 Debug( LDAP_DEBUG_TRACE,
919                         "slap_open_listener: failed on %s\n", url, 0, 0 );
920 #endif
921                 return -1;
922         }
923
924 #ifdef NEW_LOGGING
925         LDAP_LOG( CONNECTION, RESULTS, 
926                 "slap_open_listener: daemon initialized %s\n",
927                 l.sl_url.bv_val, 0, 0 );
928 #else
929         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
930                 l.sl_url.bv_val, 0, 0 );
931 #endif
932         return 0;
933 }
934
935 static int sockinit(void);
936 static int sockdestroy(void);
937
938 int slapd_daemon_init( const char *urls )
939 {
940         int i, j, n, rc;
941         char **u;
942
943 #ifdef NEW_LOGGING
944         LDAP_LOG( CONNECTION, ARGS, 
945                 "slapd_daemon_init: %s\n", urls ? urls : "<null>", 0, 0 );
946 #else
947         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
948                 urls ? urls : "<null>", 0, 0 );
949 #endif
950         if( (rc = sockinit()) != 0 ) {
951                 return rc;
952         }
953
954 #ifdef HAVE_SYSCONF
955         dtblsize = sysconf( _SC_OPEN_MAX );
956 #elif HAVE_GETDTABLESIZE
957         dtblsize = getdtablesize();
958 #else
959         dtblsize = FD_SETSIZE;
960 #endif
961
962 #ifdef FD_SETSIZE
963         if(dtblsize > FD_SETSIZE) {
964                 dtblsize = FD_SETSIZE;
965         }
966 #endif  /* !FD_SETSIZE */
967
968         /* open a pipe (or something equivalent connected to itself).
969          * we write a byte on this fd whenever we catch a signal. The main
970          * loop will be select'ing on this socket, and will wake up when
971          * this byte arrives.
972          */
973         if( (rc = lutil_pair( wake_sds )) < 0 ) {
974 #ifdef NEW_LOGGING
975                 LDAP_LOG( CONNECTION, ERR, 
976                         "slap_daemon_init: lutil_pair() failed rc=%d\n", rc, 0, 0);
977 #else
978                 Debug( LDAP_DEBUG_ANY,
979                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
980 #endif
981                 return rc;
982         }
983
984         FD_ZERO( &slap_daemon.sd_readers );
985         FD_ZERO( &slap_daemon.sd_writers );
986
987         if( urls == NULL ) {
988                 urls = "ldap:///";
989         }
990
991         u = ldap_str2charray( urls, " " );
992
993         if( u == NULL || u[0] == NULL ) {
994 #ifdef NEW_LOGGING
995                 LDAP_LOG( CONNECTION, ERR, 
996                         "slap_daemon_init: no urls (%s) provided.\n", urls, 0, 0 );
997 #else
998                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
999                         urls, 0, 0 );
1000 #endif
1001                 return -1;
1002         }
1003
1004         for( i=0; u[i] != NULL; i++ ) {
1005 #ifdef NEW_LOGGING
1006                 LDAP_LOG( CONNECTION, DETAIL1, 
1007                         "slap_daemon_init: listen on %s\n.", u[i], 0, 0 );
1008 #else
1009                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
1010                         u[i], 0, 0 );
1011 #endif
1012         }
1013
1014         if( i == 0 ) {
1015 #ifdef NEW_LOGGING
1016                 LDAP_LOG( CONNECTION, INFO, 
1017                          "slap_daemon_init: no listeners to open (%s)\n", urls, 0, 0 );
1018 #else
1019                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
1020                         urls, 0, 0 );
1021 #endif
1022                 ldap_charray_free( u );
1023                 return -1;
1024         }
1025
1026 #ifdef NEW_LOGGING
1027         LDAP_LOG( CONNECTION, INFO, 
1028                 "slap_daemon_init: %d listeners to open...\n", i, 0, 0 );
1029 #else
1030         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
1031                 i, 0, 0 );
1032 #endif
1033         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
1034
1035         for(n = 0, j = 0; u[n]; n++ ) {
1036                 if ( slap_open_listener( u[n], &i, &j ) ) {
1037                         ldap_charray_free( u );
1038                         return -1;
1039                 }
1040         }
1041         slap_listeners[j] = NULL;
1042
1043 #ifdef NEW_LOGGING
1044         LDAP_LOG( CONNECTION, DETAIL1, 
1045                 "slap_daemon_init: %d listeners opened\n", i, 0, 0 );
1046 #else
1047         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
1048                 i, 0, 0 );
1049 #endif
1050
1051 #ifdef HAVE_SLP
1052         slapd_slp_init( urls );
1053         slapd_slp_reg();
1054 #endif
1055
1056         ldap_charray_free( u );
1057         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
1058         return !i;
1059 }
1060
1061
1062 int
1063 slapd_daemon_destroy(void)
1064 {
1065         connections_destroy();
1066         tcp_close( wake_sds[1] );
1067         tcp_close( wake_sds[0] );
1068         sockdestroy();
1069
1070 #ifdef HAVE_SLP
1071         slapd_slp_dereg();
1072         slapd_slp_deinit();
1073 #endif
1074
1075         return 0;
1076 }
1077
1078
1079 static void
1080 close_listeners(
1081         int remove
1082 )
1083 {
1084         int l;
1085
1086         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1087                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1088                         if ( remove )
1089                                 slapd_remove( slap_listeners[l]->sl_sd, 0 );
1090 #ifdef LDAP_PF_LOCAL
1091                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
1092                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1093                         }
1094 #endif /* LDAP_PF_LOCAL */
1095                         slapd_close( slap_listeners[l]->sl_sd );
1096                 }
1097                 if ( slap_listeners[l]->sl_url.bv_val )
1098                         ber_memfree( slap_listeners[l]->sl_url.bv_val );
1099                 if ( slap_listeners[l]->sl_name.bv_val )
1100                         ber_memfree( slap_listeners[l]->sl_name.bv_val );
1101                 free ( slap_listeners[l] );
1102                 slap_listeners[l] = NULL;
1103         }
1104 }
1105
1106
1107 static void *
1108 slapd_daemon_task(
1109         void *ptr
1110 )
1111 {
1112         int l;
1113         time_t  last_idle_check = 0;
1114         time( &starttime );
1115
1116         if ( global_idletimeout > 0 ) {
1117                 last_idle_check = slap_get_time();
1118         }
1119         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1120                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1121                         continue;
1122 #ifdef LDAP_CONNECTIONLESS
1123                 /* Since this is connectionless, the data port is the
1124                  * listening port. The listen() and accept() calls
1125                  * are unnecessary.
1126                  */
1127                 if ( slap_listeners[l]->sl_is_udp ) {
1128                         slapd_add( slap_listeners[l]->sl_sd );
1129                         continue;
1130                 }
1131 #endif
1132
1133                 if ( listen( slap_listeners[l]->sl_sd, SLAPD_LISTEN ) == -1 ) {
1134                         int err = sock_errno();
1135
1136 #ifdef LDAP_PF_INET6
1137                         /* If error is EADDRINUSE, we are trying to listen to INADDR_ANY and
1138                          * we are already listening to in6addr_any, then we want to ignore
1139                          * this and continue.
1140                          */
1141                         if ( err == EADDRINUSE ) {
1142                                 int i;
1143                                 struct sockaddr_in sa = slap_listeners[l]->sl_sa.sa_in_addr;
1144                                 struct sockaddr_in6 sa6;
1145                                 
1146                                 if ( sa.sin_family == AF_INET &&
1147                                      sa.sin_addr.s_addr == htonl(INADDR_ANY) ) {
1148                                         for ( i = 0 ; i < l; i++ ) {
1149                                                 sa6 = slap_listeners[i]->sl_sa.sa_in6_addr;
1150                                                 if ( sa6.sin6_family == AF_INET6 &&
1151                                                      !memcmp( &sa6.sin6_addr, &in6addr_any, sizeof(struct in6_addr) ) )
1152                                                         break;
1153                                         }
1154
1155                                         if ( i < l ) {
1156                                                 /* We are already listening to in6addr_any */
1157 #ifdef NEW_LOGGING
1158                                                 LDAP_LOG(CONNECTION, WARNING,
1159                                                            "slapd_daemon_task: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n", 0, 0, 0 );
1160 #else
1161                                                 Debug( LDAP_DEBUG_CONNS,
1162                                                        "daemon: Attempt to listen to 0.0.0.0 failed, already listening on ::, assuming IPv4 included\n",
1163                                                        0, 0, 0 );
1164 #endif
1165                                                 slapd_close( slap_listeners[l]->sl_sd );
1166                                                 slap_listeners[l]->sl_sd = AC_SOCKET_INVALID;
1167                                                 continue;
1168                                         }
1169                                 }
1170                         }
1171 #endif                          
1172 #ifdef NEW_LOGGING
1173                         LDAP_LOG( CONNECTION, ERR, 
1174                                 "slapd_daemon_task: listen( %s, 5 ) failed errno=%d (%s)\n",
1175                                 slap_listeners[l]->sl_url.bv_val, err, sock_errstr(err) );
1176 #else
1177                         Debug( LDAP_DEBUG_ANY,
1178                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
1179                                         slap_listeners[l]->sl_url.bv_val, err,
1180                                         sock_errstr(err) );
1181 #endif
1182                         return( (void*)-1 );
1183                 }
1184
1185                 slapd_add( slap_listeners[l]->sl_sd );
1186         }
1187
1188 #ifdef HAVE_NT_SERVICE_MANAGER
1189         if ( started_event != NULL ) {
1190                 ldap_pvt_thread_cond_signal( &started_event );
1191         }
1192 #endif
1193         /* initialization complete. Here comes the loop. */
1194
1195         while ( !slapd_shutdown ) {
1196                 ber_socket_t i;
1197                 int ns;
1198                 int at;
1199                 ber_socket_t nfds;
1200 #define SLAPD_EBADF_LIMIT 16
1201                 int ebadf = 0;
1202                 int emfile = 0;
1203
1204 #define SLAPD_IDLE_CHECK_LIMIT 4
1205                 time_t  now;
1206
1207
1208                 fd_set                  readfds;
1209                 fd_set                  writefds;
1210                 Sockaddr                from;
1211
1212                 struct timeval          zero;
1213                 struct timeval          *tvp;
1214
1215                 if( emfile ) {
1216                         now = slap_get_time();
1217                         connections_timeout_idle( now );
1218                 }
1219                 else if ( global_idletimeout > 0 ) {
1220                         now = slap_get_time();
1221                         if ( difftime( last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) {
1222                                 connections_timeout_idle( now );
1223                         }
1224                 }
1225
1226 #ifdef SIGHUP
1227                 if( slapd_gentle_shutdown ) {
1228                         ber_socket_t active;
1229
1230                         if( slapd_gentle_shutdown == 1 ) {
1231                                 Debug( LDAP_DEBUG_ANY, "slapd gentle shutdown\n", 0, 0, 0 );
1232                                 close_listeners( 1 );
1233                                 global_restrictops |= SLAP_RESTRICT_OP_WRITES;
1234                                 slapd_gentle_shutdown = 2;
1235                         }
1236
1237                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
1238                         active = slap_daemon.sd_nactives;
1239                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
1240                         if( active == 0 ) {
1241                                 slapd_shutdown = 2;
1242                                 break;
1243                         }
1244                 }
1245 #endif
1246
1247                 FD_ZERO( &writefds );
1248                 FD_ZERO( &readfds );
1249
1250                 zero.tv_sec = 0;
1251                 zero.tv_usec = 0;
1252
1253                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
1254
1255 #ifdef FD_SET_MANUAL_COPY
1256                 for( s = 0; s < nfds; s++ ) {
1257                         if(FD_ISSET( &slap_sd_readers, s )) {
1258                                 FD_SET( s, &readfds );
1259                         }
1260                         if(FD_ISSET( &slap_sd_writers, s )) {
1261                                 FD_SET( s, &writefds );
1262                         }
1263                 }
1264 #else
1265                 AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
1266                 AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
1267 #endif
1268                 assert(!FD_ISSET(wake_sds[0], &readfds));
1269                 FD_SET( wake_sds[0], &readfds );
1270
1271                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1272                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1273                                 continue;
1274                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
1275                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
1276                 }
1277
1278 #ifndef HAVE_WINSOCK
1279                 nfds = slap_daemon.sd_nfds;
1280 #else
1281                 nfds = dtblsize;
1282 #endif
1283
1284                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
1285
1286                 at = ldap_pvt_thread_pool_backload(&connection_pool);
1287
1288 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
1289                 tvp = NULL;
1290 #else
1291                 tvp = at ? &zero : NULL;
1292 #endif
1293
1294                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1295                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1296                                 continue;
1297
1298 #ifdef NEW_LOGGING
1299                         LDAP_LOG( CONNECTION, DETAIL1, 
1300                                 "slapd_daemon_task: select: listen=%d "
1301                                 "active_threads=%d tvp=%s\n",
1302                                 slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "zero" );
1303 #else
1304                         Debug( LDAP_DEBUG_CONNS,
1305                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
1306                                         slap_listeners[l]->sl_sd, at,
1307                                         tvp == NULL ? "NULL" : "zero" );
1308 #endif
1309                 }
1310
1311                 switch(ns = select( nfds, &readfds,
1312 #ifdef HAVE_WINSOCK
1313                         /* don't pass empty fd_set */
1314                         ( writefds.fd_count > 0 ? &writefds : NULL ),
1315 #else
1316                         &writefds,
1317 #endif
1318                         NULL, tvp ))
1319                 {
1320                 case -1: {      /* failure - try again */
1321                                 int err = sock_errno();
1322
1323                                 if( err == EBADF
1324 #ifdef WSAENOTSOCK
1325                                         /* you'd think this would be EBADF */
1326                                         || err == WSAENOTSOCK
1327 #endif
1328                                 ) {
1329                                         if (++ebadf < SLAPD_EBADF_LIMIT)
1330                                                 continue;
1331                                 }
1332
1333                                 if( err != EINTR ) {
1334 #ifdef NEW_LOGGING
1335                                         LDAP_LOG( CONNECTION, INFO, 
1336                                                 "slapd_daemon_task: select failed (%d): %s\n",
1337                                                 err, sock_errstr(err), 0 );
1338 #else
1339                                         Debug( LDAP_DEBUG_CONNS,
1340                                                 "daemon: select failed (%d): %s\n",
1341                                                 err, sock_errstr(err), 0 );
1342 #endif
1343                                         slapd_shutdown = 2;
1344                                 }
1345                         }
1346                         continue;
1347
1348                 case 0:         /* timeout - let threads run */
1349                         ebadf = 0;
1350 #ifdef NEW_LOGGING
1351                         LDAP_LOG( CONNECTION, DETAIL2,
1352                                    "slapd_daemon_task: select timeout - yielding\n", 0, 0, 0 );
1353 #else
1354                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
1355                             0, 0, 0 );
1356 #endif
1357                         ldap_pvt_thread_yield();
1358                         continue;
1359
1360                 default:        /* something happened - deal with it */
1361                         if( slapd_shutdown ) continue;
1362
1363                         ebadf = 0;
1364 #ifdef NEW_LOGGING
1365                         LDAP_LOG( CONNECTION, DETAIL2, 
1366                                    "slapd_daemon_task: activity on %d descriptors\n", ns, 0, 0 );
1367 #else
1368                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
1369                                 ns, 0, 0 );
1370 #endif
1371                         /* FALL THRU */
1372                 }
1373
1374                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
1375                         char c[BUFSIZ];
1376                         tcp_read( wake_sds[0], c, sizeof(c) );
1377 #if defined(NO_THREADS) || defined(HAVE_GNU_PTH)
1378                         waking = 0;
1379 #endif
1380                         continue;
1381                 }
1382
1383                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1384                         ber_socket_t s;
1385                         socklen_t len = sizeof(from);
1386                         long id;
1387                         slap_ssf_t ssf = 0;
1388                         char *authid = NULL;
1389 #ifdef SLAPD_RLOOKUPS
1390                         char hbuf[NI_MAXHOST];
1391 #endif
1392
1393                         char    *dnsname = NULL;
1394                         char    *peeraddr = NULL;
1395 #ifdef LDAP_PF_LOCAL
1396                         char    peername[MAXPATHLEN + sizeof("PATH=")];
1397 #elif defined(LDAP_PF_INET6)
1398                         char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
1399 #else
1400                         char    peername[sizeof("IP=255.255.255.255:65336")];
1401 #endif /* LDAP_PF_LOCAL */
1402
1403                         peername[0] = '\0';
1404
1405                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1406                                 continue;
1407
1408                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
1409                                 continue;
1410
1411 #ifdef LDAP_CONNECTIONLESS
1412                         if ( slap_listeners[l]->sl_is_udp ) {
1413                                 /* The first time we receive a query, we set this
1414                                  * up as a "connection". It remains open for the life
1415                                  * of the slapd.
1416                                  */
1417                                 if ( slap_listeners[l]->sl_is_udp < 2 ) {
1418                                     id = connection_init(
1419                                         slap_listeners[l]->sl_sd,
1420                                         slap_listeners[l], "", "",
1421                                         2, ssf, authid );
1422                                     slap_listeners[l]->sl_is_udp++;
1423                                 }
1424                                 continue;
1425                         }
1426 #endif
1427
1428                         s = accept( slap_listeners[l]->sl_sd,
1429                                 (struct sockaddr *) &from, &len );
1430                         if ( s == AC_SOCKET_INVALID ) {
1431                                 int err = sock_errno();
1432
1433 #ifdef EMFILE
1434                                 if( err == EMFILE ) {
1435                                         emfile++;
1436                                 } else
1437 #endif
1438 #ifdef ENFILE
1439                                 if( err == ENFILE ) {
1440                                         emfile++;
1441                                 } else 
1442 #endif
1443                                 {
1444                                         emfile=0;
1445                                 }
1446
1447                                 if( emfile < 3 ) {
1448 #ifdef NEW_LOGGING
1449                                         LDAP_LOG( CONNECTION, ERR, 
1450                                                 "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n",
1451                                                 (long)slap_listeners[l]->sl_sd, 
1452                                                 err, sock_errstr(err) );
1453 #else
1454                                         Debug( LDAP_DEBUG_ANY,
1455                                             "daemon: accept(%ld) failed errno=%d (%s)\n",
1456                                             (long) slap_listeners[l]->sl_sd, err,
1457                                             sock_errstr(err) );
1458 #endif
1459                                 } else {
1460                                         /* prevent busy loop */
1461 #  ifdef HAVE_USLEEP
1462                                         if( emfile % 4 == 3 ) usleep( 250 );
1463 #  else
1464                                         if( emfile % 8 == 7 ) sleep( 1 );
1465 #  endif
1466                                 }
1467
1468                                 ldap_pvt_thread_yield();
1469                                 continue;
1470                         }
1471                         emfile = 0;
1472
1473 #ifndef HAVE_WINSOCK
1474                         /* make sure descriptor number isn't too great */
1475                         if ( s >= dtblsize ) {
1476 #ifdef NEW_LOGGING
1477                                 LDAP_LOG( CONNECTION, ERR, 
1478                                    "slapd_daemon_task: %ld beyond descriptor table size %ld\n",
1479                                    (long)s, (long)dtblsize, 0 );
1480 #else
1481                                 Debug( LDAP_DEBUG_ANY,
1482                                         "daemon: %ld beyond descriptor table size %ld\n",
1483                                         (long) s, (long) dtblsize, 0 );
1484 #endif
1485
1486                                 slapd_close(s);
1487                                 ldap_pvt_thread_yield();
1488                                 continue;
1489                         }
1490 #endif
1491
1492 #ifdef LDAP_DEBUG
1493                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
1494
1495                         /* newly accepted stream should not be in any of the FD SETS */
1496                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
1497                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
1498                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
1499
1500                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
1501 #endif
1502
1503 #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY )
1504 #ifdef LDAP_PF_LOCAL
1505                         /* for IPv4 and IPv6 sockets only */
1506                         if ( from.sa_addr.sa_family != AF_LOCAL )
1507 #endif /* LDAP_PF_LOCAL */
1508                         {
1509                                 int rc;
1510                                 int tmp;
1511 #ifdef SO_KEEPALIVE
1512                                 /* enable keep alives */
1513                                 tmp = 1;
1514                                 rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
1515                                         (char *) &tmp, sizeof(tmp) );
1516                                 if ( rc == AC_SOCKET_ERROR ) {
1517                                         int err = sock_errno();
1518 #ifdef NEW_LOGGING
1519                                         LDAP_LOG( CONNECTION, ERR, 
1520                                                 "slapd_daemon_task: setsockopt( %ld, SO_KEEPALIVE)"
1521                                            " failed errno=%d (%s)\n",
1522                                                 (long)s, err, sock_errstr(err) );
1523 #else
1524                                         Debug( LDAP_DEBUG_ANY,
1525                                                 "slapd(%ld): setsockopt(SO_KEEPALIVE) failed "
1526                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
1527 #endif
1528                                 }
1529 #endif
1530 #ifdef TCP_NODELAY
1531                                 /* enable no delay */
1532                                 tmp = 1;
1533                                 rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
1534                                         (char *)&tmp, sizeof(tmp) );
1535                                 if ( rc == AC_SOCKET_ERROR ) {
1536                                         int err = sock_errno();
1537 #ifdef NEW_LOGGING
1538                                         LDAP_LOG( CONNECTION, ERR, 
1539                                                 "slapd_daemon_task: setsockopt( %ld, "
1540                                                 "TCP_NODELAY) failed errno=%d (%s)\n",
1541                                                 (long)s, err, sock_errstr(err) );
1542 #else
1543                                         Debug( LDAP_DEBUG_ANY,
1544                                                 "slapd(%ld): setsockopt(TCP_NODELAY) failed "
1545                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
1546 #endif
1547                                 }
1548 #endif
1549                         }
1550 #endif
1551
1552 #ifdef NEW_LOGGING
1553                         LDAP_LOG( CONNECTION, DETAIL1, 
1554                                 "slapd_daemon_task: new connection on %ld\n", (long)s, 0, 0 );
1555 #else
1556                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
1557                                 (long) s, 0, 0 );
1558 #endif
1559                         switch ( from.sa_addr.sa_family ) {
1560 #  ifdef LDAP_PF_LOCAL
1561                         case AF_LOCAL:
1562                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
1563                                 ssf = LDAP_PVT_SASL_LOCAL_SSF;
1564                                 {
1565                                         uid_t uid;
1566                                         gid_t gid;
1567
1568                                         if( getpeereid( s, &uid, &gid ) == 0 ) {
1569                                                 authid = ch_malloc(
1570                                                         sizeof("uidnumber=4294967295+gidnumber=4294967295,"
1571                                                                 "cn=peercred,cn=external,cn=auth"));
1572                                                 sprintf(authid, "uidnumber=%d+gidnumber=%d,"
1573                                                         "cn=peercred,cn=external,cn=auth",
1574                                                         (int) uid, (int) gid);
1575                                         }
1576                                 }
1577                                 dnsname = "local";
1578                                 break;
1579 #endif /* LDAP_PF_LOCAL */
1580
1581 #  ifdef LDAP_PF_INET6
1582                         case AF_INET6:
1583                         if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
1584                                 peeraddr = inet_ntoa( *((struct in_addr *)
1585                                                         &from.sa_in6_addr.sin6_addr.s6_addr[12]) );
1586                                 sprintf( peername, "IP=%s:%d",
1587                                          peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
1588                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
1589                         } else {
1590                                 char addr[INET6_ADDRSTRLEN];
1591
1592                                 peeraddr = (char *) inet_ntop( AF_INET6,
1593                                                       &from.sa_in6_addr.sin6_addr,
1594                                                       addr, sizeof addr );
1595                                 sprintf( peername, "IP=%s %d",
1596                                          peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
1597                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
1598                         }
1599                         break;
1600 #  endif /* LDAP_PF_INET6 */
1601
1602                         case AF_INET:
1603                         peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
1604                         sprintf( peername, "IP=%s:%d",
1605                                 peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
1606                                 (unsigned) ntohs( from.sa_in_addr.sin_port ) );
1607                                 break;
1608
1609                         default:
1610                                 slapd_close(s);
1611                                 continue;
1612                         }
1613
1614                         if ( ( from.sa_addr.sa_family == AF_INET )
1615 #ifdef LDAP_PF_INET6
1616                                 || ( from.sa_addr.sa_family == AF_INET6 )
1617 #endif
1618                         ) {
1619 #ifdef SLAPD_RLOOKUPS
1620                                 if ( use_reverse_lookup ) {
1621                                         char *herr;
1622                                         if (ldap_pvt_get_hname( (const struct sockaddr *)&from, len, hbuf,
1623                                                 sizeof(hbuf), &herr ) == 0) {
1624                                                 ldap_pvt_str2lower( hbuf );
1625                                                 dnsname = hbuf;
1626                                         }
1627                                 }
1628 #else
1629                                 dnsname = NULL;
1630 #endif /* SLAPD_RLOOKUPS */
1631
1632 #ifdef HAVE_TCPD
1633                                 if ( !hosts_ctl("slapd",
1634                                                 dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
1635                                                 peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
1636                                                 SLAP_STRING_UNKNOWN ))
1637                                 {
1638                                         /* DENY ACCESS */
1639                                         Statslog( LDAP_DEBUG_STATS,
1640                                                 "fd=%ld DENIED from %s (%s)",
1641                                                 (long) s,
1642                                                 dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
1643                                                 peeraddr != NULL ? peeraddr : SLAP_STRING_UNKNOWN,
1644                                                 0, 0 );
1645                                         slapd_close(s);
1646                                         continue;
1647                                 }
1648 #endif /* HAVE_TCPD */
1649                         }
1650
1651                         id = connection_init(s,
1652                                 slap_listeners[l],
1653                                 dnsname != NULL ? dnsname : SLAP_STRING_UNKNOWN,
1654                                 peername,
1655 #ifdef HAVE_TLS
1656                                 slap_listeners[l]->sl_is_tls,
1657 #else
1658                                 0,
1659 #endif
1660                                 ssf,
1661                                 authid );
1662
1663                         if( authid ) ch_free(authid);
1664
1665                         if( id < 0 ) {
1666 #ifdef NEW_LOGGING
1667                                 LDAP_LOG( CONNECTION, INFO, 
1668                                         "slapd_daemon_task: "
1669                                         "connection_init(%ld, %s, %s) "
1670                                         "failed.\n",
1671                                         (long)s, peername, 
1672                                         slap_listeners[l]->sl_name.bv_val );
1673 #else
1674                                 Debug( LDAP_DEBUG_ANY,
1675                                         "daemon: connection_init(%ld, %s, %s) "
1676                                         "failed.\n",
1677                                         (long) s,
1678                                         peername,
1679                                         slap_listeners[l]->sl_name.bv_val );
1680 #endif
1681                                 slapd_close(s);
1682                                 continue;
1683                         }
1684
1685                         Statslog( LDAP_DEBUG_STATS,
1686                                 "conn=%ld fd=%ld ACCEPT from %s (%s)\n",
1687                                 id, (long) s,
1688                                 peername,
1689                                 slap_listeners[l]->sl_name.bv_val,
1690                                 0 );
1691
1692                         slapd_add( s );
1693                         continue;
1694                 }
1695
1696 #ifdef LDAP_DEBUG
1697 #ifdef NEW_LOGGING
1698                 LDAP_LOG( CONNECTION, DETAIL2,
1699                            "slapd_daemon_task: activity on ", 0, 0, 0 );
1700 #else
1701                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
1702 #endif
1703 #ifdef HAVE_WINSOCK
1704                 for ( i = 0; i < readfds.fd_count; i++ ) {
1705 #ifdef NEW_LOGGING
1706                         LDAP_LOG( CONNECTION, DETAIL2, 
1707                                 " %d%s", readfds.fd_array[i], "r", 0, 0 );
1708 #else
1709                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1710                                 readfds.fd_array[i], "r", 0 );
1711 #endif
1712                 }
1713                 for ( i = 0; i < writefds.fd_count; i++ ) {
1714 #ifdef NEW_LOGGING
1715                         LDAP_LOG( CONNECTION, DETAIL2, 
1716                                 " %d%s", writefds.fd_array[i], "w" , 0 );
1717 #else
1718                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1719                                 writefds.fd_array[i], "w", 0 );
1720 #endif
1721                 }
1722
1723 #else
1724                 for ( i = 0; i < nfds; i++ ) {
1725                         int     r, w;
1726                         int     is_listener = 0;
1727
1728                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1729                                 if ( i == slap_listeners[l]->sl_sd ) {
1730 #ifdef LDAP_CONNECTIONLESS
1731                                 /* The listener is the data port. Don't
1732                                  * skip it.
1733                                  */
1734                                         if (slap_listeners[l]->sl_is_udp) continue;
1735 #endif
1736                                         is_listener = 1;
1737                                         break;
1738                                 }
1739                         }
1740                         if ( is_listener ) {
1741                                 continue;
1742                         }
1743                         r = FD_ISSET( i, &readfds );
1744                         w = FD_ISSET( i, &writefds );
1745                         if ( r || w ) {
1746 #ifdef NEW_LOGGING
1747                                 LDAP_LOG( CONNECTION, DETAIL2, 
1748                                         " %d%s%s", i, r ? "r" : "", w ? "w" : "" );
1749 #else
1750                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
1751                                     r ? "r" : "", w ? "w" : "" );
1752 #endif
1753                         }
1754                 }
1755 #endif
1756 #ifdef NEW_LOGGING
1757                 LDAP_LOG( CONNECTION, DETAIL2, "\n", 0, 0, 0 );
1758 #else
1759                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
1760 #endif
1761
1762 #endif
1763
1764                 /* loop through the writers */
1765 #ifdef HAVE_WINSOCK
1766                 for ( i = 0; i < writefds.fd_count; i++ )
1767 #else
1768                 for ( i = 0; i < nfds; i++ )
1769 #endif
1770                 {
1771                         ber_socket_t wd;
1772                         int is_listener = 0;
1773 #ifdef HAVE_WINSOCK
1774                         wd = writefds.fd_array[i];
1775 #else
1776                         if( ! FD_ISSET( i, &writefds ) ) {
1777                                 continue;
1778                         }
1779                         wd = i;
1780 #endif
1781
1782                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1783                                 if ( i == slap_listeners[l]->sl_sd ) {
1784 #ifdef LDAP_CONNECTIONLESS
1785                                         if (slap_listeners[l]->sl_is_udp) continue;
1786 #endif
1787                                         is_listener = 1;
1788                                         break;
1789                                 }
1790                         }
1791                         if ( is_listener ) {
1792                                 continue;
1793                         }
1794 #ifdef NEW_LOGGING
1795                         LDAP_LOG( CONNECTION, DETAIL2, 
1796                                 "slapd_daemon_task: write active on %d\n", wd, 0, 0 );
1797 #else
1798                         Debug( LDAP_DEBUG_CONNS,
1799                                 "daemon: write active on %d\n",
1800                                 wd, 0, 0 );
1801 #endif
1802                         /*
1803                          * NOTE: it is possible that the connection was closed
1804                          * and that the stream is now inactive.
1805                          * connection_write() must valid the stream is still
1806                          * active.
1807                          */
1808
1809                         if ( connection_write( wd ) < 0 ) {
1810                                 FD_CLR( (unsigned) wd, &readfds );
1811                                 slapd_close( wd );
1812                         }
1813                 }
1814
1815 #ifdef HAVE_WINSOCK
1816                 for ( i = 0; i < readfds.fd_count; i++ )
1817 #else
1818                 for ( i = 0; i < nfds; i++ )
1819 #endif
1820                 {
1821                         ber_socket_t rd;
1822                         int is_listener = 0;
1823
1824 #ifdef HAVE_WINSOCK
1825                         rd = readfds.fd_array[i];
1826 #else
1827                         if( ! FD_ISSET( i, &readfds ) ) {
1828                                 continue;
1829                         }
1830                         rd = i;
1831 #endif
1832
1833                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1834                                 if ( rd == slap_listeners[l]->sl_sd ) {
1835 #ifdef LDAP_CONNECTIONLESS
1836                                         if (slap_listeners[l]->sl_is_udp) continue;
1837 #endif
1838                                         is_listener = 1;
1839                                         break;
1840                                 }
1841                         }
1842                         if ( is_listener ) {
1843                                 continue;
1844                         }
1845
1846 #ifdef NEW_LOGGING
1847                         LDAP_LOG( CONNECTION, DETAIL2, 
1848                                 "slapd_daemon_task: read activity on %d\n", rd, 0, 0 );
1849 #else
1850                         Debug ( LDAP_DEBUG_CONNS,
1851                                 "daemon: read activity on %d\n", rd, 0, 0 );
1852 #endif
1853                         /*
1854                          * NOTE: it is possible that the connection was closed
1855                          * and that the stream is now inactive.
1856                          * connection_read() must valid the stream is still
1857                          * active.
1858                          */
1859
1860                         if ( connection_read( rd ) < 0 ) {
1861                                 slapd_close( rd );
1862                         }
1863                 }
1864                 ldap_pvt_thread_yield();
1865         }
1866
1867         if( slapd_shutdown == 1 ) {
1868 #ifdef NEW_LOGGING
1869                 LDAP_LOG( CONNECTION, CRIT,
1870                    "slapd_daemon_task: shutdown requested and initiated.\n", 0, 0, 0 );
1871 #else
1872                 Debug( LDAP_DEBUG_TRACE,
1873                         "daemon: shutdown requested and initiated.\n",
1874                         0, 0, 0 );
1875 #endif
1876
1877         } else if ( slapd_shutdown == 2 ) {
1878 #ifdef HAVE_NT_SERVICE_MANAGER
1879 #ifdef NEW_LOGGING
1880                         LDAP_LOG( CONNECTION, CRIT,
1881                            "slapd_daemon_task: shutdown initiated by Service Manager.\n",
1882                            0, 0, 0);
1883 #else
1884                         Debug( LDAP_DEBUG_TRACE,
1885                                "daemon: shutdown initiated by Service Manager.\n",
1886                                0, 0, 0);
1887 #endif
1888 #else /* !HAVE_NT_SERVICE_MANAGER */
1889 #ifdef NEW_LOGGING
1890                         LDAP_LOG( CONNECTION, CRIT,
1891                            "slapd_daemon_task: abnormal condition, "
1892                            "shutdown initiated.\n", 0, 0, 0 );
1893 #else
1894                         Debug( LDAP_DEBUG_TRACE,
1895                                "daemon: abnormal condition, shutdown initiated.\n",
1896                                0, 0, 0 );
1897 #endif
1898 #endif /* !HAVE_NT_SERVICE_MANAGER */
1899         } else {
1900 #ifdef NEW_LOGGING
1901                 LDAP_LOG( CONNECTION, CRIT,
1902                    "slapd_daemon_task: no active streams, shutdown initiated.\n", 
1903                    0, 0, 0 );
1904 #else
1905                 Debug( LDAP_DEBUG_TRACE,
1906                        "daemon: no active streams, shutdown initiated.\n",
1907                        0, 0, 0 );
1908 #endif
1909         }
1910
1911         if( slapd_gentle_shutdown != 2 ) {
1912                 close_listeners ( 0 );
1913         }
1914
1915         free ( slap_listeners );
1916         slap_listeners = NULL;
1917
1918         if( !slapd_gentle_shutdown ) {
1919                 connections_shutdown();
1920         }
1921
1922 #ifdef NEW_LOGGING
1923         LDAP_LOG( CONNECTION, CRIT, 
1924                 "slapd_daemon_task: shutdown waiting for %d threads to terminate.\n",
1925                 ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
1926 #else
1927         Debug( LDAP_DEBUG_ANY,
1928             "slapd shutdown: waiting for %d threads to terminate\n",
1929             ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
1930 #endif
1931         ldap_pvt_thread_pool_destroy(&connection_pool, 1);
1932
1933         return NULL;
1934 }
1935
1936
1937 int slapd_daemon( void )
1938 {
1939         int rc;
1940
1941         connections_init();
1942
1943 #define SLAPD_LISTENER_THREAD 1
1944 #if defined( SLAPD_LISTENER_THREAD )
1945         {
1946                 ldap_pvt_thread_t       listener_tid;
1947
1948                 /* listener as a separate THREAD */
1949                 rc = ldap_pvt_thread_create( &listener_tid,
1950                         0, slapd_daemon_task, NULL );
1951
1952                 if ( rc != 0 ) {
1953 #ifdef NEW_LOGGING
1954                         LDAP_LOG( CONNECTION, ERR, 
1955                                 "slapd_daemon: listener ldap_pvt_thread_create failed (%d).\n",
1956                                 rc, 0, 0 );
1957 #else
1958                         Debug( LDAP_DEBUG_ANY,
1959                         "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1960 #endif
1961                         return rc;
1962                 }
1963  
1964                 /* wait for the listener thread to complete */
1965                 ldap_pvt_thread_join( listener_tid, (void *) NULL );
1966         }
1967 #else
1968         /* experimental code */
1969         slapd_daemon_task( NULL );
1970 #endif
1971
1972         return 0;
1973
1974 }
1975
1976 int sockinit(void)
1977 {
1978 #if defined( HAVE_WINSOCK2 )
1979     WORD wVersionRequested;
1980         WSADATA wsaData;
1981         int err;
1982
1983         wVersionRequested = MAKEWORD( 2, 0 );
1984
1985         err = WSAStartup( wVersionRequested, &wsaData );
1986         if ( err != 0 ) {
1987                 /* Tell the user that we couldn't find a usable */
1988                 /* WinSock DLL.                                  */
1989                 return -1;
1990         }
1991
1992         /* Confirm that the WinSock DLL supports 2.0.*/
1993         /* Note that if the DLL supports versions greater    */
1994         /* than 2.0 in addition to 2.0, it will still return */
1995         /* 2.0 in wVersion since that is the version we      */
1996         /* requested.                                        */
1997
1998         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1999                 HIBYTE( wsaData.wVersion ) != 0 )
2000         {
2001             /* Tell the user that we couldn't find a usable */
2002             /* WinSock DLL.                                  */
2003             WSACleanup();
2004             return -1;
2005         }
2006
2007         /* The WinSock DLL is acceptable. Proceed. */
2008 #elif defined( HAVE_WINSOCK )
2009         WSADATA wsaData;
2010         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
2011             return -1;
2012         }
2013 #endif
2014         return 0;
2015 }
2016
2017 int sockdestroy(void)
2018 {
2019 #if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
2020         WSACleanup();
2021 #endif
2022         return 0;
2023 }
2024
2025 RETSIGTYPE
2026 slap_sig_shutdown( int sig )
2027 {
2028 #ifdef NEW_LOGGING
2029         LDAP_LOG( CONNECTION, CRIT, 
2030                 "slap_sig_shutdown: signal %d\n", sig, 0, 0 );
2031 #else
2032         Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
2033 #endif
2034
2035         /*
2036          * If the NT Service Manager is controlling the server, we don't
2037          * want SIGBREAK to kill the server. For some strange reason,
2038          * SIGBREAK is generated when a user logs out.
2039          */
2040
2041 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
2042         if (is_NT_Service && sig == SIGBREAK)
2043 #ifdef NEW_LOGGING
2044             LDAP_LOG( CONNECTION, CRIT,
2045                     "slap_sig_shutdown: SIGBREAK ignored.\n", 0, 0, 0 );
2046 #else
2047             Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
2048                   0, 0, 0);
2049 #endif
2050         else
2051 #endif
2052 #ifdef SIGHUP
2053         if (sig == SIGHUP && global_gentlehup && slapd_gentle_shutdown == 0)
2054                 slapd_gentle_shutdown = 1;
2055         else
2056 #endif
2057         slapd_shutdown = 1;
2058
2059         WAKE_LISTENER(1);
2060
2061         /* reinstall self */
2062         (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
2063 }
2064
2065 RETSIGTYPE
2066 slap_sig_wake( int sig )
2067 {
2068         WAKE_LISTENER(1);
2069
2070         /* reinstall self */
2071         (void) SIGNAL_REINSTALL( sig, slap_sig_wake );
2072 }
2073
2074
2075 void slapd_add_internal(ber_socket_t s) {
2076         slapd_add(s);
2077 }
2078
2079 Listener ** slapd_get_listeners(void) {
2080         return slap_listeners;
2081 }