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