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