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