]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
bb8236d01f6652b7352e06b367a3f4dcf06cdf67
[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_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 static ber_socket_t wake_sds[2];
63
64 #ifdef NO_THREADS
65 static int waking;
66 #define WAKE_LISTENER(w) \
67 ((w && !waking) ? tcp_write( wake_sds[1], "0", 1 ), waking=1 : 0)
68 #else
69 #define WAKE_LISTENER(w) \
70 do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
71 #endif
72
73 #ifdef HAVE_NT_SERVICE_MANAGER
74 /* in nt_main.c */
75 extern ldap_pvt_thread_cond_t                   started_event;
76 extern int        is_NT_Service;
77 #endif
78
79 #ifndef HAVE_WINSOCK
80 static 
81 #endif
82 volatile sig_atomic_t slapd_shutdown = 0;
83
84 static ldap_pvt_thread_t        listener_tid;
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  * Add a descriptor to daemon control
104  */
105 static void slapd_add(ber_socket_t s) {
106         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
107
108         assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
109         assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
110         assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
111
112 #ifndef HAVE_WINSOCK
113         if (s >= slap_daemon.sd_nfds) {
114                 slap_daemon.sd_nfds = s + 1;
115         }
116 #endif
117
118         FD_SET( s, &slap_daemon.sd_actives );
119         FD_SET( s, &slap_daemon.sd_readers );
120
121         Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
122                 (long) s,
123             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
124                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
125
126         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
127 }
128
129 /*
130  * Remove the descriptor from daemon control
131  */
132 void slapd_remove(ber_socket_t s, int wake) {
133         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
134
135         Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
136                 (long) s,
137             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
138                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
139
140         FD_CLR( s, &slap_daemon.sd_actives );
141         FD_CLR( s, &slap_daemon.sd_readers );
142         FD_CLR( s, &slap_daemon.sd_writers );
143
144         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
145         WAKE_LISTENER(wake);
146 }
147
148 void slapd_clr_write(ber_socket_t s, int wake) {
149         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
150
151         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
152         FD_CLR( s, &slap_daemon.sd_writers );
153
154         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
155         WAKE_LISTENER(wake);
156 }
157
158 void slapd_set_write(ber_socket_t s, int wake) {
159         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
160
161         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
162         if (!FD_ISSET(s, &slap_daemon.sd_writers))
163             FD_SET( (unsigned) s, &slap_daemon.sd_writers );
164
165         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
166         WAKE_LISTENER(wake);
167 }
168
169 void slapd_clr_read(ber_socket_t s, int wake) {
170         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
171
172         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
173         FD_CLR( s, &slap_daemon.sd_readers );
174
175         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
176         WAKE_LISTENER(wake);
177 }
178
179 void slapd_set_read(ber_socket_t s, int wake) {
180         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
181
182         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
183         if (!FD_ISSET(s, &slap_daemon.sd_readers))
184             FD_SET( s, &slap_daemon.sd_readers );
185
186         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
187         WAKE_LISTENER(wake);
188 }
189
190 static void slapd_close(ber_socket_t s) {
191         Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
192                 (long) s, 0, 0 );
193         tcp_close(s);
194 }
195
196
197 static Listener * open_listener( const char* url )
198 {
199         int     tmp, rc;
200         Listener l;
201         Listener *li;
202         LDAPURLDesc *lud;
203         char *s;
204         int port;
205 #ifdef HAVE_GETADDRINFO
206         char serv[7];
207         struct addrinfo hints, *res, *sai;
208         int err;
209 #endif
210
211         rc = ldap_url_parse( url, &lud );
212
213         if( rc != LDAP_URL_SUCCESS ) {
214                 Debug( LDAP_DEBUG_ANY,
215                         "daemon: listen URL \"%s\" parse error=%d\n",
216                         url, rc, 0 );
217                 return NULL;
218         }
219
220 #ifndef HAVE_TLS
221         if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
222                 Debug( LDAP_DEBUG_ANY,
223                         "daemon: TLS not supported (%s)\n",
224                         url, 0, 0 );
225                 ldap_free_urldesc( lud );
226                 return NULL;
227         }
228
229         if(! lud->lud_port ) {
230                 lud->lud_port = LDAP_PORT;
231         }
232
233 #else
234         l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );
235
236         if(! lud->lud_port ) {
237                 lud->lud_port = l.sl_is_tls ? LDAPS_PORT : LDAP_PORT;
238         }
239 #endif
240
241 #ifdef HAVE_GETADDRINFO
242         memset( &hints, '\0', sizeof(hints) );
243         hints.ai_flags = AI_PASSIVE;
244         hints.ai_family = AF_UNSPEC;
245         hints.ai_socktype = SOCK_STREAM;
246
247 #  ifdef LDAP_PF_LOCAL
248         if (lud->lud_protocol == LDAP_PROTO_LOCAL) {
249                 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
250                         err = getaddrinfo(NULL, "/tmp/.ldap-sock", &hints, &res);
251                         if (!err)
252                                 unlink( "/tmp/.ldap-sock" );
253                 } else {
254                         err = getaddrinfo(NULL, lud->lud_host, &hints, &res);
255                         if (!err)
256                                 unlink( lud->lud_host );
257                 }
258         } else
259 #  endif /* LDAP_PF_LOCAL */
260         {
261                 snprintf(serv, sizeof serv, "%d", lud->lud_port);
262                 if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
263                         || strcmp(lud->lud_host, "*") == 0 )
264                 {
265                         err = getaddrinfo(NULL, serv, &hints, &res);
266                 } else {
267                         err = getaddrinfo(lud->lud_host, serv, &hints, &res);
268                 }
269         }
270
271         if ( err ) {
272                 Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed\n", 0, 0, 0);
273                 ldap_free_urldesc( lud );
274                 return NULL;
275         }
276
277         ldap_free_urldesc( lud );
278         sai = res;
279         do {
280                 l.sl_sd = socket( sai->ai_family, sai->ai_socktype, sai->ai_protocol);
281                 if ( l.sl_sd == AC_SOCKET_INVALID ) {
282                         Debug( LDAP_DEBUG_ANY,
283                                 "daemon: socket() failed errno=%d (%s)\n", err,
284                                 sock_errstr(err), 0 );
285                         continue;
286                 }
287
288                 if ( sai->ai_family != AF_UNIX ) {
289 #else
290 #ifdef LDAP_PF_LOCAL
291         if (lud->lud_protocol == LDAP_PROTO_LOCAL) {
292                 port = 0;
293                 (void) memset( (void *)&l.sl_sa.sa_un_addr, '\0', sizeof(l.sl_sa.sa_un_addr) );
294
295                 l.sl_sa.sa_un_addr.sun_family = AF_UNIX;
296
297                 /* hack: overload the host to be the path */
298                 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
299                         strcpy( l.sl_sa.sa_un_addr.sun_path, "/tmp/.ldap-sock" );
300                 } else {
301                         if ( strlen(lud->lud_host) > (sizeof(l.sl_sa.sa_un_addr.sun_path) - 1) ) {
302                                 Debug( LDAP_DEBUG_ANY,
303                                         "daemon: domain socket path (%s) too long in URL: %s",
304                                         lud->lud_host, url, 0);
305                                 ldap_free_urldesc( lud );
306                                 return NULL;
307                         }
308                         strcpy( l.sl_sa.sa_un_addr.sun_path, lud->lud_host );
309                 }
310                 unlink( l.sl_sa.sa_un_addr.sun_path ); 
311 #if 0
312                 /* I don't think we need to set this. */
313                 l.sl_sa.sa_un_addr.sun_len = sizeof( l.sl_sa.sa_un_addr.sun_len ) +
314                         sizeof( l.sl_sa.sa_un_addr.sun_family ) +
315                         strlen( l.sl_sa.sa_un_addr.sun_path ) + 1;
316 #endif
317         } else
318 #endif /* LDAP_PF_LOCAL */
319         {
320
321         port = lud->lud_port;
322
323         (void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
324
325         l.sl_addr.sin_family = AF_INET;
326         l.sl_addr.sin_port = htons( (unsigned short) lud->lud_port );
327
328         if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
329                 || strcmp(lud->lud_host, "*") == 0 )
330         {
331                 l.sl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
332
333         } else {
334                 /* host or address was specified */
335                 if( !inet_aton( lud->lud_host, &l.sl_addr.sin_addr ) ) {
336                         struct hostent *he = gethostbyname( lud->lud_host );
337                         if( he == NULL ) {
338                                 Debug( LDAP_DEBUG_ANY,
339                                         "daemon: invalid host (%s) in URL: %s",
340                                         lud->lud_host, url, 0);
341                                 ldap_free_urldesc( lud );
342                                 return NULL;
343                         }
344
345                         memcpy( &l.sl_addr.sin_addr, he->h_addr,
346                                sizeof( l.sl_addr.sin_addr ) );
347                 }
348         }
349         }
350
351         ldap_free_urldesc( lud );
352
353         l.sl_sd = socket( l.sl_sa.sa_addr.sa_family, SOCK_STREAM, 0 );
354         if ( l.sl_sd == AC_SOCKET_INVALID ) {
355                 int err = sock_errno();
356                 Debug( LDAP_DEBUG_ANY,
357                         "daemon: socket() failed errno=%d (%s)\n", err,
358                         sock_errstr(err), 0 );
359                 return NULL;
360         }
361
362 #ifndef HAVE_WINSOCK
363         if ( l.sl_sd >= dtblsize ) {
364                 Debug( LDAP_DEBUG_ANY,
365                         "daemon: listener descriptor %ld is too great %ld\n",
366                         (long) l.sl_sd, (long) dtblsize, 0 );
367                 tcp_close( l.sl_sd );
368                 return NULL;
369         }
370 #endif
371
372 #ifdef LDAP_PF_LOCAL
373         /* for IP sockets only */
374         if ( l.sl_sa.sa_addr.sa_family == AF_INET ) {
375 #endif /* LDAP_PF_LOCAL */
376 #endif /* HAVE_GETADDRINFO */
377
378 #ifdef SO_REUSEADDR
379         /* enable address reuse */
380         tmp = 1;
381         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
382                 (char *) &tmp, sizeof(tmp) );
383         if ( rc == AC_SOCKET_ERROR ) {
384                 int err = sock_errno();
385                 Debug( LDAP_DEBUG_ANY,
386                "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
387                 (long) l.sl_sd, err, sock_errstr(err) );
388         }
389 #endif
390 #ifdef SO_KEEPALIVE
391         /* enable keep alives */
392         tmp = 1;
393         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_KEEPALIVE,
394                 (char *) &tmp, sizeof(tmp) );
395         if ( rc == AC_SOCKET_ERROR ) {
396                 int err = sock_errno();
397                 Debug( LDAP_DEBUG_ANY,
398                         "slapd(%ld): setsockopt(SO_KEEPALIVE) failed errno=%d (%s)\n",
399                 (long) l.sl_sd, err, sock_errstr(err) );
400         }
401 #endif
402 #ifdef TCP_NODELAY
403         /* enable no delay */
404         tmp = 1;
405         rc = setsockopt( l.sl_sd, IPPROTO_TCP, TCP_NODELAY,
406                 (char *)&tmp, sizeof(tmp) );
407         if ( rc == AC_SOCKET_ERROR ) {
408                 int err = sock_errno();
409                 Debug( LDAP_DEBUG_ANY,
410                         "slapd(%ld): setsockopt(TCP_NODELAY) failed errno=%d (%s)\n",
411                 (long) l.sl_sd, err, sock_errstr(err) );
412         }
413 #endif
414
415 #ifdef HAVE_GETADDRINFO
416                 } /* sai->ai_family != AF_UNIX */
417                 if (!bind(l.sl_sd, sai->ai_addr, sai->ai_addrlen))
418                         break;
419                 err = sock_errno();
420                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
421                         (long) l.sl_sd, err, sock_errstr(err) );
422                 tcp_close( l.sl_sd );
423         } while ((sai = sai->ai_next) != NULL);
424
425         if (!sai) {
426                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed\n",
427                         (long) l.sl_sd, 0, 0 );
428                 return NULL;
429         }
430
431         switch ( sai->ai_family ) {
432 #  ifdef LDAP_PF_LOCAL
433         case AF_UNIX:
434                 if ( chmod( (char *)sai->ai_addr, S_IRWXU ) < 0 ) {
435                         err = sock_errno();
436                         Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
437                                 (long) l.sl_sd, err, sock_errstr(err) );
438                         tcp_close( l.sl_sd );
439                         return NULL;
440                 }
441                 l.sl_name = ch_malloc( strlen((char *)sai->ai_addr) + sizeof("PATH=") );
442                 sprintf( l.sl_name, "PATH=%s", sai->ai_addr );
443                 break;
444 #  endif /* LDAP_PF_LOCAL */
445
446         case AF_INET: {
447                 char addr[INET_ADDRSTRLEN];
448                 inet_ntop( AF_INET,
449                         &((struct sockaddr_in *)sai->ai_addr)->sin_addr,
450                         addr, sizeof(addr) );
451                 l.sl_name = ch_malloc( strlen(addr) + strlen(serv) + sizeof("IP=:") );
452                 sprintf( l.sl_name, "IP=%s:%s", addr, serv );
453         } break;
454
455 #  ifdef LDAP_INET6
456         case AF_INET6: {
457                 char addr[INET6_ADDRSTRLEN];
458                 inet_ntop( AF_INET6,
459                         &((struct sockaddr_in6 *)sai->ai_addr)->sin6_addr,
460                         addr, sizeof addr);
461                 l.sl_name = ch_malloc( strlen(addr) + strlen(serv) + sizeof("IP= ") );
462                 sprintf( l.sl_name, "IP=%s %s", addr, serv );
463         } break;
464 #  endif /* LDAP_INET6 */
465
466         default:
467                 Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
468                         (int) sai->ai_family, 0, 0 );
469                 break;
470         }
471 #else
472 #ifdef LDAP_PF_LOCAL
473         /* close conditional */
474         }
475 #endif /* LDAP_PF_LOCAL */
476
477         switch ( l.sl_sa.sa_addr.sa_family ) {
478 #ifdef LDAP_PF_LOCAL
479                 case AF_UNIX:
480                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
481                                 sizeof(l.sl_sa.sa_un_addr) );
482                         break;
483 #endif
484
485                 case AF_INET:
486                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
487                                 sizeof(l.sl_sa.sa_in_addr) );
488                         break;
489
490                 default:
491                         rc = AC_SOCKET_ERROR;
492                         errno = EINVAL;
493                         break;
494         }
495
496         if ( rc == AC_SOCKET_ERROR ) {
497                 int err = sock_errno();
498                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
499                 (long) l.sl_sd, err, sock_errstr(err) );
500                 tcp_close( l.sl_sd );
501                 return NULL;
502         }
503
504         switch ( l.sl_sa.sa_addr.sa_family ) {
505 #ifdef LDAP_PF_LOCAL
506                 case AF_UNIX:
507                         if ( chmod( l.sl_sa.sa_un_addr.sun_path, S_IRWXU ) < 0 ) {
508                                 int err = sock_errno();
509                                 Debug( LDAP_DEBUG_ANY,
510                                         "daemon: chmod(%ld) failed errno=%d (%s)",
511                                         (long) l.sl_sd, err, sock_errstr(err) );
512                                 tcp_close( l.sl_sd );
513                                 return NULL;
514                         }
515
516                         l.sl_name = ch_malloc( strlen(l.sl_sa.sa_un_addr.sun_path)
517                                 + sizeof("PATH=") );
518                         sprintf( l.sl_name, "PATH=%s", l.sl_sa.sa_un_addr.sun_path );
519                         break;
520 #  endif /* LDAP_PF_LOCAL */
521
522                 case AF_INET:
523                         l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
524                         s = inet_ntoa( l.sl_addr.sin_addr );
525                         sprintf( l.sl_name, "IP=%s:%d",
526                                 s != NULL ? s : "unknown" , port );
527                         break;
528
529                 default:
530                         l.sl_name = ch_strdup( "UNKNOWN" );
531                         break;
532         }
533
534 #endif /* HAVE_GETADDRINFO */
535
536         l.sl_url = ch_strdup( url );
537         li = ch_malloc( sizeof( Listener ) );
538         *li = l;
539
540         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
541                 l.sl_url, 0, 0 );
542
543         return li;
544 }
545
546 static int sockinit(void);
547 static int sockdestroy(void);
548
549 int slapd_daemon_init( const char *urls )
550 {
551         int i, rc;
552         char **u;
553
554         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
555                 urls ? urls : "<null>", 0, 0 );
556
557         if( (rc = sockinit()) != 0 ) {
558                 return rc;
559         }
560
561 #ifdef HAVE_SYSCONF
562         dtblsize = sysconf( _SC_OPEN_MAX );
563 #elif HAVE_GETDTABLESIZE
564         dtblsize = getdtablesize();
565 #else
566         dtblsize = FD_SETSIZE;
567 #endif
568
569 #ifdef FD_SETSIZE
570         if(dtblsize > FD_SETSIZE) {
571                 dtblsize = FD_SETSIZE;
572         }
573 #endif  /* !FD_SETSIZE */
574
575         /* open a pipe (or something equivalent connected to itself).
576          * we write a byte on this fd whenever we catch a signal. The main
577          * loop will be select'ing on this socket, and will wake up when
578          * this byte arrives.
579          */
580         if( (rc = lutil_pair( wake_sds )) < 0 ) {
581                 Debug( LDAP_DEBUG_ANY,
582                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
583                 return rc;
584         }
585
586         FD_ZERO( &slap_daemon.sd_readers );
587         FD_ZERO( &slap_daemon.sd_writers );
588
589         if( urls == NULL ) {
590                 urls = "ldap:///";
591         }
592
593         u = str2charray( urls, " " );
594
595         if( u == NULL || u[0] == NULL ) {
596                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
597                         urls, 0, 0 );
598
599                 return -1;
600         }
601
602         for( i=0; u[i] != NULL; i++ ) {
603                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
604                         u[i], 0, 0 );
605         }
606
607         if( i == 0 ) {
608                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
609                         urls, 0, 0 );
610                 charray_free( u );
611                 return -1;
612         }
613
614         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
615                 i, 0, 0 );
616
617         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
618
619         for(i = 0; u[i] != NULL; i++ ) {
620                 slap_listeners[i] = open_listener( u[i] );
621
622                 if( slap_listeners[i] == NULL ) {
623                         charray_free( u );
624                         return -1;
625                 }
626         }
627         slap_listeners[i] = NULL;
628
629         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
630                 i, 0, 0 );
631
632         charray_free( u );
633         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
634         return !i;
635 }
636
637
638 int
639 slapd_daemon_destroy(void)
640 {
641         connections_destroy();
642         tcp_close( wake_sds[1] );
643         tcp_close( wake_sds[0] );
644         sockdestroy();
645         return 0;
646 }
647
648
649 static void *
650 slapd_daemon_task(
651         void *ptr
652 )
653 {
654         int l;
655         time_t  last_idle_check = slap_get_time();
656         time( &starttime );
657
658         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
659                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
660                         continue;
661
662                 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
663                         int err = sock_errno();
664                         Debug( LDAP_DEBUG_ANY,
665                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
666                                         slap_listeners[l]->sl_url, err,
667                                         sock_errstr(err) );
668                         return( (void*)-1 );
669                 }
670
671                 slapd_add( slap_listeners[l]->sl_sd );
672         }
673
674 #ifdef HAVE_NT_SERVICE_MANAGER
675         if ( started_event != NULL ) {
676                 ldap_pvt_thread_cond_signal( &started_event );
677         }
678 #endif
679         /* initialization complete. Here comes the loop. */
680
681         while ( !slapd_shutdown ) {
682                 ber_socket_t i;
683                 int ns;
684                 int at;
685                 ber_socket_t nfds;
686 #define SLAPD_EBADF_LIMIT 10
687                 int ebadf = 0;
688
689 #define SLAPD_IDLE_CHECK_LIMIT 4
690                 time_t  now = slap_get_time();
691
692
693                 fd_set                  readfds;
694                 fd_set                  writefds;
695                 Sockaddr                from;
696
697 #if defined(SLAPD_RLOOKUPS)
698         struct hostent          *hp;
699 #endif
700                 struct timeval          zero;
701                 struct timeval          *tvp;
702
703                 if( global_idletimeout > 0 && difftime(
704                         last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
705                         now ) < 0 )
706                 {
707                         connections_timeout_idle(now);
708                 }
709
710                 FD_ZERO( &writefds );
711                 FD_ZERO( &readfds );
712
713                 zero.tv_sec = 0;
714                 zero.tv_usec = 0;
715
716                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
717
718 #ifdef FD_SET_MANUAL_COPY
719                 for( s = 0; s < nfds; s++ ) {
720                         if(FD_ISSET( &slap_sd_readers, s )) {
721                                 FD_SET( s, &readfds );
722                         }
723                         if(FD_ISSET( &slap_sd_writers, s )) {
724                                 FD_SET( s, &writefds );
725                         }
726                 }
727 #else
728                 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
729                 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
730 #endif
731                 assert(!FD_ISSET(wake_sds[0], &readfds));
732                 FD_SET( wake_sds[0], &readfds );
733
734                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
735                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
736                                 continue;
737                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
738                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
739                 }
740
741 #ifndef HAVE_WINSOCK
742                 nfds = slap_daemon.sd_nfds;
743 #else
744                 nfds = dtblsize;
745 #endif
746
747                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
748
749                 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
750                 at = active_threads;
751                 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
752
753 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
754                 tvp = NULL;
755 #else
756                 tvp = at ? &zero : NULL;
757 #endif
758
759                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
760                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
761                                 continue;
762
763                         Debug( LDAP_DEBUG_CONNS,
764                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
765                                         slap_listeners[l]->sl_sd, at,
766                                         tvp == NULL ? "NULL" : "zero" );
767                 }
768
769                 switch(ns = select( nfds, &readfds,
770 #ifdef HAVE_WINSOCK
771                         /* don't pass empty fd_set */
772                         ( writefds.fd_count > 0 ? &writefds : NULL ),
773 #else
774                         &writefds,
775 #endif
776                         NULL, tvp ))
777                 {
778                 case -1: {      /* failure - try again */
779                                 int err = sock_errno();
780
781                                 if( err == EBADF 
782 #ifdef HAVE_WINSOCK
783                                         || err == WSAENOTSOCK   /* you'd think this would be EBADF */
784 #endif
785                                 ) {
786                                         if (++ebadf < SLAPD_EBADF_LIMIT)
787                                                 continue;
788                                 }
789
790                                 if( err != EINTR ) {
791                                         Debug( LDAP_DEBUG_CONNS,
792                                                 "daemon: select failed (%d): %s\n",
793                                                 err, sock_errstr(err), 0 );
794
795                                         slapd_shutdown = -1;
796                                 }
797                         }
798                         continue;
799
800                 case 0:         /* timeout - let threads run */
801                         ebadf = 0;
802                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
803                             0, 0, 0 );
804                 ldap_pvt_thread_yield();
805                         continue;
806
807                 default:        /* something happened - deal with it */
808                         ebadf = 0;
809                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
810                                 ns, 0, 0 );
811                         /* FALL THRU */
812                 }
813
814                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
815                         char c[BUFSIZ];
816                         tcp_read( wake_sds[0], c, sizeof(c) );
817 #ifdef NO_THREADS
818                         waking = 0;
819 #endif
820                         continue;
821                 }
822
823                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
824                         ber_int_t s;
825                         socklen_t len = sizeof(from);
826                         long id;
827
828                         char    *dnsname;
829                         char    *peeraddr;
830 #ifdef LDAP_PF_LOCAL
831                         char    peername[MAXPATHLEN + sizeof("PATH=")];
832 #elif defined(LDAP_INET6)
833                         char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
834 #else
835                         char    peername[sizeof("IP=255.255.255.255:65336")];
836 #endif /* LDAP_PF_LOCAL */
837
838                         peername[0] = '\0';
839
840                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
841                                 continue;
842
843                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
844                                 continue;
845
846                         if ( (s = accept( slap_listeners[l]->sl_sd,
847                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
848                         {
849                                 int err = sock_errno();
850                                 Debug( LDAP_DEBUG_ANY,
851                                     "daemon: accept(%ld) failed errno=%d (%s)\n",
852                                     (long) slap_listeners[l]->sl_sd, err,
853                                     sock_errstr(err) );
854                                 continue;
855                         }
856
857 #ifdef LDAP_DEBUG
858                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
859
860                         /* newly accepted stream should not be in any of the FD SETS */
861
862                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
863                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
864                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
865
866                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
867 #endif
868
869 #ifndef HAVE_WINSOCK
870                         /* make sure descriptor number isn't too great */
871                         if ( s >= dtblsize ) {
872                                 Debug( LDAP_DEBUG_ANY,
873                                         "daemon: %ld beyond descriptor table size %ld\n",
874                                         (long) s, (long) dtblsize, 0 );
875                                 slapd_close(s);
876                                 continue;
877                         }
878 #endif
879                    
880                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
881                                 (long) s, 0, 0 );
882
883                         len = sizeof(from);
884
885                         if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
886                                 int err = sock_errno();
887                                 Debug( LDAP_DEBUG_ANY,
888                                         "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
889                                         (long) s, err, sock_errstr(err) );
890                                 slapd_close(s);
891                                 continue;
892                         }
893
894                         switch ( from.sa_addr.sa_family ) {
895 #  ifdef LDAP_PF_LOCAL
896                         case AF_UNIX:
897                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
898                                 break;
899 #endif /* LDAP_PF_LOCAL */
900
901 #  ifdef LDAP_INET6
902                         case AF_INET6: {
903                                 char addr[INET6_ADDRSTRLEN];
904                                 sprintf( peername, "IP=%s %d",
905                                         inet_ntop( AF_INET6,
906                                                 &from.sa_in6_addr.sin6_addr,
907                                             addr, sizeof addr) ? addr : "unknown",
908                                         (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
909                         } break;
910 #  endif /* LDAP_INET6 */
911
912                         case AF_INET:
913                         peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
914                         sprintf( peername, "IP=%s:%d",
915                                 peeraddr != NULL ? peeraddr : "unknown",
916                                 (unsigned) ntohs( from.sa_in_addr.sin_port ) );
917                                 break;
918
919                         default:
920                                 slapd_close(s);
921                                 continue;
922                         }
923                         if ( ( from.sa_addr.sa_family == AF_INET ) 
924 #ifdef LDAP_INET6
925                                 || ( from.sa_addr.sa_family == AF_INET6 )
926 #endif
927                         ) {
928 #ifdef SLAPD_RLOOKUPS
929 #  ifdef LDAP_INET6
930                                 if ( from.sa_addr.sa_family == AF_INET6 )
931                                         hp = gethostbyaddr(
932                                                 (char *)&(from.sa_in6_addr.sin6_addr),
933                                                 sizeof(from.sa_in6_addr.sin6_addr),
934                                                 AF_INET6 );
935                                 else
936 #  endif LDAP_INET6
937                                 hp = gethostbyaddr(
938                                         (char *) &(from.sa_in_addr.sin_addr),
939                                         sizeof(from.sa_in_addr.sin_addr),
940                                         AF_INET );
941                                 dnsname = hp ? ldap_pvt_str2lower( hp->h_name ) : NULL;
942 #else
943                                 dnsname = NULL;
944 #endif /* SLAPD_RLOOKUPS */
945
946 #ifdef HAVE_TCPD
947                                 if ( !hosts_ctl("slapd",
948                                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
949                                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
950                                                 STRING_UNKNOWN ))
951                                 {
952                                         /* DENY ACCESS */
953                                         Statslog( LDAP_DEBUG_ANY,
954                                                 "fd=%ld connection from %s (%s) denied.\n",
955                                                 (long) s,
956                                                 dnsname != NULL ? dnsname : "unknown",
957                                                 peeraddr != NULL ? peeraddr : "unknown",
958                                                 0, 0 );
959                                         slapd_close(s);
960                                         continue;
961                                 }
962 #endif /* HAVE_TCPD */
963                         }
964
965                         if( (id = connection_init(s,
966                                 slap_listeners[l]->sl_url,
967                                 dnsname != NULL ? dnsname : "unknown",
968                                 peername,
969                                 slap_listeners[l]->sl_name,
970 #ifdef HAVE_TLS
971                                 slap_listeners[l]->sl_is_tls
972 #else
973                                 0
974 #endif
975                                 )) < 0 )
976                         {
977                                 Debug( LDAP_DEBUG_ANY,
978                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
979                                         (long) s,
980                                         peername,
981                                         slap_listeners[l]->sl_name );
982                                 slapd_close(s);
983                                 continue;
984                         }
985
986                         Statslog( LDAP_DEBUG_STATS,
987                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
988                                 id, (long) s,
989                                 peername,
990                                 slap_listeners[l]->sl_name,
991                                 0 );
992
993                         slapd_add( s );
994                         continue;
995                 }
996
997 #ifdef LDAP_DEBUG
998                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
999 #ifdef HAVE_WINSOCK
1000                 for ( i = 0; i < readfds.fd_count; i++ ) {
1001                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1002                                 readfds.fd_array[i], "r", 0 );
1003                 }
1004                 for ( i = 0; i < writefds.fd_count; i++ ) {
1005                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1006                                 writefds.fd_array[i], "w", 0 );
1007                 }
1008 #else
1009                 for ( i = 0; i < nfds; i++ ) {
1010                         int     r, w;
1011                         int     is_listener = 0;
1012
1013                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1014                                 if ( i == slap_listeners[l]->sl_sd ) {
1015                                         is_listener = 1;
1016                                         break;
1017                                 }
1018                         }
1019                         if ( is_listener ) {
1020                                 continue;
1021                         }
1022                         r = FD_ISSET( i, &readfds );
1023                         w = FD_ISSET( i, &writefds );
1024                         if ( r || w ) {
1025                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
1026                                     r ? "r" : "", w ? "w" : "" );
1027                         }
1028                 }
1029 #endif
1030                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
1031 #endif
1032
1033                 /* loop through the writers */
1034 #ifdef HAVE_WINSOCK
1035                 for ( i = 0; i < writefds.fd_count; i++ )
1036 #else
1037                 for ( i = 0; i < nfds; i++ )
1038 #endif
1039                 {
1040                         ber_socket_t wd;
1041                         int is_listener = 0;
1042 #ifdef HAVE_WINSOCK
1043                         wd = writefds.fd_array[i];
1044 #else
1045                         if( ! FD_ISSET( i, &writefds ) ) {
1046                                 continue;
1047                         }
1048                         wd = i;
1049 #endif
1050
1051                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1052                                 if ( i == slap_listeners[l]->sl_sd ) {
1053                                         is_listener = 1;
1054                                         break;
1055                                 }
1056                         }
1057                         if ( is_listener ) {
1058                                 continue;
1059                         }
1060                         Debug( LDAP_DEBUG_CONNS,
1061                                 "daemon: write active on %d\n",
1062                                 wd, 0, 0 );
1063
1064                         /*
1065                          * NOTE: it is possible that the connection was closed
1066                          * and that the stream is now inactive.
1067                          * connection_write() must valid the stream is still
1068                          * active.
1069                          */
1070
1071                         if ( connection_write( wd ) < 0 ) {
1072                                 FD_CLR( (unsigned) wd, &readfds );
1073                                 slapd_close( wd );
1074                         }
1075                 }
1076
1077 #ifdef HAVE_WINSOCK
1078                 for ( i = 0; i < readfds.fd_count; i++ )
1079 #else
1080                 for ( i = 0; i < nfds; i++ )
1081 #endif
1082                 {
1083                         ber_socket_t rd;
1084                         int is_listener = 0;
1085
1086 #ifdef HAVE_WINSOCK
1087                         rd = readfds.fd_array[i];
1088 #else
1089                         if( ! FD_ISSET( i, &readfds ) ) {
1090                                 continue;
1091                         }
1092                         rd = i;
1093 #endif
1094
1095                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1096                                 if ( rd == slap_listeners[l]->sl_sd ) {
1097                                         is_listener = 1;
1098                                         break;
1099                                 }
1100                         }
1101                         if ( is_listener ) {
1102                                 continue;
1103                         }
1104
1105                         Debug ( LDAP_DEBUG_CONNS,
1106                                 "daemon: read activity on %d\n", rd, 0, 0 );
1107
1108                         /*
1109                          * NOTE: it is possible that the connection was closed
1110                          * and that the stream is now inactive.
1111                          * connection_read() must valid the stream is still
1112                          * active.
1113                          */
1114
1115                         if ( connection_read( rd ) < 0 ) {
1116                                 slapd_close( rd );
1117                         }
1118                 }
1119                 ldap_pvt_thread_yield();
1120         }
1121
1122         if( slapd_shutdown > 0 ) {
1123                 Debug( LDAP_DEBUG_TRACE,
1124                         "daemon: shutdown requested and initiated.\n",
1125                         0, 0, 0 );
1126
1127         } else if ( slapd_shutdown < 0 ) {
1128 #ifdef HAVE_NT_SERVICE_MANAGER
1129                 if (slapd_shutdown == -1)
1130                     Debug( LDAP_DEBUG_TRACE,
1131                           "daemon: shutdown initiated by Service Manager.\n",
1132                           0, 0, 0);
1133                 else
1134 #endif
1135                 Debug( LDAP_DEBUG_TRACE,
1136                         "daemon: abnormal condition, shutdown initiated.\n",
1137                         0, 0, 0 );
1138         } else {
1139                 Debug( LDAP_DEBUG_TRACE,
1140                         "daemon: no active streams, shutdown initiated.\n",
1141                         0, 0, 0 );
1142         }
1143
1144         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1145                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1146 #ifdef LDAP_PF_LOCAL
1147                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_UNIX ) {
1148                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1149                         }
1150 #endif /* LDAP_PF_LOCAL */
1151                         slapd_close( slap_listeners[l]->sl_sd );
1152                         break;
1153                 }
1154         }
1155
1156         ldap_pvt_thread_pool_destroy(connection_pool, 1);
1157
1158         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
1159         Debug( LDAP_DEBUG_ANY,
1160             "slapd shutdown: waiting for %d threads to terminate\n",
1161             active_threads, 0, 0 );
1162         while ( active_threads > 0 ) {
1163                 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
1164         }
1165         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
1166
1167         return NULL;
1168 }
1169
1170
1171 int slapd_daemon( void )
1172 {
1173         int rc;
1174
1175         connections_init();
1176
1177 #define SLAPD_LISTENER_THREAD 1
1178 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
1179
1180         /* listener as a separate THREAD */
1181         rc = ldap_pvt_thread_create( &listener_tid,
1182                 0, slapd_daemon_task, NULL );
1183
1184         if ( rc != 0 ) {
1185                 Debug( LDAP_DEBUG_ANY,
1186                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1187                 return rc;
1188         }
1189
1190         /* wait for the listener thread to complete */
1191         ldap_pvt_thread_join( listener_tid, (void *) NULL );
1192 #else
1193         /* expermimental code */
1194         listener_tid = pthread_self();
1195         slapd_daemon_task( NULL );
1196 #endif
1197
1198         return 0;
1199
1200 }
1201
1202 #ifdef HAVE_WINSOCK2
1203 int sockinit(void)
1204 {
1205     WORD wVersionRequested;
1206         WSADATA wsaData;
1207         int err;
1208  
1209         wVersionRequested = MAKEWORD( 2, 0 );
1210  
1211         err = WSAStartup( wVersionRequested, &wsaData );
1212         if ( err != 0 ) {
1213                 /* Tell the user that we couldn't find a usable */
1214                 /* WinSock DLL.                                  */
1215                 return -1;
1216         }
1217  
1218         /* Confirm that the WinSock DLL supports 2.0.*/
1219         /* Note that if the DLL supports versions greater    */
1220         /* than 2.0 in addition to 2.0, it will still return */
1221         /* 2.0 in wVersion since that is the version we      */
1222         /* requested.                                        */
1223  
1224         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1225                 HIBYTE( wsaData.wVersion ) != 0 )
1226         {
1227             /* Tell the user that we couldn't find a usable */
1228             /* WinSock DLL.                                  */
1229             WSACleanup();
1230             return -1; 
1231         }
1232
1233         /* The WinSock DLL is acceptable. Proceed. */
1234         return 0;
1235 }
1236
1237 int sockdestroy(void)
1238 {
1239         WSACleanup();
1240         return 0;
1241 }
1242
1243 #elif HAVE_WINSOCK
1244 static int sockinit(void)
1245 {
1246         WSADATA wsaData;
1247         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1248             return -1;
1249         }
1250         return 0;
1251 }
1252 static int sockdestroy(void)
1253 {
1254         WSACleanup();
1255         return 0;
1256 }
1257
1258 #else
1259 static int sockinit(void)
1260 {
1261         return 0;
1262 }
1263 static int sockdestroy(void)
1264 {
1265         return 0;
1266 }
1267 #endif
1268
1269 RETSIGTYPE
1270 slap_sig_shutdown( int sig )
1271 {
1272         Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
1273
1274         /*
1275          * If the NT Service Manager is controlling the server, we don't
1276          * want SIGBREAK to kill the server. For some strange reason,
1277          * SIGBREAK is generated when a user logs out.
1278          */
1279
1280 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
1281         if (is_NT_Service && sig == SIGBREAK)
1282             Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
1283                   0, 0, 0);
1284         else
1285 #endif
1286         slapd_shutdown = sig;
1287
1288         WAKE_LISTENER(1);
1289
1290         /* reinstall self */
1291         (void) SIGNAL( sig, slap_sig_shutdown );
1292 }
1293
1294 RETSIGTYPE
1295 slap_sig_wake( int sig )
1296 {
1297         WAKE_LISTENER(1);
1298
1299         /* reinstall self */
1300         (void) SIGNAL( sig, slap_sig_wake );
1301 }