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