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