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