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