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