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