]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
Further trim_refs_url fixes from Hallvard. Need additional testing.
[openldap] / servers / slapd / daemon.c
1 /*
2  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
3  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
4  */
5
6 #include "portable.h"
7
8 #include <stdio.h>
9
10 #include <ac/ctype.h>
11 #include <ac/errno.h>
12 #include <ac/signal.h>
13 #include <ac/socket.h>
14 #include <ac/string.h>
15 #include <ac/time.h>
16 #include <ac/unistd.h>
17
18 #include "ldap_pvt.h"
19 #include "lutil.h"
20 #include "slap.h"
21
22 #ifdef HAVE_TCPD
23 #include <tcpd.h>
24
25 int allow_severity = LOG_INFO;
26 int deny_severity = LOG_NOTICE;
27 #endif /* TCP Wrappers */
28
29 /* globals */
30 time_t starttime;
31 ber_socket_t dtblsize;
32
33 typedef struct slap_listener {
34         char* sl_url;
35         char* sl_name;
36 #ifdef HAVE_TLS
37         int             sl_is_tls;
38 #endif
39         ber_socket_t            sl_sd;
40         struct sockaddr_in      sl_addr;
41 } Listener;
42
43 Listener **slap_listeners = NULL;
44
45 static ber_socket_t wake_sds[2];
46
47 #define WAKE_LISTENER(w) \
48 do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
49
50 #ifdef HAVE_WINSOCK2
51 /* in nt_main.c */
52 extern ldap_pvt_thread_cond_t                   started_event;
53 #endif
54
55 #ifndef HAVE_WINSOCK
56 static 
57 #endif
58 volatile sig_atomic_t slapd_shutdown = 0;
59
60 static ldap_pvt_thread_t        listener_tid;
61
62 static struct slap_daemon {
63         ldap_pvt_thread_mutex_t sd_mutex;
64
65         int sd_nactives;
66
67 #ifndef HAVE_WINSOCK
68         /* In winsock, accept() returns values higher than dtblsize
69                 so don't bother with this optimization */
70         int sd_nfds;
71 #endif
72
73         fd_set sd_actives;
74         fd_set sd_readers;
75         fd_set sd_writers;
76 } slap_daemon; 
77
78 /*
79  * Add a descriptor to daemon control
80  */
81 static void slapd_add(ber_socket_t s) {
82         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
83
84         assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
85         assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
86         assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
87
88 #ifndef HAVE_WINSOCK
89         if (s >= slap_daemon.sd_nfds) {
90                 slap_daemon.sd_nfds = s + 1;
91         }
92 #endif
93
94         FD_SET( s, &slap_daemon.sd_actives );
95         FD_SET( s, &slap_daemon.sd_readers );
96
97         Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
98                 (long) s,
99             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
100                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
101
102         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
103 }
104
105 /*
106  * Remove the descriptor from daemon control
107  */
108 void slapd_remove(ber_socket_t s, int wake) {
109         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
110
111         Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
112                 (long) s,
113             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
114                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
115
116         FD_CLR( s, &slap_daemon.sd_actives );
117         FD_CLR( s, &slap_daemon.sd_readers );
118         FD_CLR( s, &slap_daemon.sd_writers );
119
120         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
121         WAKE_LISTENER(wake);
122 }
123
124 void slapd_clr_write(ber_socket_t s, int wake) {
125         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
126
127         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
128         FD_CLR( s, &slap_daemon.sd_writers );
129
130         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
131         WAKE_LISTENER(wake);
132 }
133
134 void slapd_set_write(ber_socket_t s, int wake) {
135         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
136
137         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
138         FD_SET( (unsigned) s, &slap_daemon.sd_writers );
139
140         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
141         WAKE_LISTENER(wake);
142 }
143
144 void slapd_clr_read(ber_socket_t s, int wake) {
145         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
146
147         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
148         FD_CLR( s, &slap_daemon.sd_readers );
149
150         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
151         WAKE_LISTENER(wake);
152 }
153
154 void slapd_set_read(ber_socket_t s, int wake) {
155         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
156
157         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
158         FD_SET( s, &slap_daemon.sd_readers );
159
160         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
161         WAKE_LISTENER(wake);
162 }
163
164 static void slapd_close(ber_socket_t s) {
165         Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
166                 (long) s, 0, 0 );
167         tcp_close(s);
168 }
169
170
171 static Listener *
172 open_listener(
173         const char* url,
174         int port,
175         int tls_port )
176 {
177         int     tmp, rc;
178         Listener l;
179         Listener *li;
180         LDAPURLDesc *lud;
181         char *s;
182
183         rc = ldap_url_parse( url, &lud );
184
185         if( rc != LDAP_URL_SUCCESS ) {
186                 Debug( LDAP_DEBUG_ANY,
187                         "daemon: listen URL \"%s\" parse error=%d\n",
188                         url, rc, 0 );
189                 return NULL;
190         }
191
192 #ifndef HAVE_TLS
193         if( lud->lud_ldaps ) {
194                 Debug( LDAP_DEBUG_ANY,
195                         "daemon: TLS not supported (%s)\n",
196                         url, 0, 0 );
197                 ldap_free_urldesc( lud );
198                 return NULL;
199         }
200
201         if(! lud->lud_port ) {
202                 lud->lud_port = port;
203         }
204
205 #else
206         l.sl_is_tls = lud->lud_ldaps;
207
208         if(! lud->lud_port ) {
209                 lud->lud_port = lud->lud_ldaps ? tls_port : port;
210         }
211 #endif
212
213         port = lud->lud_port;
214
215         (void) memset( (void*) &l.sl_addr, '\0', sizeof(l.sl_addr) );
216
217         l.sl_addr.sin_family = AF_INET;
218         l.sl_addr.sin_port = htons( (unsigned short) lud->lud_port );
219
220         if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
221                 || strcmp(lud->lud_host, "*") == 0 )
222         {
223                 l.sl_addr.sin_addr.s_addr = htonl(INADDR_ANY);
224
225         } else {
226                 /* host or address was specified */
227                 if( !inet_aton( lud->lud_host, &l.sl_addr.sin_addr ) ) {
228                         struct hostent *he = gethostbyname( lud->lud_host );
229                         if( he == NULL ) {
230                                 Debug( LDAP_DEBUG_ANY, "invalid host (%s) in URL: %s",
231                                         lud->lud_host, url, 0);
232                                 ldap_free_urldesc( lud );
233                                 return NULL;
234                         }
235
236                         memcpy( &l.sl_addr.sin_addr, he->h_addr,
237                                sizeof( l.sl_addr.sin_addr ) );
238                 }
239         }
240
241         ldap_free_urldesc( lud );
242
243
244         if ( (l.sl_sd = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID ) {
245                 int err = sock_errno();
246                 Debug( LDAP_DEBUG_ANY,
247                         "daemon: socket() failed errno=%d (%s)\n", err,
248                         sock_errstr(err), 0 );
249                 return NULL;
250         }
251
252 #ifndef HAVE_WINSOCK
253         if ( l.sl_sd >= dtblsize ) {
254                 Debug( LDAP_DEBUG_ANY,
255                         "daemon: listener descriptor %ld is too great %ld\n",
256                         (long) l.sl_sd, (long) dtblsize, 0 );
257                 tcp_close( l.sl_sd );
258                 return NULL;
259         }
260 #endif
261
262 #ifdef SO_REUSEADDR
263         /* enable address reuse */
264         tmp = 1;
265         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
266                 (char *) &tmp, sizeof(tmp) );
267         if ( rc == AC_SOCKET_ERROR ) {
268                 int err = sock_errno();
269                 Debug( LDAP_DEBUG_ANY,
270                "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
271                 (long) l.sl_sd, err, sock_errstr(err) );
272         }
273 #endif
274 #ifdef SO_KEEPALIVE
275         /* enable keep alives */
276         tmp = 1;
277         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_KEEPALIVE,
278                 (char *) &tmp, sizeof(tmp) );
279         if ( rc == AC_SOCKET_ERROR ) {
280                 int err = sock_errno();
281                 Debug( LDAP_DEBUG_ANY,
282                         "slapd(%ld): setsockopt(SO_KEEPALIVE) failed errno=%d (%s)\n",
283                 (long) l.sl_sd, err, sock_errstr(err) );
284         }
285 #endif
286 #ifdef TCP_NODELAY
287         /* enable no delay */
288         tmp = 1;
289         rc = setsockopt( l.sl_sd, IPPROTO_TCP, TCP_NODELAY,
290                 (char *)&tmp, sizeof(tmp) );
291         if ( rc == AC_SOCKET_ERROR ) {
292                 int err = sock_errno();
293                 Debug( LDAP_DEBUG_ANY,
294                         "slapd(%ld): setsockopt(TCP_NODELAY) failed errno=%d (%s)\n",
295                 (long) l.sl_sd, err, sock_errstr(err) );
296         }
297 #endif
298
299         rc = bind( l.sl_sd, (struct sockaddr *) &l.sl_addr, sizeof(l.sl_addr) );
300         if ( rc == AC_SOCKET_ERROR ) {
301                 int err = sock_errno();
302                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
303                 (long) l.sl_sd, err, sock_errstr(err) );
304                 tcp_close( l.sl_sd );
305                 return NULL;
306         }
307
308         l.sl_url = ch_strdup( url );
309
310         l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
311         s = inet_ntoa( l.sl_addr.sin_addr );
312         sprintf( l.sl_name, "IP=%s:%d",
313                 s != NULL ? s : "unknown" , port );
314
315         li = ch_malloc( sizeof( Listener ) );
316         *li = l;
317
318         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
319                 l.sl_url, 0, 0 );
320
321         return li;
322 }
323
324 static int sockinit(void);
325 static int sockdestroy(void);
326
327 int slapd_daemon_init(char *urls, int port, int tls_port )
328 {
329         int i, rc;
330         char **u;
331
332 #ifndef HAVE_TLS
333         assert( tls_port == 0 );
334 #endif
335
336         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s (%d/%d)\n",
337                 urls ? urls : "<null>", port, tls_port );
338
339         if( rc = sockinit() ) {
340                 return rc;
341         }
342
343 #ifdef HAVE_SYSCONF
344         dtblsize = sysconf( _SC_OPEN_MAX );
345 #elif HAVE_GETDTABLESIZE
346         dtblsize = getdtablesize();
347 #else
348         dtblsize = FD_SETSIZE;
349 #endif
350
351 #ifdef FD_SETSIZE
352         if(dtblsize > FD_SETSIZE) {
353                 dtblsize = FD_SETSIZE;
354         }
355 #endif  /* !FD_SETSIZE */
356
357         /* open a pipe (or something equivalent connected to itself).
358          * we write a byte on this fd whenever we catch a signal. The main
359          * loop will be select'ing on this socket, and will wake up when
360          * this byte arrives.
361          */
362         if( (rc = lutil_pair( wake_sds )) < 0 ) {
363                 Debug( LDAP_DEBUG_ANY,
364                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
365                 return rc;
366         }
367
368         FD_ZERO( &slap_daemon.sd_readers );
369         FD_ZERO( &slap_daemon.sd_writers );
370
371         if( urls == NULL ) {
372                 urls = "ldap:///";
373         }
374
375         u = str2charray( urls, " " );
376
377         if( u == NULL || u[0] == NULL ) {
378                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
379                         urls, 0, 0 );
380
381                 return -1;
382         }
383
384         for( i=0; u[i] != NULL; i++ ) {
385                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
386                         u[i], 0, 0 );
387         }
388
389         if( i == 0 ) {
390                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
391                         urls, 0, 0 );
392                 charray_free( u );
393                 return -1;
394         }
395
396         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
397                 i, 0, 0 );
398
399         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
400
401         for(i = 0; u[i] != NULL; i++ ) {
402                 slap_listeners[i] = open_listener( u[i], port, tls_port );
403
404                 if( slap_listeners[i] == NULL ) {
405                         charray_free( u );
406                         return -1;
407                 }
408         }
409         slap_listeners[i] = NULL;
410
411         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
412                 i, 0, 0 );
413
414         charray_free( u );
415         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
416         return !i;
417 }
418
419
420 int
421 slapd_daemon_destroy(void)
422 {
423         connections_destroy();
424         tcp_close( wake_sds[1] );
425         tcp_close( wake_sds[0] );
426         sockdestroy();
427         return 0;
428 }
429
430
431 static void *
432 slapd_daemon_task(
433         void *ptr
434 )
435 {
436         int l;
437         time_t  last_idle_check = slap_get_time();
438         time( &starttime );
439
440         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
441                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
442                         continue;
443
444                 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
445                         int err = sock_errno();
446                         Debug( LDAP_DEBUG_ANY,
447                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
448                                         slap_listeners[l]->sl_url, err,
449                                         sock_errstr(err) );
450                         return( (void*)-1 );
451                 }
452
453                 slapd_add( slap_listeners[l]->sl_sd );
454         }
455
456 #ifdef HAVE_WINSOCK
457         if ( started_event != NULL ) {
458                 ldap_pvt_thread_cond_signal( &started_event );
459         }
460 #endif
461         /* initialization complete. Here comes the loop. */
462
463         while ( !slapd_shutdown ) {
464                 ber_socket_t i;
465                 int ns;
466                 int at;
467                 ber_socket_t nfds;
468 #define SLAPD_EBADF_LIMIT 10
469                 int ebadf = 0;
470
471 #define SLAPD_IDLE_CHECK_LIMIT 4
472                 time_t  now = slap_get_time();
473
474
475                 fd_set                  readfds;
476                 fd_set                  writefds;
477
478                 struct sockaddr_in      from;
479 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
480         struct hostent          *hp;
481 #endif
482                 struct timeval          zero;
483                 struct timeval          *tvp;
484
485                 if( global_idletimeout > 0 && difftime(
486                         last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
487                         now ) < 0 )
488                 {
489                         connections_timeout_idle(now);
490                 }
491
492                 FD_ZERO( &writefds );
493                 FD_ZERO( &readfds );
494
495                 zero.tv_sec = 0;
496                 zero.tv_usec = 0;
497
498                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
499
500 #ifdef FD_SET_MANUAL_COPY
501                 for( s = 0; s < nfds; s++ ) {
502                         if(FD_ISSET( &slap_sd_readers, s )) {
503                                 FD_SET( s, &readfds );
504                         }
505                         if(FD_ISSET( &slap_sd_writers, s )) {
506                                 FD_SET( s, &writefds );
507                         }
508                 }
509 #else
510                 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
511                 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
512 #endif
513                 FD_SET( wake_sds[0], &readfds );
514
515                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
516                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
517                                 continue;
518                         FD_SET( slap_listeners[l]->sl_sd, &readfds );
519                 }
520
521 #ifndef HAVE_WINSOCK
522                 nfds = slap_daemon.sd_nfds;
523 #else
524                 nfds = dtblsize;
525 #endif
526
527                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
528
529                 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
530                 at = active_threads;
531                 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
532
533 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
534                 tvp = NULL;
535 #else
536                 tvp = at ? &zero : NULL;
537 #endif
538
539                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
540                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
541                                 continue;
542
543                         Debug( LDAP_DEBUG_CONNS,
544                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
545                                         slap_listeners[l]->sl_sd, at,
546                                         tvp == NULL ? "NULL" : "zero" );
547                 }
548
549                 switch(ns = select( nfds, &readfds,
550 #ifdef HAVE_WINSOCK
551                         /* don't pass empty fd_set */
552                         ( writefds.fd_count > 0 ? &writefds : NULL ),
553 #else
554                         &writefds,
555 #endif
556                         NULL, tvp ))
557                 {
558                 case -1: {      /* failure - try again */
559                                 int err = sock_errno();
560
561                                 if( err == EBADF && ++ebadf < SLAPD_EBADF_LIMIT) {
562                                         continue;
563                                 }
564
565                                 if( err != EINTR ) {
566                                         Debug( LDAP_DEBUG_CONNS,
567                                                 "daemon: select failed (%d): %s\n",
568                                                 err, sock_errstr(err), 0 );
569
570                                         slapd_shutdown = -1;
571                                 }
572                         }
573                         continue;
574
575                 case 0:         /* timeout - let threads run */
576                         ebadf = 0;
577                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
578                             0, 0, 0 );
579                 ldap_pvt_thread_yield();
580                         continue;
581
582                 default:        /* something happened - deal with it */
583                         ebadf = 0;
584                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
585                                 ns, 0, 0 );
586                         /* FALL THRU */
587                 }
588
589                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
590                         char c;
591                         tcp_read( wake_sds[0], &c, 1 );
592                         continue;
593                 }
594
595                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
596                         ber_int_t s;
597                         socklen_t len = sizeof(from);
598                         long id;
599
600                         char    *dnsname;
601                         char    *peeraddr;
602
603                         char    peername[sizeof("IP=255.255.255.255:65336")];
604
605                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
606                                 continue;
607
608                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
609                                 continue;
610
611                         if ( (s = accept( slap_listeners[l]->sl_sd,
612                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
613                         {
614                                 int err = sock_errno();
615                                 Debug( LDAP_DEBUG_ANY,
616                                     "daemon: accept(%ld) failed errno=%d (%s)\n",
617                                     (long) slap_listeners[l]->sl_sd, err,
618                                     sock_errstr(err) );
619                                 continue;
620                         }
621
622 #ifdef LDAP_DEBUG
623                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
624
625                         /* newly accepted stream should not be in any of the FD SETS */
626
627                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
628                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
629                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
630
631                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
632 #endif
633
634 #ifndef HAVE_WINSOCK
635                         /* make sure descriptor number isn't too great */
636                         if ( s >= dtblsize ) {
637                                 Debug( LDAP_DEBUG_ANY,
638                                         "daemon: %ld beyond descriptor table size %ld\n",
639                                         (long) s, (long) dtblsize, 0 );
640                                 slapd_close(s);
641                                 continue;
642                         }
643 #endif
644                    
645                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
646                                 (long) s, 0, 0 );
647
648                         len = sizeof(from);
649
650                         if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
651                                 int err = sock_errno();
652                                 Debug( LDAP_DEBUG_ANY,
653                                         "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
654                                         (long) s, err, sock_errstr(err) );
655                                 slapd_close(s);
656                                 continue;
657                         }
658
659                         peeraddr = inet_ntoa( from.sin_addr );
660                         sprintf( peername, "IP=%s:%d",
661                                 peeraddr != NULL ? peeraddr : "unknown",
662                                 (unsigned) ntohs( from.sin_port ) );
663
664 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
665                         hp = gethostbyaddr( (char *)
666                             &(from.sin_addr.s_addr),
667                             sizeof(from.sin_addr.s_addr), AF_INET );
668
669                         if(hp) {
670                                 dnsname = ldap_pvt_str2lower( hp->h_name );
671
672                         } else {
673                                 dnsname = NULL;
674                         }
675 #else
676                         dnsname = NULL;
677 #endif
678
679 #ifdef HAVE_TCPD
680                         if( !hosts_ctl("slapd",
681                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
682                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
683                                 STRING_UNKNOWN ))
684                         {
685                                 /* DENY ACCESS */
686                                 Statslog( LDAP_DEBUG_ANY,
687                                  "fd=%ld connection from %s (%s) denied.\n",
688                                         (long) s,
689                                         dnsname != NULL ? dnsname : "unknown",
690                                         peeraddr != NULL ? peeraddr : "unknown",
691                                   0, 0 );
692
693                                 slapd_close(s);
694                                 continue;
695                         }
696 #endif /* HAVE_TCPD */
697
698                         if( (id = connection_init(s,
699                                 slap_listeners[l]->sl_url,
700                                 dnsname != NULL ? dnsname : "unknown",
701                                 peername,
702                                 slap_listeners[l]->sl_name,
703 #ifdef HAVE_TLS
704                                 slap_listeners[l]->sl_is_tls
705 #else
706                                 0
707 #endif
708                                 )) < 0 )
709                         {
710                                 Debug( LDAP_DEBUG_ANY,
711                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
712                                         (long) s,
713                                         peername,
714                                         slap_listeners[l]->sl_name );
715                                 slapd_close(s);
716                                 continue;
717                         }
718
719                         Statslog( LDAP_DEBUG_STATS,
720                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
721                                 id, (long) s,
722                                 peername,
723                                 slap_listeners[l]->sl_name,
724                                 0 );
725
726                         slapd_add( s );
727                         continue;
728                 }
729
730 #ifdef LDAP_DEBUG
731                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
732 #ifdef HAVE_WINSOCK
733                 for ( i = 0; i < readfds.fd_count; i++ ) {
734                         Debug( LDAP_DEBUG_CONNS, " %d%s",
735                                 readfds.fd_array[i], "r", 0 );
736                 }
737                 for ( i = 0; i < writefds.fd_count; i++ ) {
738                         Debug( LDAP_DEBUG_CONNS, " %d%s",
739                                 writefds.fd_array[i], "w", 0 );
740                 }
741 #else
742                 for ( i = 0; i < nfds; i++ ) {
743                         int     r, w;
744                         int     is_listener = 0;
745
746                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
747                                 if ( i == slap_listeners[l]->sl_sd ) {
748                                         is_listener = 1;
749                                         break;
750                                 }
751                         }
752                         if ( is_listener ) {
753                                 continue;
754                         }
755                         r = FD_ISSET( i, &readfds );
756                         w = FD_ISSET( i, &writefds );
757                         if ( r || w ) {
758                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
759                                     r ? "r" : "", w ? "w" : "" );
760                         }
761                 }
762 #endif
763                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
764 #endif
765
766                 /* loop through the writers */
767 #ifdef HAVE_WINSOCK
768                 for ( i = 0; i < writefds.fd_count; i++ )
769 #else
770                 for ( i = 0; i < nfds; i++ )
771 #endif
772                 {
773                         ber_socket_t wd;
774                         int is_listener = 0;
775 #ifdef HAVE_WINSOCK
776                         wd = writefds.fd_array[i];
777 #else
778                         if( ! FD_ISSET( i, &writefds ) ) {
779                                 continue;
780                         }
781                         wd = i;
782 #endif
783
784                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
785                                 if ( i == slap_listeners[l]->sl_sd ) {
786                                         is_listener = 1;
787                                         break;
788                                 }
789                         }
790                         if ( is_listener ) {
791                                 continue;
792                         }
793                         Debug( LDAP_DEBUG_CONNS,
794                                 "daemon: write active on %d\n",
795                                 wd, 0, 0 );
796
797                         /*
798                          * NOTE: it is possible that the connection was closed
799                          * and that the stream is now inactive.
800                          * connection_write() must valid the stream is still
801                          * active.
802                          */
803
804                         if ( connection_write( wd ) < 0 ) {
805                                 FD_CLR( (unsigned) wd, &readfds );
806                                 slapd_close( wd );
807                         }
808                 }
809
810 #ifdef HAVE_WINSOCK
811                 for ( i = 0; i < readfds.fd_count; i++ )
812 #else
813                 for ( i = 0; i < nfds; i++ )
814 #endif
815                 {
816                         ber_socket_t rd;
817                         int is_listener = 0;
818
819 #ifdef HAVE_WINSOCK
820                         rd = readfds.fd_array[i];
821 #else
822                         if( ! FD_ISSET( i, &readfds ) ) {
823                                 continue;
824                         }
825                         rd = i;
826 #endif
827
828                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
829                                 if ( rd == slap_listeners[l]->sl_sd ) {
830                                         is_listener = 1;
831                                         break;
832                                 }
833                         }
834                         if ( is_listener ) {
835                                 continue;
836                         }
837
838                         Debug ( LDAP_DEBUG_CONNS,
839                                 "daemon: read activity on %d\n", rd, 0, 0 );
840
841                         /*
842                          * NOTE: it is possible that the connection was closed
843                          * and that the stream is now inactive.
844                          * connection_read() must valid the stream is still
845                          * active.
846                          */
847
848                         if ( connection_read( rd ) < 0 ) {
849                                 slapd_close( rd );
850                         }
851                 }
852                 ldap_pvt_thread_yield();
853         }
854
855         if( slapd_shutdown > 0 ) {
856                 Debug( LDAP_DEBUG_TRACE,
857                         "daemon: shutdown requested and initiated.\n",
858                         0, 0, 0 );
859
860         } else if ( slapd_shutdown < 0 ) {
861                 Debug( LDAP_DEBUG_TRACE,
862                         "daemon: abnormal condition, shutdown initiated.\n",
863                         0, 0, 0 );
864         } else {
865                 Debug( LDAP_DEBUG_TRACE,
866                         "daemon: no active streams, shutdown initiated.\n",
867                         0, 0, 0 );
868         }
869
870         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
871                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
872                         slapd_close( slap_listeners[l]->sl_sd );
873                         break;
874                 }
875         }
876
877         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
878         Debug( LDAP_DEBUG_ANY,
879             "slapd shutdown: waiting for %d threads to terminate\n",
880             active_threads, 0, 0 );
881         while ( active_threads > 0 ) {
882                 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
883         }
884         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
885
886         return NULL;
887 }
888
889
890 int slapd_daemon( void )
891 {
892         int rc;
893
894         connections_init();
895
896 #define SLAPD_LISTENER_THREAD 1
897 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
898
899         /* listener as a separate THREAD */
900         rc = ldap_pvt_thread_create( &listener_tid,
901                 0, slapd_daemon_task, NULL );
902
903         if ( rc != 0 ) {
904                 Debug( LDAP_DEBUG_ANY,
905                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
906                 return rc;
907         }
908
909         /* wait for the listener thread to complete */
910         ldap_pvt_thread_join( listener_tid, (void *) NULL );
911 #else
912         /* expermimental code */
913         listener_tid = pthread_self();
914         slapd_daemon_task( NULL );
915 #endif
916
917         return 0;
918
919 }
920
921 #ifdef HAVE_WINSOCK2
922 int sockinit(void)
923 {
924     WORD wVersionRequested;
925         WSADATA wsaData;
926         int err;
927  
928         wVersionRequested = MAKEWORD( 2, 0 );
929  
930         err = WSAStartup( wVersionRequested, &wsaData );
931         if ( err != 0 ) {
932                 /* Tell the user that we couldn't find a usable */
933                 /* WinSock DLL.                                  */
934                 return -1;
935         }
936  
937         /* Confirm that the WinSock DLL supports 2.0.*/
938         /* Note that if the DLL supports versions greater    */
939         /* than 2.0 in addition to 2.0, it will still return */
940         /* 2.0 in wVersion since that is the version we      */
941         /* requested.                                        */
942  
943         if ( LOBYTE( wsaData.wVersion ) != 2 ||
944                 HIBYTE( wsaData.wVersion ) != 0 )
945         {
946             /* Tell the user that we couldn't find a usable */
947             /* WinSock DLL.                                  */
948             WSACleanup();
949             return -1; 
950         }
951
952         /* The WinSock DLL is acceptable. Proceed. */
953         return 0;
954 }
955
956 int sockdestroy(void)
957 {
958         WSACleanup();
959         return 0;
960 }
961
962 #elif HAVE_WINSOCK
963 static int sockinit(void)
964 {
965         WSADATA wsaData;
966         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
967             return -1;
968         }
969         return 0;
970 }
971 static int sockdestroy(void)
972 {
973         WSACleanup();
974         return 0;
975 }
976
977 #else
978 static int sockinit(void)
979 {
980         return 0;
981 }
982 static int sockdestroy(void)
983 {
984         return 0;
985 }
986 #endif
987
988 RETSIGTYPE
989 slap_sig_shutdown( int sig )
990 {
991         slapd_shutdown = sig;
992         WAKE_LISTENER(1);
993
994         /* reinstall self */
995         (void) SIGNAL( sig, slap_sig_shutdown );
996 }
997
998 RETSIGTYPE
999 slap_sig_wake( int sig )
1000 {
1001         WAKE_LISTENER(1);
1002
1003         /* reinstall self */
1004         (void) SIGNAL( sig, slap_sig_wake );
1005 }