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