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