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