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