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