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