]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
9a55fc277b638713b1f19a7cc37c2c6f57cd37e2
[openldap] / servers / slapd / daemon.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/ctype.h>
12 #include <ac/errno.h>
13 #include <ac/signal.h>
14 #include <ac/socket.h>
15 #include <ac/string.h>
16 #include <ac/time.h>
17 #include <ac/unistd.h>
18
19 #include "ldap_pvt.h"
20 #include "lutil.h"
21 #include "slap.h"
22
23 #ifdef HAVE_TCPD
24 #include <tcpd.h>
25
26 int allow_severity = LOG_INFO;
27 int deny_severity = LOG_NOTICE;
28 #endif /* TCP Wrappers */
29
30 #ifdef LDAP_PF_LOCAL
31 #include <sys/stat.h>
32 #endif /* LDAP_PF_LOCAL */
33
34 /* globals */
35 time_t starttime;
36 ber_socket_t dtblsize;
37
38 #ifdef LDAP_PF_LOCAL
39 typedef union slap_sockaddr {
40         struct sockaddr sa_addr;
41         struct sockaddr_in sa_in_addr;
42         struct sockaddr_un sa_un_addr;
43 } Sockaddr;
44 #endif /* LDAP_PF_LOCAL */
45
46 typedef struct slap_listener {
47         char* sl_url;
48         char* sl_name;
49 #ifdef HAVE_TLS
50         int             sl_is_tls;
51 #endif
52         ber_socket_t            sl_sd;
53 #ifdef LDAP_PF_LOCAL
54         Sockaddr sl_sa;
55 #define sl_addr sl_sa.sa_in_addr
56 #else   
57         struct sockaddr_in      sl_addr;
58 #endif /* LDAP_PF_LOCAL */
59 } Listener;
60
61 Listener **slap_listeners = NULL;
62
63 static ber_socket_t wake_sds[2];
64
65 #ifdef NO_THREADS
66 static int waking;
67 #define WAKE_LISTENER(w) \
68 ((w && !waking) ? tcp_write( wake_sds[1], "0", 1 ), waking=1 : 0)
69 #else
70 #define WAKE_LISTENER(w) \
71 do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
72 #endif
73
74 #ifdef HAVE_NT_SERVICE_MANAGER
75 /* in nt_main.c */
76 extern ldap_pvt_thread_cond_t                   started_event;
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
206         rc = ldap_url_parse( url, &lud );
207
208         if( rc != LDAP_URL_SUCCESS ) {
209                 Debug( LDAP_DEBUG_ANY,
210                         "daemon: listen URL \"%s\" parse error=%d\n",
211                         url, rc, 0 );
212                 return NULL;
213         }
214
215 #ifndef HAVE_TLS
216         if( lud->lud_properties & LDAP_URL_USE_SSL ) {
217                 Debug( LDAP_DEBUG_ANY,
218                         "daemon: TLS not supported (%s)\n",
219                         url, 0, 0 );
220                 ldap_free_urldesc( lud );
221                 return NULL;
222         }
223
224         if(! lud->lud_port ) {
225                 lud->lud_port = LDAP_PORT;
226         }
227
228 #else
229         l.sl_is_tls = (lud->lud_properties & LDAP_URL_USE_SSL);
230
231         if(! lud->lud_port ) {
232                 lud->lud_port = (lud->lud_properties & LDAP_URL_USE_SSL) ? LDAPS_PORT : LDAP_PORT;
233         }
234 #endif
235
236 #ifdef LDAP_PF_LOCAL
237         if (lud->lud_protocol == LDAP_PROTO_LOCAL) {
238                 port = 0;
239                 (void) memset( (void *)&l.sl_sa.sa_un_addr, '\0', sizeof(l.sl_sa.sa_un_addr) );
240
241                 l.sl_sa.sa_un_addr.sun_family = AF_UNIX;
242
243                 /* hack: overload the host to be the path */
244                 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
245                         strcpy( l.sl_sa.sa_un_addr.sun_path, "/tmp/.ldap-sock" );
246                 } else {
247                         if ( strlen(lud->lud_host) > (sizeof(l.sl_sa.sa_un_addr.sun_path) - 1) ) {
248                                 Debug( LDAP_DEBUG_ANY, "domain socket path (%s) too long in URL: %s",
249                                         lud->lud_host, url, 0);
250                                 ldap_free_urldesc( lud );
251                                 return NULL;
252                         }
253                         strcpy( l.sl_sa.sa_un_addr.sun_path, lud->lud_host );
254                 }
255                 unlink( l.sl_sa.sa_un_addr.sun_path ); 
256 #if 0
257                 /* I don't think we need to set this. */
258                 l.sl_sa.sa_un_addr.sun_len = sizeof( l.sl_sa.sa_un_addr.sun_len ) +
259                         sizeof( l.sl_sa.sa_un_addr.sun_family ) +
260                         strlen( l.sl_sa.sa_un_addr.sun_path ) + 1;
261 #endif
262         } else {
263 #endif /* LDAP_PF_LOCAL */
264
265         port = lud->lud_port;
266
267         (void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
268
269         l.sl_addr.sin_family = AF_INET;
270         l.sl_addr.sin_port = htons( (unsigned short) lud->lud_port );
271
272         if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
273                 || strcmp(lud->lud_host, "*") == 0 )
274         {
275                 l.sl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
276
277         } else {
278                 /* host or address was specified */
279                 if( !inet_aton( lud->lud_host, &l.sl_addr.sin_addr ) ) {
280                         struct hostent *he = gethostbyname( lud->lud_host );
281                         if( he == NULL ) {
282                                 Debug( LDAP_DEBUG_ANY, "invalid host (%s) in URL: %s",
283                                         lud->lud_host, url, 0);
284                                 ldap_free_urldesc( lud );
285                                 return NULL;
286                         }
287
288                         memcpy( &l.sl_addr.sin_addr, he->h_addr,
289                                sizeof( l.sl_addr.sin_addr ) );
290                 }
291         }
292 #ifdef LDAP_PF_LOCAL
293         }
294 #endif /* LDAP_PF_LOCAL */
295
296         ldap_free_urldesc( lud );
297
298 #ifdef LDAP_PF_LOCAL
299         l.sl_sd = socket( l.sl_sa.sa_addr.sa_family, SOCK_STREAM, 0 );
300         if ( l.sl_sd == AC_SOCKET_INVALID ) {
301 #else
302         if ( (l.sl_sd = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID ) {
303 #endif /* LDAP_PF_LOCAL */
304                 int err = sock_errno();
305                 Debug( LDAP_DEBUG_ANY,
306                         "daemon: socket() failed errno=%d (%s)\n", err,
307                         sock_errstr(err), 0 );
308                 return NULL;
309         }
310
311 #ifndef HAVE_WINSOCK
312         if ( l.sl_sd >= dtblsize ) {
313                 Debug( LDAP_DEBUG_ANY,
314                         "daemon: listener descriptor %ld is too great %ld\n",
315                         (long) l.sl_sd, (long) dtblsize, 0 );
316                 tcp_close( l.sl_sd );
317                 return NULL;
318         }
319 #endif
320
321 #ifdef LDAP_PF_LOCAL
322         /* for IP sockets only */
323         if ( l.sl_sa.sa_addr.sa_family == AF_INET ) {
324 #endif /* LDAP_PF_LOCAL */
325
326 #ifdef SO_REUSEADDR
327         /* enable address reuse */
328         tmp = 1;
329         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
330                 (char *) &tmp, sizeof(tmp) );
331         if ( rc == AC_SOCKET_ERROR ) {
332                 int err = sock_errno();
333                 Debug( LDAP_DEBUG_ANY,
334                "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
335                 (long) l.sl_sd, err, sock_errstr(err) );
336         }
337 #endif
338 #ifdef SO_KEEPALIVE
339         /* enable keep alives */
340         tmp = 1;
341         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_KEEPALIVE,
342                 (char *) &tmp, sizeof(tmp) );
343         if ( rc == AC_SOCKET_ERROR ) {
344                 int err = sock_errno();
345                 Debug( LDAP_DEBUG_ANY,
346                         "slapd(%ld): setsockopt(SO_KEEPALIVE) failed errno=%d (%s)\n",
347                 (long) l.sl_sd, err, sock_errstr(err) );
348         }
349 #endif
350 #ifdef TCP_NODELAY
351         /* enable no delay */
352         tmp = 1;
353         rc = setsockopt( l.sl_sd, IPPROTO_TCP, TCP_NODELAY,
354                 (char *)&tmp, sizeof(tmp) );
355         if ( rc == AC_SOCKET_ERROR ) {
356                 int err = sock_errno();
357                 Debug( LDAP_DEBUG_ANY,
358                         "slapd(%ld): setsockopt(TCP_NODELAY) failed errno=%d (%s)\n",
359                 (long) l.sl_sd, err, sock_errstr(err) );
360         }
361 #endif
362
363 #ifdef LDAP_PF_LOCAL
364         /* close conditional */
365         }
366
367         switch ( l.sl_sa.sa_addr.sa_family ) {
368                 case AF_UNIX:
369                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
370                                 sizeof(l.sl_sa.sa_un_addr) );
371                         break;
372                 case AF_INET:
373                         rc = bind( l.sl_sd, (struct sockaddr *)&l.sl_sa,
374                                 sizeof(l.sl_sa.sa_in_addr) );
375                         break;
376                 default:
377                         rc = AC_SOCKET_ERROR;
378                         errno = EINVAL;
379                         break;
380         }
381 #else
382         rc = bind( l.sl_sd, (struct sockaddr *) &l.sl_addr, sizeof(l.sl_addr) );
383 #endif /* LDAP_PF_LOCAL */
384         if ( rc == AC_SOCKET_ERROR ) {
385                 int err = sock_errno();
386                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
387                 (long) l.sl_sd, err, sock_errstr(err) );
388                 tcp_close( l.sl_sd );
389                 return NULL;
390         }
391 #ifdef LDAP_PF_LOCAL
392         if ( l.sl_sa.sa_addr.sa_family == AF_UNIX ) {
393                 if ( chmod( l.sl_sa.sa_un_addr.sun_path, S_IRWXU ) < 0 ) {
394                         int err = sock_errno();
395                         Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
396                                 (long) l.sl_sd, err, sock_errstr(err) );
397                         tcp_close( l.sl_sd );
398                         return NULL;
399                 }
400         }
401 #endif /* LDAP_PF_LOACL */
402         l.sl_url = ch_strdup( url );
403 #ifdef LDAP_PF_LOCAL
404         switch ( l.sl_sa.sa_addr.sa_family ) {
405                 case AF_UNIX:
406                         l.sl_name = ch_malloc( strlen(l.sl_sa.sa_un_addr.sun_path) + sizeof("PATH=") );
407                         sprintf( l.sl_name, "PATH=%s", l.sl_sa.sa_un_addr.sun_path );
408                         break;
409                 case AF_INET:
410                         l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
411                         s = inet_ntoa( l.sl_addr.sin_addr );
412                         sprintf( l.sl_name, "IP=%s:%d",
413                                 s != NULL ? s : "unknown" , port );
414                         break;
415                 default:
416                         l.sl_name = ch_strdup( "UNKNOWN" );
417                         break;
418         }
419 #else
420         l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
421         s = inet_ntoa( l.sl_addr.sin_addr );
422         sprintf( l.sl_name, "IP=%s:%d",
423                 s != NULL ? s : "unknown" , port );
424 #endif /* LDAP_PF_LOCAL */
425
426         li = ch_malloc( sizeof( Listener ) );
427         *li = l;
428
429         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
430                 l.sl_url, 0, 0 );
431
432         return li;
433 }
434
435 static int sockinit(void);
436 static int sockdestroy(void);
437
438 int slapd_daemon_init( char *urls )
439 {
440         int i, rc;
441         char **u;
442
443         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
444                 urls ? urls : "<null>", 0, 0 );
445
446         if( (rc = sockinit()) != 0 ) {
447                 return rc;
448         }
449
450 #ifdef HAVE_SYSCONF
451         dtblsize = sysconf( _SC_OPEN_MAX );
452 #elif HAVE_GETDTABLESIZE
453         dtblsize = getdtablesize();
454 #else
455         dtblsize = FD_SETSIZE;
456 #endif
457
458 #ifdef FD_SETSIZE
459         if(dtblsize > FD_SETSIZE) {
460                 dtblsize = FD_SETSIZE;
461         }
462 #endif  /* !FD_SETSIZE */
463
464         /* open a pipe (or something equivalent connected to itself).
465          * we write a byte on this fd whenever we catch a signal. The main
466          * loop will be select'ing on this socket, and will wake up when
467          * this byte arrives.
468          */
469         if( (rc = lutil_pair( wake_sds )) < 0 ) {
470                 Debug( LDAP_DEBUG_ANY,
471                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
472                 return rc;
473         }
474
475         FD_ZERO( &slap_daemon.sd_readers );
476         FD_ZERO( &slap_daemon.sd_writers );
477
478         if( urls == NULL ) {
479                 urls = "ldap:///";
480         }
481
482         u = str2charray( urls, " " );
483
484         if( u == NULL || u[0] == NULL ) {
485                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
486                         urls, 0, 0 );
487
488                 return -1;
489         }
490
491         for( i=0; u[i] != NULL; i++ ) {
492                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
493                         u[i], 0, 0 );
494         }
495
496         if( i == 0 ) {
497                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
498                         urls, 0, 0 );
499                 charray_free( u );
500                 return -1;
501         }
502
503         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
504                 i, 0, 0 );
505
506         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
507
508         for(i = 0; u[i] != NULL; i++ ) {
509                 slap_listeners[i] = open_listener( u[i] );
510
511                 if( slap_listeners[i] == NULL ) {
512                         charray_free( u );
513                         return -1;
514                 }
515         }
516         slap_listeners[i] = NULL;
517
518         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
519                 i, 0, 0 );
520
521         charray_free( u );
522         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
523         return !i;
524 }
525
526
527 int
528 slapd_daemon_destroy(void)
529 {
530         connections_destroy();
531         tcp_close( wake_sds[1] );
532         tcp_close( wake_sds[0] );
533         sockdestroy();
534         return 0;
535 }
536
537
538 static void *
539 slapd_daemon_task(
540         void *ptr
541 )
542 {
543         int l;
544         time_t  last_idle_check = slap_get_time();
545         time( &starttime );
546
547         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
548                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
549                         continue;
550
551                 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
552                         int err = sock_errno();
553                         Debug( LDAP_DEBUG_ANY,
554                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
555                                         slap_listeners[l]->sl_url, err,
556                                         sock_errstr(err) );
557                         return( (void*)-1 );
558                 }
559
560                 slapd_add( slap_listeners[l]->sl_sd );
561         }
562
563 #ifdef HAVE_NT_SERVICE_MANAGER
564         if ( started_event != NULL ) {
565                 ldap_pvt_thread_cond_signal( &started_event );
566         }
567 #endif
568         /* initialization complete. Here comes the loop. */
569
570         while ( !slapd_shutdown ) {
571                 ber_socket_t i;
572                 int ns;
573                 int at;
574                 ber_socket_t nfds;
575 #define SLAPD_EBADF_LIMIT 10
576                 int ebadf = 0;
577
578 #define SLAPD_IDLE_CHECK_LIMIT 4
579                 time_t  now = slap_get_time();
580
581
582                 fd_set                  readfds;
583                 fd_set                  writefds;
584 #ifdef LDAP_PF_LOCAL
585                 Sockaddr                from;
586 /* minimize impact, undefine later. */
587 #define sin_addr sa_in_addr.sin_addr
588 #define sin_port sa_in_addr.sin_port
589 #else
590                 struct sockaddr_in      from;
591 #endif /* LDAP_PF_LOCAL */
592 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
593         struct hostent          *hp;
594 #endif
595                 struct timeval          zero;
596                 struct timeval          *tvp;
597
598                 if( global_idletimeout > 0 && difftime(
599                         last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
600                         now ) < 0 )
601                 {
602                         connections_timeout_idle(now);
603                 }
604
605                 FD_ZERO( &writefds );
606                 FD_ZERO( &readfds );
607
608                 zero.tv_sec = 0;
609                 zero.tv_usec = 0;
610
611                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
612
613 #ifdef FD_SET_MANUAL_COPY
614                 for( s = 0; s < nfds; s++ ) {
615                         if(FD_ISSET( &slap_sd_readers, s )) {
616                                 FD_SET( s, &readfds );
617                         }
618                         if(FD_ISSET( &slap_sd_writers, s )) {
619                                 FD_SET( s, &writefds );
620                         }
621                 }
622 #else
623                 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
624                 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
625 #endif
626                 assert(!FD_ISSET(wake_sds[0], &readfds));
627                 FD_SET( wake_sds[0], &readfds );
628
629                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
630                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
631                                 continue;
632                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
633                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
634                 }
635
636 #ifndef HAVE_WINSOCK
637                 nfds = slap_daemon.sd_nfds;
638 #else
639                 nfds = dtblsize;
640 #endif
641
642                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
643
644                 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
645                 at = active_threads;
646                 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
647
648 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
649                 tvp = NULL;
650 #else
651                 tvp = at ? &zero : NULL;
652 #endif
653
654                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
655                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
656                                 continue;
657
658                         Debug( LDAP_DEBUG_CONNS,
659                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
660                                         slap_listeners[l]->sl_sd, at,
661                                         tvp == NULL ? "NULL" : "zero" );
662                 }
663
664                 switch(ns = select( nfds, &readfds,
665 #ifdef HAVE_WINSOCK
666                         /* don't pass empty fd_set */
667                         ( writefds.fd_count > 0 ? &writefds : NULL ),
668 #else
669                         &writefds,
670 #endif
671                         NULL, tvp ))
672                 {
673                 case -1: {      /* failure - try again */
674                                 int err = sock_errno();
675
676                                 if( err == EBADF 
677 #ifdef HAVE_WINSOCK
678                                         || err == WSAENOTSOCK   /* you'd think this would be EBADF */
679 #endif
680                                 ) {
681                                         if (++ebadf < SLAPD_EBADF_LIMIT)
682                                                 continue;
683                                 }
684
685                                 if( err != EINTR ) {
686                                         Debug( LDAP_DEBUG_CONNS,
687                                                 "daemon: select failed (%d): %s\n",
688                                                 err, sock_errstr(err), 0 );
689
690                                         slapd_shutdown = -1;
691                                 }
692                         }
693                         continue;
694
695                 case 0:         /* timeout - let threads run */
696                         ebadf = 0;
697                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
698                             0, 0, 0 );
699                 ldap_pvt_thread_yield();
700                         continue;
701
702                 default:        /* something happened - deal with it */
703                         ebadf = 0;
704                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
705                                 ns, 0, 0 );
706                         /* FALL THRU */
707                 }
708
709                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
710                         char c[BUFSIZ];
711                         tcp_read( wake_sds[0], c, sizeof(c) );
712 #ifdef NO_THREADS
713                         waking = 0;
714 #endif
715                         continue;
716                 }
717
718                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
719                         ber_int_t s;
720                         socklen_t len = sizeof(from);
721                         long id;
722
723                         char    *dnsname;
724                         char    *peeraddr;
725 #ifdef LDAP_PF_LOCAL
726                         char    peername[MAXPATHLEN + sizeof("PATH=")];
727 #else
728                         char    peername[sizeof("IP=255.255.255.255:65336")];
729 #endif /* LDAP_PF_LOCAL */
730                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
731                                 continue;
732
733                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
734                                 continue;
735
736                         if ( (s = accept( slap_listeners[l]->sl_sd,
737                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
738                         {
739                                 int err = sock_errno();
740                                 Debug( LDAP_DEBUG_ANY,
741                                     "daemon: accept(%ld) failed errno=%d (%s)\n",
742                                     (long) slap_listeners[l]->sl_sd, err,
743                                     sock_errstr(err) );
744                                 continue;
745                         }
746
747 #ifdef LDAP_DEBUG
748                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
749
750                         /* newly accepted stream should not be in any of the FD SETS */
751
752                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
753                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
754                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
755
756                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
757 #endif
758
759 #ifndef HAVE_WINSOCK
760                         /* make sure descriptor number isn't too great */
761                         if ( s >= dtblsize ) {
762                                 Debug( LDAP_DEBUG_ANY,
763                                         "daemon: %ld beyond descriptor table size %ld\n",
764                                         (long) s, (long) dtblsize, 0 );
765                                 slapd_close(s);
766                                 continue;
767                         }
768 #endif
769                    
770                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
771                                 (long) s, 0, 0 );
772
773                         len = sizeof(from);
774
775                         if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
776                                 int err = sock_errno();
777                                 Debug( LDAP_DEBUG_ANY,
778                                         "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
779                                         (long) s, err, sock_errstr(err) );
780                                 slapd_close(s);
781                                 continue;
782                         }
783
784 #ifdef LDAP_PF_LOCAL
785                         switch ( from.sa_addr.sa_family ) {
786                         case AF_UNIX:
787                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
788                                 break;
789                         case AF_INET:
790 #endif /* LDAP_PF_LOCAL */
791                         peeraddr = inet_ntoa( from.sin_addr );
792                         sprintf( peername, "IP=%s:%d",
793                                 peeraddr != NULL ? peeraddr : "unknown",
794                                 (unsigned) ntohs( from.sin_port ) );
795
796 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
797                         hp = gethostbyaddr( (char *)
798                             &(from.sin_addr),
799                             sizeof(from.sin_addr), AF_INET );
800
801                         if(hp) {
802                                 dnsname = ldap_pvt_str2lower( hp->h_name );
803
804                         } else {
805                                 dnsname = NULL;
806                         }
807 #else
808                         dnsname = NULL;
809 #endif
810
811 #ifdef HAVE_TCPD
812                         if( !hosts_ctl("slapd",
813                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
814                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
815                                 STRING_UNKNOWN ))
816                         {
817                                 /* DENY ACCESS */
818                                 Statslog( LDAP_DEBUG_ANY,
819                                  "fd=%ld connection from %s (%s) denied.\n",
820                                         (long) s,
821                                         dnsname != NULL ? dnsname : "unknown",
822                                         peeraddr != NULL ? peeraddr : "unknown",
823                                   0, 0 );
824
825                                 slapd_close(s);
826                                 continue;
827                         }
828 #endif /* HAVE_TCPD */
829 #ifdef LDAP_PF_LOCAL
830                                 break;
831                         default:
832                                 slapd_close(s);
833                                 continue;
834                         }
835 #undef  sin_addr
836 #undef  sin_port
837 #endif /* LDAP_PF_LOCAL */
838
839                         if( (id = connection_init(s,
840                                 slap_listeners[l]->sl_url,
841                                 dnsname != NULL ? dnsname : "unknown",
842                                 peername,
843                                 slap_listeners[l]->sl_name,
844 #ifdef HAVE_TLS
845                                 slap_listeners[l]->sl_is_tls
846 #else
847                                 0
848 #endif
849                                 )) < 0 )
850                         {
851                                 Debug( LDAP_DEBUG_ANY,
852                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
853                                         (long) s,
854                                         peername,
855                                         slap_listeners[l]->sl_name );
856                                 slapd_close(s);
857                                 continue;
858                         }
859
860                         Statslog( LDAP_DEBUG_STATS,
861                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
862                                 id, (long) s,
863                                 peername,
864                                 slap_listeners[l]->sl_name,
865                                 0 );
866
867                         slapd_add( s );
868                         continue;
869                 }
870
871 #ifdef LDAP_DEBUG
872                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
873 #ifdef HAVE_WINSOCK
874                 for ( i = 0; i < readfds.fd_count; i++ ) {
875                         Debug( LDAP_DEBUG_CONNS, " %d%s",
876                                 readfds.fd_array[i], "r", 0 );
877                 }
878                 for ( i = 0; i < writefds.fd_count; i++ ) {
879                         Debug( LDAP_DEBUG_CONNS, " %d%s",
880                                 writefds.fd_array[i], "w", 0 );
881                 }
882 #else
883                 for ( i = 0; i < nfds; i++ ) {
884                         int     r, w;
885                         int     is_listener = 0;
886
887                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
888                                 if ( i == slap_listeners[l]->sl_sd ) {
889                                         is_listener = 1;
890                                         break;
891                                 }
892                         }
893                         if ( is_listener ) {
894                                 continue;
895                         }
896                         r = FD_ISSET( i, &readfds );
897                         w = FD_ISSET( i, &writefds );
898                         if ( r || w ) {
899                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
900                                     r ? "r" : "", w ? "w" : "" );
901                         }
902                 }
903 #endif
904                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
905 #endif
906
907                 /* loop through the writers */
908 #ifdef HAVE_WINSOCK
909                 for ( i = 0; i < writefds.fd_count; i++ )
910 #else
911                 for ( i = 0; i < nfds; i++ )
912 #endif
913                 {
914                         ber_socket_t wd;
915                         int is_listener = 0;
916 #ifdef HAVE_WINSOCK
917                         wd = writefds.fd_array[i];
918 #else
919                         if( ! FD_ISSET( i, &writefds ) ) {
920                                 continue;
921                         }
922                         wd = i;
923 #endif
924
925                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
926                                 if ( i == slap_listeners[l]->sl_sd ) {
927                                         is_listener = 1;
928                                         break;
929                                 }
930                         }
931                         if ( is_listener ) {
932                                 continue;
933                         }
934                         Debug( LDAP_DEBUG_CONNS,
935                                 "daemon: write active on %d\n",
936                                 wd, 0, 0 );
937
938                         /*
939                          * NOTE: it is possible that the connection was closed
940                          * and that the stream is now inactive.
941                          * connection_write() must valid the stream is still
942                          * active.
943                          */
944
945                         if ( connection_write( wd ) < 0 ) {
946                                 FD_CLR( (unsigned) wd, &readfds );
947                                 slapd_close( wd );
948                         }
949                 }
950
951 #ifdef HAVE_WINSOCK
952                 for ( i = 0; i < readfds.fd_count; i++ )
953 #else
954                 for ( i = 0; i < nfds; i++ )
955 #endif
956                 {
957                         ber_socket_t rd;
958                         int is_listener = 0;
959
960 #ifdef HAVE_WINSOCK
961                         rd = readfds.fd_array[i];
962 #else
963                         if( ! FD_ISSET( i, &readfds ) ) {
964                                 continue;
965                         }
966                         rd = i;
967 #endif
968
969                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
970                                 if ( rd == slap_listeners[l]->sl_sd ) {
971                                         is_listener = 1;
972                                         break;
973                                 }
974                         }
975                         if ( is_listener ) {
976                                 continue;
977                         }
978
979                         Debug ( LDAP_DEBUG_CONNS,
980                                 "daemon: read activity on %d\n", rd, 0, 0 );
981
982                         /*
983                          * NOTE: it is possible that the connection was closed
984                          * and that the stream is now inactive.
985                          * connection_read() must valid the stream is still
986                          * active.
987                          */
988
989                         if ( connection_read( rd ) < 0 ) {
990                                 slapd_close( rd );
991                         }
992                 }
993                 ldap_pvt_thread_yield();
994         }
995
996         if( slapd_shutdown > 0 ) {
997                 Debug( LDAP_DEBUG_TRACE,
998                         "daemon: shutdown requested and initiated.\n",
999                         0, 0, 0 );
1000
1001         } else if ( slapd_shutdown < 0 ) {
1002                 Debug( LDAP_DEBUG_TRACE,
1003                         "daemon: abnormal condition, shutdown initiated.\n",
1004                         0, 0, 0 );
1005         } else {
1006                 Debug( LDAP_DEBUG_TRACE,
1007                         "daemon: no active streams, shutdown initiated.\n",
1008                         0, 0, 0 );
1009         }
1010
1011         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1012                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1013 #ifdef LDAP_PF_LOCAL
1014                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_UNIX ) {
1015                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1016                         }
1017 #endif /* LDAP_PF_LOCAL */
1018                         slapd_close( slap_listeners[l]->sl_sd );
1019                         break;
1020                 }
1021         }
1022
1023         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
1024         Debug( LDAP_DEBUG_ANY,
1025             "slapd shutdown: waiting for %d threads to terminate\n",
1026             active_threads, 0, 0 );
1027         while ( active_threads > 0 ) {
1028                 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
1029         }
1030         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
1031
1032         return NULL;
1033 }
1034
1035
1036 int slapd_daemon( void )
1037 {
1038         int rc;
1039
1040         connections_init();
1041
1042 #define SLAPD_LISTENER_THREAD 1
1043 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
1044
1045         /* listener as a separate THREAD */
1046         rc = ldap_pvt_thread_create( &listener_tid,
1047                 0, slapd_daemon_task, NULL );
1048
1049         if ( rc != 0 ) {
1050                 Debug( LDAP_DEBUG_ANY,
1051                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1052                 return rc;
1053         }
1054
1055         /* wait for the listener thread to complete */
1056         ldap_pvt_thread_join( listener_tid, (void *) NULL );
1057 #else
1058         /* expermimental code */
1059         listener_tid = pthread_self();
1060         slapd_daemon_task( NULL );
1061 #endif
1062
1063         return 0;
1064
1065 }
1066
1067 #ifdef HAVE_WINSOCK2
1068 int sockinit(void)
1069 {
1070     WORD wVersionRequested;
1071         WSADATA wsaData;
1072         int err;
1073  
1074         wVersionRequested = MAKEWORD( 2, 0 );
1075  
1076         err = WSAStartup( wVersionRequested, &wsaData );
1077         if ( err != 0 ) {
1078                 /* Tell the user that we couldn't find a usable */
1079                 /* WinSock DLL.                                  */
1080                 return -1;
1081         }
1082  
1083         /* Confirm that the WinSock DLL supports 2.0.*/
1084         /* Note that if the DLL supports versions greater    */
1085         /* than 2.0 in addition to 2.0, it will still return */
1086         /* 2.0 in wVersion since that is the version we      */
1087         /* requested.                                        */
1088  
1089         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1090                 HIBYTE( wsaData.wVersion ) != 0 )
1091         {
1092             /* Tell the user that we couldn't find a usable */
1093             /* WinSock DLL.                                  */
1094             WSACleanup();
1095             return -1; 
1096         }
1097
1098         /* The WinSock DLL is acceptable. Proceed. */
1099         return 0;
1100 }
1101
1102 int sockdestroy(void)
1103 {
1104         WSACleanup();
1105         return 0;
1106 }
1107
1108 #elif HAVE_WINSOCK
1109 static int sockinit(void)
1110 {
1111         WSADATA wsaData;
1112         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1113             return -1;
1114         }
1115         return 0;
1116 }
1117 static int sockdestroy(void)
1118 {
1119         WSACleanup();
1120         return 0;
1121 }
1122
1123 #else
1124 static int sockinit(void)
1125 {
1126         return 0;
1127 }
1128 static int sockdestroy(void)
1129 {
1130         return 0;
1131 }
1132 #endif
1133
1134 RETSIGTYPE
1135 slap_sig_shutdown( int sig )
1136 {
1137         slapd_shutdown = sig;
1138         WAKE_LISTENER(1);
1139
1140         /* reinstall self */
1141         (void) SIGNAL( sig, slap_sig_shutdown );
1142 }
1143
1144 RETSIGTYPE
1145 slap_sig_wake( int sig )
1146 {
1147         WAKE_LISTENER(1);
1148
1149         /* reinstall self */
1150         (void) SIGNAL( sig, slap_sig_wake );
1151 }