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