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