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