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