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