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