]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
3de1106ecf457f5366613331d58cb13993508422
[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
255 #ifdef HAVE_WINSOCK
256                 if((l.sl_addr.sin_addr.S_un.S_addr = inet_addr(lud->lud_host)) == INADDR_NONE)
257 #else
258                 if(!inet_aton(lud->lud_host, &l.sl_addr.sin_addr))
259 #endif  
260                 {
261                         struct hostent *he = gethostbyname( lud->lud_host );
262                         if( he == NULL ) {
263                                 Debug( LDAP_DEBUG_ANY, "invalid host (%s) in URL: %s",
264                                         lud->lud_host, url, 0);
265                                 ldap_free_urldesc( lud );
266                                 return NULL;
267                         }
268
269 #ifdef HAVE_WINSOCK
270                         memcpy( &l.sl_addr.sin_addr.S_un.S_addr, he->h_addr,
271                                sizeof( l.sl_addr.sin_addr.S_un.S_addr ) );
272 #else
273                         memcpy( &l.sl_addr.sin_addr, he->h_addr,
274                                sizeof( l.sl_addr.sin_addr ) );
275 #endif  
276                 }
277         }
278
279         ldap_free_urldesc( lud );
280
281
282         if ( (l.sl_sd = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID ) {
283 #ifndef HAVE_WINSOCK
284                 int err = errno;
285                 Debug( LDAP_DEBUG_ANY,
286                         "daemon: socket() failed errno %d (%s)\n", err,
287                 err > -1 && err < sys_nerr ? sys_errlist[err] :
288                 "unknown", 0 );
289 #else
290                 Debug( LDAP_DEBUG_ANY, 
291                         "daemon: socket() failed errno %d (%s)\n",
292                         WSAGetLastError(),
293                 WSAGetLastErrorString(), 0 );
294 #endif
295                 return NULL;
296         }
297
298 #ifndef HAVE_WINSOCK
299         if ( l.sl_sd >= dtblsize ) {
300                 Debug( LDAP_DEBUG_ANY,
301                         "daemon: listener descriptor %ld is too great %ld\n",
302                         (long) l.sl_sd, (long) dtblsize, 0 );
303                 tcp_close( l.sl_sd );
304                 return NULL;
305         }
306 #endif
307
308 #ifdef SO_REUSEADDR
309         tmp = 1;
310         if ( setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
311                 (char *) &tmp, sizeof(tmp) ) == -1 )
312         {
313                 int err = errno;
314                 Debug( LDAP_DEBUG_ANY,
315                "slapd(%ld): setsockopt() failed errno %d (%s)\n",
316                 (long) l.sl_sd, err,
317                         err > -1 && err < sys_nerr
318                                 ? sys_errlist[err] : "unknown" );
319         }
320 #endif
321 #ifdef SO_KEEPALIVE
322         tmp = 1;
323         if ( setsockopt( l.sl_sd, SOL_SOCKET, SO_KEEPALIVE,
324                 (char *) &tmp, sizeof(tmp) ) == -1 )
325         {
326                 int err = errno;
327                 Debug( LDAP_DEBUG_ANY,
328                         "slapd(%ld): setsockopt(KEEPALIVE) failed errno %d (%s)\n",
329                 (long) l.sl_sd, err,
330                         err > -1 && err < sys_nerr
331                                 ? sys_errlist[err] : "unknown" );
332         }
333 #endif
334
335         if ( bind( l.sl_sd, (struct sockaddr *) &l.sl_addr, sizeof(l.sl_addr) ) == -1 ) {
336                 int err = errno;
337                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno %d (%s)\n",
338                 (long) l.sl_sd, err,
339                         err > -1 && err < sys_nerr
340                                 ? sys_errlist[err] : "unknown" );
341                 tcp_close( l.sl_sd );
342                 return NULL;
343         }
344
345         l.sl_url = ch_strdup( url );
346
347         l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65336") );
348         s = inet_ntoa( l.sl_addr.sin_addr );
349         sprintf( l.sl_name, "IP=%s:%d",
350                 s != NULL ? s : "unknown" , port );
351
352         li = ch_malloc( sizeof( Listener ) );
353         *li = l;
354
355         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
356                 l.sl_url, 0, 0 );
357
358         return li;
359 }
360
361 static int sockinit(void);
362 static int sockdestroy(void);
363
364 int slapd_daemon_init(char *urls, int port, int tls_port )
365 {
366         int i, rc;
367         char **u;
368
369 #ifndef HAVE_TLS
370         assert( tls_port == 0 );
371 #endif
372
373         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s (%d/%d)\n",
374                 urls ? urls : "<null>", port, tls_port );
375
376         if( rc = sockinit() ) {
377                 return rc;
378         }
379
380 #ifdef HAVE_SYSCONF
381         dtblsize = sysconf( _SC_OPEN_MAX );
382 #elif HAVE_GETDTABLESIZE
383         dtblsize = getdtablesize();
384 #else
385         dtblsize = FD_SETSIZE;
386 #endif
387
388 #ifdef FD_SETSIZE
389         if(dtblsize > FD_SETSIZE) {
390                 dtblsize = FD_SETSIZE;
391         }
392 #endif  /* !FD_SETSIZE */
393
394         FD_ZERO( &slap_daemon.sd_readers );
395         FD_ZERO( &slap_daemon.sd_writers );
396
397         if( urls == NULL ) {
398                 urls = "ldap:///";
399         }
400
401         u = str2charray( urls, " " );
402
403         if( u == NULL || u[0] == NULL ) {
404                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
405                         urls, 0, 0 );
406
407                 return -1;
408         }
409
410         for( i=0; u[i] != NULL; i++ ) {
411                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
412                         u[i], 0, 0 );
413         }
414
415         if( i == 0 ) {
416                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
417                         urls, 0, 0 );
418                 return -1;
419         }
420
421         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
422                 i, 0, 0 );
423
424         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
425
426         for(i = 0; u[i] != NULL; i++ ) {
427                 slap_listeners[i] = open_listener( u[i], port, tls_port );
428
429                 if( slap_listeners[i] == NULL ) {
430                         return -1;
431                 }
432         }
433         slap_listeners[i] = NULL;
434
435         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened.\n",
436                 i, 0, 0 );
437
438         charray_free( u );
439         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
440         return !i;
441 }
442
443
444 slapd_daemon_destroy(void)
445 {
446         connections_destroy();
447         sockdestroy();
448         return 0;
449 }
450
451
452 static void *
453 slapd_daemon_task(
454         void *ptr
455 )
456 {
457         int l;
458
459         time( &starttime );
460
461         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
462                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
463                         continue;
464
465                 if ( listen( slap_listeners[l]->sl_sd, 5 ) == -1 ) {
466                         int err = errno;
467                         Debug( LDAP_DEBUG_ANY,
468                                 "daemon: listen(%s, 5) failed errno %d (%s)\n",
469                                         (long) slap_listeners[l]->sl_url, err,
470                                         err > -1 && err < sys_nerr
471                                         ? sys_errlist[err] : "unknown" );
472
473                         return( (void*)-1 );
474                 }
475
476                 slapd_add( slap_listeners[l]->sl_sd );
477         }
478
479 #ifdef HAVE_WINSOCK
480         if ( started_event != NULL ) {
481                 ldap_pvt_thread_cond_signal( &started_event );
482         }
483 #endif
484         /* initialization complete. Here comes the loop. */
485
486         while ( !slapd_shutdown ) {
487                 ber_socket_t i;
488                 int ns;
489                 int at;
490                 ber_socket_t nfds;
491 #define SLAPD_EBADF_LIMIT 10
492                 int ebadf = 0;
493
494 #define SLAPD_IDLE_CHECK_LIMIT 4
495                 time_t  last_idle_check = slap_get_time();
496                 time_t  now;
497
498
499                 fd_set                  readfds;
500                 fd_set                  writefds;
501
502                 struct sockaddr_in      from;
503 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
504         struct hostent          *hp;
505 #endif
506                 struct timeval          zero;
507                 struct timeval          *tvp;
508
509                 if( global_idletimeout > 0 && difftime(
510                         last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT,
511                         now ) < 0 )
512                 {
513                         connections_timeout_idle(now);
514                 }
515
516                 FD_ZERO( &writefds );
517                 FD_ZERO( &readfds );
518
519                 zero.tv_sec = 0;
520                 zero.tv_usec = 0;
521
522                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
523
524 #ifdef FD_SET_MANUAL_COPY
525                 for( s = 0; s < nfds; s++ ) {
526                         if(FD_ISSET( &slap_sd_writers, s )) {
527                                 FD_SET( &writefds, s );
528                         }
529                         if(FD_ISSET( &slap_sd_writers, s )) {
530                                 FD_SET( &writefds, s );
531                         }
532                 }
533 #else
534                 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
535                 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
536 #endif
537
538                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
539                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
540                                 continue;
541                         FD_SET( slap_listeners[l]->sl_sd, &readfds );
542                 }
543
544 #ifndef HAVE_WINSOCK
545                 nfds = slap_daemon.sd_nfds;
546 #else
547                 nfds = dtblsize;
548 #endif
549
550                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
551
552                 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
553                 at = active_threads;
554                 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
555
556 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
557                 tvp = NULL;
558 #else
559                 tvp = at ? &zero : NULL;
560 #endif
561
562                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
563                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
564                                 continue;
565
566                         Debug( LDAP_DEBUG_CONNS,
567                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
568                                         slap_listeners[l]->sl_sd, at,
569                                         tvp == NULL ? "NULL" : "zero" );
570                 }
571
572                 switch(ns = select( nfds, &readfds,
573 #ifdef HAVE_WINSOCK
574                         /* don't pass empty fd_set */
575                         ( writefds.fd_count > 0 ? &writefds : NULL ),
576 #else
577                         &writefds,
578 #endif
579                         NULL, tvp ))
580                 {
581                 case -1: {      /* failure - try again */
582 #ifdef HAVE_WINSOCK
583                                 int err = WSAGetLastError();
584 #else
585                                 int err = errno;
586 #endif
587
588                                 if( err == EBADF && ++ebadf < SLAPD_EBADF_LIMIT) {
589                                         continue;
590                                 }
591
592                                 if( err != EINTR ) {
593                                         Debug( LDAP_DEBUG_CONNS,
594                                                 "daemon: select failed (%d): %s\n",
595                                                 err,
596                                                 err >= 0 && err < sys_nerr
597                                                         ? sys_errlist[err] : "unknown",
598                                                 0 );
599
600
601                                 slapd_shutdown = -1;
602                                 }
603                         }
604                         continue;
605
606                 case 0:         /* timeout - let threads run */
607                         ebadf = 0;
608                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
609                             0, 0, 0 );
610                 ldap_pvt_thread_yield();
611                         continue;
612
613                 default:        /* something happened - deal with it */
614                         ebadf = 0;
615                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
616                                 ns, 0, 0 );
617                         /* FALL THRU */
618                 }
619
620                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
621                         ber_int_t s;
622                         socklen_t len = sizeof(from);
623                         long id;
624
625                         char    *dnsname;
626                         char    *peeraddr;
627
628                         char    peername[sizeof("IP:255.255.255.255:65336")];
629
630                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
631                                 continue;
632
633                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
634                                 continue;
635
636                         if ( (s = accept( slap_listeners[l]->sl_sd,
637                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
638                         {
639                                 int err = errno;
640                                 Debug( LDAP_DEBUG_ANY,
641                                     "daemon: accept(%ld) failed errno %d (%s)\n", err,
642                                     (long) slap_listeners[l]->sl_sd,
643                                     err >= 0 && err < sys_nerr ?
644                                     sys_errlist[err] : "unknown");
645                                 continue;
646                         }
647
648 #ifdef LDAP_DEBUG
649                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
650
651                         /* newly accepted stream should not be in any of the FD SETS */
652
653                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
654                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
655                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
656
657                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
658 #endif
659
660 #ifndef HAVE_WINSOCK
661                         /* make sure descriptor number isn't too great */
662                         if ( s >= dtblsize ) {
663                                 Debug( LDAP_DEBUG_ANY,
664                                         "daemon: %ld beyond descriptor table size %ld\n",
665                                         (long) s, (long) dtblsize, 0 );
666                                 slapd_close(s);
667                                 continue;
668                         }
669 #endif
670                    
671                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
672                                 (long) s, 0, 0 );
673
674                         len = sizeof(from);
675
676                         if ( getpeername( s, (struct sockaddr *) &from, &len ) != 0 ) {
677                                 int err = errno;
678                                 Debug( LDAP_DEBUG_ANY,
679                                         "daemon: getpeername( %ld ) failed: errno=%d (%s)\n",
680                                         (long) s, err,
681                                     err >= 0 && err < sys_nerr ?
682                                     sys_errlist[err] : "unknown" );
683                                 slapd_close(s);
684                                 continue;
685                         }
686
687                         peeraddr = inet_ntoa( from.sin_addr );
688                         sprintf( peername, "IP:%s:%d",
689                                 peeraddr != NULL ? peeraddr : "unknown",
690                                 (unsigned) ntohs( from.sin_port ) );
691
692 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
693                         hp = gethostbyaddr( (char *)
694                             &(from.sin_addr.s_addr),
695                             sizeof(from.sin_addr.s_addr), AF_INET );
696
697                         if(hp) {
698                                 dnsname = str2lower( hp->h_name );
699
700                         } else {
701                                 dnsname = NULL;
702                         }
703 #else
704                         dnsname = NULL;
705 #endif
706
707 #ifdef HAVE_TCPD
708                         if( !hosts_ctl("slapd",
709                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
710                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
711                                 STRING_UNKNOWN ))
712                         {
713                                 /* DENY ACCESS */
714                                 Statslog( LDAP_DEBUG_ANY,
715                                  "fd=%ld connection from %s (%s) denied.\n",
716                                         (long) s,
717                                         dnsname != NULL ? dnsname : "unknown",
718                                         peeraddr != NULL ? peeraddr : "unknown",
719                                   0, 0 );
720
721                                 slapd_close(s);
722                                 continue;
723                         }
724 #endif /* HAVE_TCPD */
725
726                         if( (id = connection_init(s,
727                                 slap_listeners[l]->sl_url,
728                                 dnsname, peername,
729                                 slap_listeners[l]->sl_name,
730 #ifdef HAVE_TLS
731                                 slap_listeners[l]->sl_is_tls
732 #else
733                                 0
734 #endif
735                                 )) < 0 )
736                         {
737                                 Debug( LDAP_DEBUG_ANY,
738                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
739                                         (long) s,
740                                         peername,
741                                         slap_listeners[l]->sl_name );
742                                 slapd_close(s);
743                                 continue;
744                         }
745
746                         Statslog( LDAP_DEBUG_STATS,
747                                 "daemon: conn=%d fd=%ld connection from %s (%s) accepted.\n",
748                                 id, (long) s,
749                                 peername,
750                                 slap_listeners[l]->sl_name,
751                                 0 );
752
753                         slapd_add( s );
754                         continue;
755                 }
756
757 #ifdef LDAP_DEBUG
758                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
759 #ifdef HAVE_WINSOCK
760                 for ( i = 0; i < readfds.fd_count; i++ ) {
761                         Debug( LDAP_DEBUG_CONNS, " %d%s",
762                                 readfds.fd_array[i], "r", 0 );
763                 }
764                 for ( i = 0; i < writefds.fd_count; i++ ) {
765                         Debug( LDAP_DEBUG_CONNS, " %d%s",
766                                 writefds.fd_array[i], "w", 0 );
767                 }
768 #else
769                 for ( i = 0; i < nfds; i++ ) {
770                         int     a, r, w;
771                         int     is_listener = 0;
772
773                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
774                                 if ( i == slap_listeners[l]->sl_sd ) {
775                                         is_listener = 1;
776                                         break;
777                                 }
778                         }
779                         if ( is_listener ) {
780                                 continue;
781                         }
782                         r = FD_ISSET( i, &readfds );
783                         w = FD_ISSET( i, &writefds );
784                         if ( r || w ) {
785                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
786                                     r ? "r" : "", w ? "w" : "" );
787                         }
788                 }
789 #endif
790                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
791 #endif
792
793                 /* loop through the writers */
794 #ifdef HAVE_WINSOCK
795                 for ( i = 0; i < writefds.fd_count; i++ )
796 #else
797                 for ( i = 0; i < nfds; i++ )
798 #endif
799                 {
800                         ber_socket_t wd;
801                         int is_listener = 0;
802 #ifdef HAVE_WINSOCK
803                         wd = writefds.fd_array[i];
804 #else
805                         if( ! FD_ISSET( i, &writefds ) ) {
806                                 continue;
807                         }
808                         wd = i;
809 #endif
810
811                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
812                                 if ( i == slap_listeners[l]->sl_sd ) {
813                                         is_listener = 1;
814                                         break;
815                                 }
816                         }
817                         if ( is_listener ) {
818                                 continue;
819                         }
820                         Debug( LDAP_DEBUG_CONNS,
821                                 "daemon: write active on %d\n",
822                                 wd, 0, 0 );
823
824                         /*
825                          * NOTE: it is possible that the connection was closed
826                          * and that the stream is now inactive.
827                          * connection_write() must valid the stream is still
828                          * active.
829                          */
830
831                         if ( connection_write( wd ) < 0 ) {
832                                 FD_CLR( (unsigned) wd, &readfds );
833                                 slapd_close( wd );
834                         }
835                 }
836
837 #ifdef HAVE_WINSOCK
838                 for ( i = 0; i < readfds.fd_count; i++ )
839 #else
840                 for ( i = 0; i < nfds; i++ )
841 #endif
842                 {
843                         ber_socket_t rd;
844                         int is_listener = 0;
845                         int rc;
846
847 #ifdef HAVE_WINSOCK
848                         rd = readfds.fd_array[i];
849 #else
850                         if( ! FD_ISSET( i, &readfds ) ) {
851                                 continue;
852                         }
853                         rd = i;
854 #endif
855
856                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
857                                 if ( rd == slap_listeners[l]->sl_sd ) {
858                                         is_listener = 1;
859                                         break;
860                                 }
861                         }
862                         if ( is_listener ) {
863                                 continue;
864                         }
865
866                         Debug ( LDAP_DEBUG_CONNS,
867                                 "daemon: read activity on %d\n", rd, 0, 0 );
868
869                         /*
870                          * NOTE: it is possible that the connection was closed
871                          * and that the stream is now inactive.
872                          * connection_read() must valid the stream is still
873                          * active.
874                          */
875
876                         if ( connection_read( rd ) < 0 ) {
877                                 slapd_close( rd );
878                         }
879                 }
880                 ldap_pvt_thread_yield();
881         }
882
883         if( slapd_shutdown > 0 ) {
884                 Debug( LDAP_DEBUG_TRACE,
885                         "daemon: shutdown requested and initiated.\n",
886                         0, 0, 0 );
887
888         } else if ( slapd_shutdown < 0 ) {
889                 Debug( LDAP_DEBUG_TRACE,
890                         "daemon: abnormal condition, shutdown initiated.\n",
891                         0, 0, 0 );
892         } else {
893                 Debug( LDAP_DEBUG_TRACE,
894                         "daemon: no active streams, shutdown initiated.\n",
895                         0, 0, 0 );
896         }
897
898         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
899                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
900                         slapd_close( slap_listeners[l]->sl_sd );
901                         break;
902                 }
903         }
904
905         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
906         Debug( LDAP_DEBUG_ANY,
907             "slapd shutdown: waiting for %d threads to terminate\n",
908             active_threads, 0, 0 );
909         while ( active_threads > 0 ) {
910                 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
911         }
912         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
913
914         return NULL;
915 }
916
917
918 int slapd_daemon( void )
919 {
920         int rc;
921
922         connections_init();
923
924 #define SLAPD_LISTENER_THREAD 1
925 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
926
927         /* listener as a separate THREAD */
928         rc = ldap_pvt_thread_create( &listener_tid,
929                 0, slapd_daemon_task, NULL );
930
931         if ( rc != 0 ) {
932                 Debug( LDAP_DEBUG_ANY,
933                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
934                 return rc;
935         }
936
937         /* wait for the listener thread to complete */
938         ldap_pvt_thread_join( listener_tid, (void *) NULL );
939 #else
940         /* expermimental code */
941         listener_tid = pthread_self();
942         slapd_daemon_task( NULL );
943 #endif
944
945         return 0;
946
947 }
948
949 #ifdef HAVE_WINSOCK2
950 int sockinit(void)
951 {
952     WORD wVersionRequested;
953         WSADATA wsaData;
954         int err;
955  
956         wVersionRequested = MAKEWORD( 2, 0 );
957  
958         err = WSAStartup( wVersionRequested, &wsaData );
959         if ( err != 0 ) {
960                 /* Tell the user that we couldn't find a usable */
961                 /* WinSock DLL.                                  */
962                 return -1;
963         }
964  
965         /* Confirm that the WinSock DLL supports 2.0.*/
966         /* Note that if the DLL supports versions greater    */
967         /* than 2.0 in addition to 2.0, it will still return */
968         /* 2.0 in wVersion since that is the version we      */
969         /* requested.                                        */
970  
971         if ( LOBYTE( wsaData.wVersion ) != 2 ||
972                 HIBYTE( wsaData.wVersion ) != 0 )
973         {
974             /* Tell the user that we couldn't find a usable */
975             /* WinSock DLL.                                  */
976             WSACleanup();
977             return -1; 
978         }
979
980         /* The WinSock DLL is acceptable. Proceed. */
981         return 0;
982 }
983
984 int sockdestroy(void)
985 {
986         WSACleanup();
987         return 0;
988 }
989
990 void hit_socket(void)
991 {
992         ber_socket_t s;
993         int on = 1;
994         extern struct sockaddr_in       bind_addr;
995
996         /* throw something at the socket to terminate the select() in the daemon thread. */
997         if (( s = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID )
998                 Debug( LDAP_DEBUG_ANY,
999                         "slap_set_shutdown: socket failed\n\tWSAGetLastError=%d (%s)\n",
1000                         WSAGetLastError(), WSAGetLastErrorString(), 0 );
1001
1002         if ( ioctlsocket( s, FIONBIO, &on ) == -1 ) 
1003                 Debug( LDAP_DEBUG_ANY,
1004                         "slap_set_shutdown:FIONBIO ioctl on %d faled\n\tWSAGetLastError=%d (%s)\n",
1005                         s, WSAGetLastError(), WSAGetLastError() );
1006         
1007         bind_addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
1008
1009         if ( connect( s, (struct sockaddr *)&bind_addr, sizeof( struct sockaddr_in )) == SOCKET_ERROR ) {
1010                 Debug( LDAP_DEBUG_ANY,
1011                         "hit_socket: error on connect: %d\n",
1012                         WSAGetLastError(), 0, 0 );
1013                 /* we can probably expect some error to occur here, mostly WSAEWOULDBLOCK */
1014         }
1015
1016         tcp_close(s);
1017 }
1018
1019 #elif HAVE_WINSOCK
1020 static int sockinit(void)
1021 {       WSADATA wsaData;
1022         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1023             return -1;
1024         }
1025         return 0;
1026 }
1027 static int sockdestroy(void)
1028 {
1029         WSACleanup();
1030         return 0;
1031 }
1032
1033 #else
1034 static int sockinit(void)
1035 {
1036         return 0;
1037 }
1038 static int sockdestroy(void)
1039 {
1040         return 0;
1041 }
1042 #endif
1043
1044 void
1045 slap_set_shutdown( int sig )
1046 {
1047         int l;
1048         slapd_shutdown = sig;
1049 #ifndef HAVE_WINSOCK
1050         if(slapd_listener) {
1051                 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
1052         }
1053 #else
1054         /* trying to "hit" the socket seems to always get a */
1055         /* EWOULDBLOCK error, so just close the listen socket to */
1056         /* break out of the select since we're shutting down anyway */
1057         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1058                 if ( slap_listeners[l]->sl_sd >= 0 ) {
1059                         tcp_close( slap_listeners[l]->sl_sd );
1060                 }
1061         }
1062 #endif
1063         /* reinstall self */
1064         (void) SIGNAL( sig, slap_set_shutdown );
1065 }
1066
1067 void
1068 slap_do_nothing( int sig )
1069 {
1070         /* reinstall self */
1071         (void) SIGNAL( sig, slap_do_nothing );
1072 }