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