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