]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
3e71735c11eae539dda2c9a2db78983e7d172298
[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 "ldap_pvt_thread.h"
21 #include "lutil.h"
22 #include "slap.h"
23
24 #ifdef HAVE_TCPD
25 #include <tcpd.h>
26
27 int allow_severity = LOG_INFO;
28 int deny_severity = LOG_NOTICE;
29 #endif /* TCP Wrappers */
30
31 #ifdef LDAP_PF_LOCAL
32 #include <sys/stat.h>
33 #endif /* LDAP_PF_LOCAL */
34
35 /* globals */
36 time_t starttime;
37 ber_socket_t dtblsize;
38
39 typedef struct slap_listener {
40         char* sl_url;
41         char* sl_name;
42 #ifdef HAVE_TLS
43         int             sl_is_tls;
44 #endif
45 #ifdef LDAP_CONNECTIONLESS
46         int     sl_is_udp;              /* UDP listener is also data port */
47 #endif
48         ber_socket_t            sl_sd;
49         Sockaddr sl_sa;
50 #define sl_addr sl_sa.sa_in_addr
51 } Listener;
52
53 Listener **slap_listeners = NULL;
54
55 #define SLAPD_LISTEN 10
56
57 static ber_socket_t wake_sds[2];
58
59 #ifdef NO_THREADS
60 static int waking;
61 #define WAKE_LISTENER(w) \
62 ((w && !waking) ? tcp_write( wake_sds[1], "0", 1 ), waking=1 : 0)
63 #else
64 #define WAKE_LISTENER(w) \
65 do { if (w) tcp_write( wake_sds[1], "0", 1 ); } while(0)
66 #endif
67
68 #ifndef HAVE_WINSOCK
69 static
70 #endif
71 volatile sig_atomic_t slapd_shutdown = 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
91 #ifdef HAVE_SLP
92 /*
93  * SLP related functions
94  */
95 #include <slp.h>
96
97 #define LDAP_SRVTYPE_PREFIX "service:ldap://"
98 #define LDAPS_SRVTYPE_PREFIX "service:ldaps://"
99 static char** slapd_srvurls = NULL;
100 static SLPHandle slapd_hslp = 0;
101
102 void slapd_slp_init( const char* urls ) {
103         int i;
104
105         slapd_srvurls = str2charray( urls, " " );
106
107         if( slapd_srvurls == NULL ) return;
108
109         /* find and expand INADDR_ANY URLs */
110         for( i=0; slapd_srvurls[i] != NULL; i++ ) {
111                 if( strcmp( slapd_srvurls[i], "ldap:///" ) == 0) {
112                         char *host = ldap_pvt_get_fqdn( NULL );
113                         if ( host != NULL ) {
114                                 slapd_srvurls[i] = (char *) realloc( slapd_srvurls[i],
115                                         strlen( host ) +
116                                         sizeof( LDAP_SRVTYPE_PREFIX ) );
117                                 strcpy( slapd_srvurls[i], LDAP_SRVTYPE_PREFIX );
118                                 strcat( slapd_srvurls[i], host );
119
120                                 ch_free( host );
121                         }
122
123                 } else if ( strcmp( slapd_srvurls[i], "ldaps:///" ) == 0) {
124                         char *host = ldap_pvt_get_fqdn( NULL );
125                         if ( host != NULL ) {
126                                 slapd_srvurls[i] = (char *) realloc( slapd_srvurls[i],
127                                         strlen( host ) +
128                                         sizeof( LDAPS_SRVTYPE_PREFIX ) );
129                                 strcpy( slapd_srvurls[i], LDAPS_SRVTYPE_PREFIX );
130                                 strcat( slapd_srvurls[i], host );
131
132                                 ch_free( host );
133                         }
134                 }
135         }
136
137         /* open the SLP handle */
138         SLPOpen( "en", 0, &slapd_hslp );
139 }
140
141 void slapd_slp_deinit() {
142         if( slapd_srvurls == NULL ) return;
143
144         charray_free( slapd_srvurls );
145         slapd_srvurls = NULL;
146
147         /* close the SLP handle */
148         SLPClose( slapd_hslp );
149 }
150
151 void slapd_slp_regreport(
152         SLPHandle hslp,
153         SLPError errcode,
154         void* cookie )
155 {
156         /* empty report */
157 }
158
159 void slapd_slp_reg() {
160         int i;
161
162         for( i=0; slapd_srvurls[i] != NULL; i++ ) {
163                 if( strncmp( slapd_srvurls[i], LDAP_SRVTYPE_PREFIX,
164                                 sizeof( LDAP_SRVTYPE_PREFIX ) - 1 ) == 0 ||
165                     strncmp( slapd_srvurls[i], LDAPS_SRVTYPE_PREFIX,
166                                 sizeof( LDAPS_SRVTYPE_PREFIX ) - 1 ) == 0 )
167                 {
168                         SLPReg( slapd_hslp,
169                                 slapd_srvurls[i],
170                                 SLP_LIFETIME_MAXIMUM,
171                                 "ldap",
172                                 "",
173                                 1,
174                                 slapd_slp_regreport,
175                                 NULL );
176                 }
177         }
178 }
179
180 void slapd_slp_dereg() {
181         int i;
182
183         for( i=0; slapd_srvurls[i] != NULL; i++ ) {
184                 SLPDereg( slapd_hslp,
185                         slapd_srvurls[i],
186                         slapd_slp_regreport,
187                         NULL );
188         }
189 }
190 #endif /* HAVE_SLP */
191
192 /*
193  * Add a descriptor to daemon control
194  */
195 static void slapd_add(ber_socket_t s) {
196         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
197
198         assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
199         assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
200         assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
201
202 #ifndef HAVE_WINSOCK
203         if (s >= slap_daemon.sd_nfds) {
204                 slap_daemon.sd_nfds = s + 1;
205         }
206 #endif
207
208         FD_SET( s, &slap_daemon.sd_actives );
209         FD_SET( s, &slap_daemon.sd_readers );
210
211 #ifdef NEW_LOGGING
212         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
213                    "slapd_add: added %ld%s%s\n",
214                    (long)s,
215                    FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
216                    FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" ));
217 #else
218         Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
219                 (long) s,
220             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
221                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
222 #endif
223         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
224 }
225
226 /*
227  * Remove the descriptor from daemon control
228  */
229 void slapd_remove(ber_socket_t s, int wake) {
230         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
231
232 #ifdef NEW_LOGGING
233         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
234                    "slapd_remove: removing %ld%s%s\n",
235                    (long) s,
236                    FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
237                    FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : ""  ));
238 #else
239         Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
240                 (long) s,
241             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
242                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
243 #endif
244         FD_CLR( s, &slap_daemon.sd_actives );
245         FD_CLR( s, &slap_daemon.sd_readers );
246         FD_CLR( s, &slap_daemon.sd_writers );
247
248         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
249         WAKE_LISTENER(wake);
250 }
251
252 void slapd_clr_write(ber_socket_t s, int wake) {
253         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
254
255         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
256         FD_CLR( s, &slap_daemon.sd_writers );
257
258         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
259         WAKE_LISTENER(wake);
260 }
261
262 void slapd_set_write(ber_socket_t s, int wake) {
263         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
264
265         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
266         if (!FD_ISSET(s, &slap_daemon.sd_writers))
267             FD_SET( (unsigned) s, &slap_daemon.sd_writers );
268
269         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
270         WAKE_LISTENER(wake);
271 }
272
273 void slapd_clr_read(ber_socket_t s, int wake) {
274         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
275
276         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
277         FD_CLR( s, &slap_daemon.sd_readers );
278
279         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
280         WAKE_LISTENER(wake);
281 }
282
283 void slapd_set_read(ber_socket_t s, int wake) {
284         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
285
286         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
287         if (!FD_ISSET(s, &slap_daemon.sd_readers))
288             FD_SET( s, &slap_daemon.sd_readers );
289
290         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
291         WAKE_LISTENER(wake);
292 }
293
294 static void slapd_close(ber_socket_t s) {
295 #ifdef NEW_LOGGING
296         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
297                    "slapd_close: closing %ld\n", (long)s ));
298 #else
299         Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
300                 (long) s, 0, 0 );
301 #endif
302         tcp_close(s);
303 }
304
305 static void slap_free_listener_addresses(struct sockaddr **sal)
306 {
307         struct sockaddr **sap;
308
309         if (sal == NULL) {
310                 return;
311         }
312
313         for (sap = sal; *sap != NULL; sap++) {
314                 ch_free(*sap);
315         }
316
317         ch_free(sal);
318 }
319
320 /* port = 0 indicates AF_LOCAL */
321 static int slap_get_listener_addresses(
322         const char *host,
323         unsigned short port,
324         struct sockaddr ***sal)
325 {
326         struct sockaddr **sap;
327
328 #ifdef LDAP_PF_LOCAL
329         if ( port == 0 ) {
330                 *sal = ch_malloc(2 * sizeof(void *));
331                 if (*sal == NULL) {
332                         return -1;
333                 }
334
335                 sap = *sal;
336                 *sap = ch_malloc(sizeof(struct sockaddr_un));
337                 if (*sap == NULL)
338                         goto errexit;
339                 sap[1] = NULL;
340
341                 if ( strlen(host) >
342                      (sizeof(((struct sockaddr_un *)*sap)->sun_path) - 1) ) {
343 #ifdef NEW_LOGGING
344                         LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
345                                    "slap_get_listener_addresses: domain socket path (%s) too long in URL\n",
346                                    host ));
347 #else
348                         Debug( LDAP_DEBUG_ANY,
349                                "daemon: domain socket path (%s) too long in URL",
350                                host, 0, 0);
351 #endif
352                         goto errexit;
353                 }
354
355                 (void)memset( (void *)*sap, '\0', sizeof(struct sockaddr_un) );
356                 (*sap)->sa_family = AF_LOCAL;
357                 strcpy( ((struct sockaddr_un *)*sap)->sun_path, host );
358         } else
359 #endif
360         {
361 #ifdef HAVE_GETADDRINFO
362                 struct addrinfo hints, *res, *sai;
363                 int n, err;
364                 char serv[7];
365
366                 memset( &hints, '\0', sizeof(hints) );
367                 hints.ai_flags = AI_PASSIVE;
368                 hints.ai_socktype = SOCK_STREAM;
369                 hints.ai_family = AF_UNSPEC;
370                 snprintf(serv, sizeof serv, "%d", port);
371
372                 if ( (err = getaddrinfo(host, serv, &hints, &res)) ) {
373 #ifdef NEW_LOGGING
374                         LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
375                                    "slap_get_listener_addresses: getaddrinfo failed: %s\n",
376                                    AC_GAI_STRERROR(err) ));
377 #else
378                         Debug( LDAP_DEBUG_ANY, "daemon: getaddrinfo failed: %s\n",
379                                 AC_GAI_STRERROR(err), 0, 0);
380 #endif
381                         return -1;
382                 }
383
384                 sai = res;
385                 for (n=2; (sai = sai->ai_next) != NULL; n++) {
386                         /* EMPTY */ ;
387                 }
388                 *sal = ch_calloc(n, sizeof(void *));
389                 if (*sal == NULL) {
390                         return -1;
391                 }
392
393                 sap = *sal;
394                 *sap = NULL;
395
396                 for ( sai=res; sai; sai=sai->ai_next ) {
397                         if( sai->ai_addr == NULL ) {
398 #ifdef NEW_LOGGING
399                                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
400                                         "slap_get_listener_addresses: "
401                                         "getaddrinfo ai_addr is NULL?\n" ));
402 #else
403                                 Debug( LDAP_DEBUG_ANY, "slap_get_listener_addresses: "
404                                         "getaddrinfo ai_addr is NULL?\n", 0, 0, 0 );
405 #endif
406                                 freeaddrinfo(res);
407                                 goto errexit;
408                         }
409
410                         switch (sai->ai_family) {
411 #  ifdef LDAP_PF_INET6
412                         case AF_INET6:
413                                 *sap = ch_malloc(sizeof(struct sockaddr_in6));
414                                 if (*sap == NULL) {
415                                         freeaddrinfo(res);
416                                         goto errexit;
417                                 }
418                                 *(struct sockaddr_in6 *)*sap =
419                                         *((struct sockaddr_in6 *)sai->ai_addr);
420                                 break;
421 #  endif
422                         case AF_INET:
423                                 *sap = ch_malloc(sizeof(struct sockaddr_in));
424                                 if (*sap == NULL) {
425                                         freeaddrinfo(res);
426                                         goto errexit;
427                                 }
428                                 *(struct sockaddr_in *)*sap =
429                                         *((struct sockaddr_in *)sai->ai_addr);
430                                 break;
431                         default:
432                                 *sap = NULL;
433                                 break;
434                         }
435
436                         if (*sap != NULL) {
437                                 (*sap)->sa_family = sai->ai_family;
438                                 sap++;
439                                 *sap = NULL;
440                         }
441                 }
442
443                 freeaddrinfo(res);
444 #else
445                 struct in_addr in;
446
447                 if ( host == NULL ) {
448                         in.s_addr = htonl(INADDR_ANY);
449
450                 } else if ( !inet_aton( host, &in ) ) {
451                         struct hostent *he = gethostbyname( host );
452                         if( he == NULL ) {
453 #ifdef NEW_LOGGING
454                                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
455                                            "slap_get_listener_addresses: invalid host %s\n",
456                                            host ));
457 #else
458                                 Debug( LDAP_DEBUG_ANY,
459                                        "daemon: invalid host %s", host, 0, 0);
460 #endif
461                                 return -1;
462                         }
463                         AC_MEMCPY( &in, he->h_addr, sizeof( in ) );
464                 }
465
466                 *sal = ch_malloc(2 * sizeof(void *));
467                 if (*sal == NULL) {
468                         return -1;
469                 }
470
471                 sap = *sal;
472                 *sap = ch_malloc(sizeof(struct sockaddr_in));
473                 if (*sap == NULL) {
474                         goto errexit;
475                 }
476                 sap[1] = NULL;
477
478                 (void)memset( (void *)*sap, '\0', sizeof(struct sockaddr_in) );
479                 (*sap)->sa_family = AF_INET;
480                 ((struct sockaddr_in *)*sap)->sin_port = htons(port);
481                 ((struct sockaddr_in *)*sap)->sin_addr = in;
482 #endif
483         }
484
485         return 0;
486
487 errexit:
488         slap_free_listener_addresses(*sal);
489         return -1;
490 }
491
492 static Listener * slap_open_listener(
493         const char* url )
494 {
495         int     tmp, rc;
496         Listener l;
497         Listener *li;
498         LDAPURLDesc *lud;
499         unsigned short port;
500         int err, addrlen = 0;
501         struct sockaddr **sal, **psal;
502         int socktype = SOCK_STREAM;     /* default to COTS */
503
504         rc = ldap_url_parse( url, &lud );
505
506         if( rc != LDAP_URL_SUCCESS ) {
507 #ifdef NEW_LOGGING
508                 LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
509                            "slap_open_listener: listen URL \"%s\" parse error %d\n",
510                            url, rc ));
511 #else
512                 Debug( LDAP_DEBUG_ANY,
513                         "daemon: listen URL \"%s\" parse error=%d\n",
514                         url, rc, 0 );
515 #endif
516                 return NULL;
517         }
518
519 #ifndef HAVE_TLS
520         if( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
521 #ifdef NEW_LOGGING
522                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
523                            "slap_open_listener: TLS is not supported (%s)\n",
524                            url ));
525 #else
526                 Debug( LDAP_DEBUG_ANY,
527                         "daemon: TLS not supported (%s)\n",
528                         url, 0, 0 );
529 #endif
530                 ldap_free_urldesc( lud );
531                 return NULL;
532         }
533
534         if(! lud->lud_port ) {
535                 lud->lud_port = LDAP_PORT;
536         }
537
538 #else
539         l.sl_is_tls = ldap_pvt_url_scheme2tls( lud->lud_scheme );
540
541         if(! lud->lud_port ) {
542                 lud->lud_port = l.sl_is_tls ? LDAPS_PORT : LDAP_PORT;
543         }
544 #endif
545
546         port = (unsigned short) lud->lud_port;
547
548         tmp = ldap_pvt_url_scheme2proto(lud->lud_scheme);
549         if ( tmp == LDAP_PROTO_IPC ) {
550 #ifdef LDAP_PF_LOCAL
551                 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
552                         err = slap_get_listener_addresses(LDAPI_SOCK, 0, &sal);
553                 } else {
554                         err = slap_get_listener_addresses(lud->lud_host, 0, &sal);
555                 }
556 #else
557
558 #ifdef NEW_LOGGING
559                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
560                            "slap_open_listener: URL scheme is not supported: %s\n",
561                            url ));
562 #else
563                 Debug( LDAP_DEBUG_ANY, "daemon: URL scheme not supported: %s",
564                         url, 0, 0);
565 #endif
566                 ldap_free_urldesc( lud );
567                 return NULL;
568 #endif
569         } else {
570 #ifdef LDAP_CONNECTIONLESS
571                 l.sl_is_udp = ( tmp == LDAP_PROTO_UDP );
572 #endif
573                 if( lud->lud_host == NULL || lud->lud_host[0] == '\0'
574                         || strcmp(lud->lud_host, "*") == 0 )
575                 {
576                         err = slap_get_listener_addresses(NULL, port, &sal);
577                 } else {
578                         err = slap_get_listener_addresses(lud->lud_host, port, &sal);
579                 }
580         }
581
582         ldap_free_urldesc( lud );
583         if ( err ) {
584                 return NULL;
585         }
586
587         psal = sal;
588         while ( *sal != NULL ) {
589                 switch( (*sal)->sa_family ) {
590                 case AF_INET:
591 #ifdef LDAP_PF_INET6
592                 case AF_INET6:
593 #endif
594 #ifdef LDAP_PF_LOCAL
595                 case AF_LOCAL:
596 #endif
597                         break;
598                 default:
599                         sal++;
600                         continue;
601                 }
602 #ifdef LDAP_CONNECTIONLESS
603                 if (l.sl_is_udp)
604                     socktype = SOCK_DGRAM;
605 #endif
606                 l.sl_sd = socket( (*sal)->sa_family, socktype, 0);
607                 if ( l.sl_sd == AC_SOCKET_INVALID ) {
608                         int err = sock_errno();
609 #ifdef NEW_LOGGING
610                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
611                                    "slap_open_listener: socket() failed errno=%d (%s)\n",
612                                    err, sock_errstr(err) ));
613 #else
614                         Debug( LDAP_DEBUG_ANY,
615                                 "daemon: socket() failed errno=%d (%s)\n", err,
616                                 sock_errstr(err), 0 );
617 #endif
618                         sal++;
619                         continue;
620                 }
621 #ifndef HAVE_WINSOCK
622                 if ( l.sl_sd >= dtblsize ) {
623 #ifdef NEW_LOGGING
624                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
625                                    "slap_open_listener: listener descriptor %ld is too great %ld\n",
626                                    (long)l.sl_sd, (long)dtblsize ));
627 #else
628                         Debug( LDAP_DEBUG_ANY,
629                                "daemon: listener descriptor %ld is too great %ld\n",
630                                (long) l.sl_sd, (long) dtblsize, 0 );
631 #endif
632                         tcp_close( l.sl_sd );
633                         sal++;
634                         continue;
635                 }
636 #endif
637 #ifdef LDAP_PF_LOCAL
638                 if ( (*sal)->sa_family == AF_LOCAL ) {
639                         unlink ( ((struct sockaddr_un *)*sal)->sun_path );
640                 } else
641 #endif
642                 {
643 #ifdef SO_REUSEADDR
644                         /* enable address reuse */
645                         tmp = 1;
646                         rc = setsockopt( l.sl_sd, SOL_SOCKET, SO_REUSEADDR,
647                                          (char *) &tmp, sizeof(tmp) );
648                         if ( rc == AC_SOCKET_ERROR ) {
649                                 int err = sock_errno();
650 #ifdef NEW_LOGGING
651                                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
652                                            "slap_open_listener: setsockopt( %ld, SO_REUSEADDR ) failed errno %d (%s)\n",
653                                            (long)l.sl_sd, err, sock_errstr(err) ));
654 #else
655                                 Debug( LDAP_DEBUG_ANY,
656                                        "slapd(%ld): setsockopt(SO_REUSEADDR) failed errno=%d (%s)\n",
657                                        (long) l.sl_sd, err, sock_errstr(err) );
658 #endif
659                         }
660 #endif
661                 }
662
663                 switch( (*sal)->sa_family ) {
664                 case AF_INET:
665                         addrlen = sizeof(struct sockaddr_in);
666                         break;
667 #ifdef LDAP_PF_INET6
668                 case AF_INET6:
669                         addrlen = sizeof(struct sockaddr_in6);
670                         break;
671 #endif
672 #ifdef LDAP_PF_LOCAL
673                 case AF_LOCAL:
674                         addrlen = sizeof(struct sockaddr_un);
675                         break;
676 #endif
677                 }
678
679                 if (!bind(l.sl_sd, *sal, addrlen))
680                         break;
681                 err = sock_errno();
682 #ifdef NEW_LOGGING
683                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
684                            "slap_open_listener: bind(%ld) failed errno=%d (%s)\n",
685                            (long)l.sl_sd, err, sock_errstr(err) ));
686 #else
687                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno=%d (%s)\n",
688                        (long) l.sl_sd, err, sock_errstr(err) );
689 #endif
690                 tcp_close( l.sl_sd );
691                 sal++;
692         } /* while ( *sal != NULL ) */
693
694         if ( *sal == NULL ) {
695 #ifdef NEW_LOGGING
696                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
697                            "slap_open_listener: bind(%ld) failed.\n", (long)l.sl_sd ));
698 #else
699                 Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed\n",
700                         (long) l.sl_sd, 0, 0 );
701 #endif
702                 slap_free_listener_addresses(psal);
703                 return NULL;
704         }
705
706         switch ( (*sal)->sa_family ) {
707 #ifdef LDAP_PF_LOCAL
708         case AF_LOCAL: {
709                 char *addr = ((struct sockaddr_un *)*sal)->sun_path;
710                 if ( chmod( addr, S_IRWXU ) < 0 ) {
711                         int err = sock_errno();
712 #ifdef NEW_LOGGING
713                         LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
714                                    "slap_open_listener: fchmod(%ld) failed errno=%d (%s)\n",
715                                    (long)l.sl_sd, err, sock_errstr(err) ));
716 #else
717                         Debug( LDAP_DEBUG_ANY, "daemon: fchmod(%ld) failed errno=%d (%s)",
718                                (long) l.sl_sd, err, sock_errstr(err) );
719 #endif
720                         tcp_close( l.sl_sd );
721                         slap_free_listener_addresses(psal);
722                         return NULL;
723                 }
724                 l.sl_name = ch_malloc( strlen(addr) + sizeof("PATH=") );
725                 sprintf( l.sl_name, "PATH=%s", addr );
726         } break;
727 #endif /* LDAP_PF_LOCAL */
728
729         case AF_INET: {
730                 char *s;
731 #if defined( HAVE_GETADDRINFO ) && defined( HAVE_INET_NTOP )
732                 char addr[INET_ADDRSTRLEN];
733                 inet_ntop( AF_INET, &((struct sockaddr_in *)*sal)->sin_addr,
734                            addr, sizeof(addr) );
735                 s = addr;
736                 port = ((struct sockaddr_in *)*sal) ->sin_port;
737 #else
738                 s = inet_ntoa( l.sl_addr.sin_addr );
739                 port = l.sl_addr.sin_port;
740 #endif
741                 l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65535") );
742                 sprintf( l.sl_name, "IP=%s:%d",
743                          s != NULL ? s : "unknown" , port );
744         } break;
745
746 #ifdef LDAP_PF_INET6
747         case AF_INET6: {
748                 char addr[INET6_ADDRSTRLEN];
749                 inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
750                            addr, sizeof addr);
751                 port = ((struct sockaddr_in6 *)*sal)->sin6_port;
752                 l.sl_name = ch_malloc( strlen(addr) + sizeof("IP= 65535") );
753                 sprintf( l.sl_name, "IP=%s %d", addr, port );
754         } break;
755 #endif /* LDAP_PF_INET6 */
756
757         default:
758 #ifdef NEW_LOGGING
759                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
760                            "slap_open_listener: unsupported address family (%d)\n",
761                            (int)(*sal)->sa_family ));
762 #else
763                 Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
764                         (int) (*sal)->sa_family, 0, 0 );
765 #endif
766                 break;
767         }
768
769         slap_free_listener_addresses(psal);
770
771         l.sl_url = ch_strdup( url );
772         li = ch_malloc( sizeof( Listener ) );
773         *li = l;
774
775 #ifdef NEW_LOGGING
776         LDAP_LOG(( "connection", LDAP_LEVEL_RESULTS,
777                    "slap_open_listener: daemon initialzed %s\n", l.sl_url ));
778 #else
779         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
780                 l.sl_url, 0, 0 );
781 #endif
782         return li;
783 }
784
785 static int sockinit(void);
786 static int sockdestroy(void);
787
788 int slapd_daemon_init( const char *urls )
789 {
790         int i, rc;
791         char **u;
792
793 #ifdef NEW_LOGGING
794         LDAP_LOG(( "connection", LDAP_LEVEL_ARGS,
795                    "slapd_daemon_init: %s\n",
796                    urls ? urls : "<null>" ));
797 #else
798         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
799                 urls ? urls : "<null>", 0, 0 );
800 #endif
801         if( (rc = sockinit()) != 0 ) {
802                 return rc;
803         }
804
805 #ifdef HAVE_SYSCONF
806         dtblsize = sysconf( _SC_OPEN_MAX );
807 #elif HAVE_GETDTABLESIZE
808         dtblsize = getdtablesize();
809 #else
810         dtblsize = FD_SETSIZE;
811 #endif
812
813 #ifdef FD_SETSIZE
814         if(dtblsize > FD_SETSIZE) {
815                 dtblsize = FD_SETSIZE;
816         }
817 #endif  /* !FD_SETSIZE */
818
819         /* open a pipe (or something equivalent connected to itself).
820          * we write a byte on this fd whenever we catch a signal. The main
821          * loop will be select'ing on this socket, and will wake up when
822          * this byte arrives.
823          */
824         if( (rc = lutil_pair( wake_sds )) < 0 ) {
825 #ifdef NEW_LOGGING
826                 LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
827                            "slap_daemon_init: lutil_pair() failed rc=%d\n", rc ));
828 #else
829                 Debug( LDAP_DEBUG_ANY,
830                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
831 #endif
832                 return rc;
833         }
834
835         FD_ZERO( &slap_daemon.sd_readers );
836         FD_ZERO( &slap_daemon.sd_writers );
837
838         if( urls == NULL ) {
839                 urls = "ldap:///";
840         }
841
842         u = str2charray( urls, " " );
843
844         if( u == NULL || u[0] == NULL ) {
845 #ifdef NEW_LOGGING
846                 LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
847                            "slap_daemon_init: no urls (%s) provided.\n", urls ));
848 #else
849                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
850                         urls, 0, 0 );
851 #endif
852                 return -1;
853         }
854
855         for( i=0; u[i] != NULL; i++ ) {
856 #ifdef NEW_LOGGING
857                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
858                            "slap_daemon_init: listen on %s\n.", u[i] ));
859 #else
860                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
861                         u[i], 0, 0 );
862 #endif
863         }
864
865         if( i == 0 ) {
866 #ifdef NEW_LOGGING
867                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
868                            "slap_daemon_init: no listeners to open (%s)\n", urls ));
869 #else
870                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
871                         urls, 0, 0 );
872 #endif
873                 charray_free( u );
874                 return -1;
875         }
876
877 #ifdef NEW_LOGGING
878         LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
879                    "slap_daemon_init: %d listeners to open...\n", i ));
880 #else
881         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
882                 i, 0, 0 );
883 #endif
884         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
885
886         for(i = 0; u[i] != NULL; i++ ) {
887                 slap_listeners[i] = slap_open_listener( u[i] );
888
889                 if( slap_listeners[i] == NULL ) {
890                         charray_free( u );
891                         return -1;
892                 }
893         }
894         slap_listeners[i] = NULL;
895
896 #ifdef NEW_LOGGING
897         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
898                    "slap_daemon_init: %d listeners opened\n", i ));
899 #else
900         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
901                 i, 0, 0 );
902 #endif
903
904 #ifdef HAVE_SLP
905         slapd_slp_init( urls );
906         slapd_slp_reg();
907 #endif
908
909         charray_free( u );
910         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
911         return !i;
912 }
913
914
915 int
916 slapd_daemon_destroy(void)
917 {
918         connections_destroy();
919         tcp_close( wake_sds[1] );
920         tcp_close( wake_sds[0] );
921         sockdestroy();
922
923 #ifdef HAVE_SLP
924         slapd_slp_dereg();
925         slapd_slp_deinit();
926 #endif
927
928         return 0;
929 }
930
931
932 static void *
933 slapd_daemon_task(
934         void *ptr
935 )
936 {
937         int l;
938         time_t  last_idle_check = 0;
939         time( &starttime );
940
941         if ( global_idletimeout > 0 ) {
942                 last_idle_check = slap_get_time();
943         }
944         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
945                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
946                         continue;
947 #ifdef LDAP_CONNECTIONLESS
948                 /* Since this is connectionless, the data port is the
949                  * listening port. The listen() and accept() calls
950                  * are unnecessary.
951                  */
952                 if ( slap_listeners[l]->sl_is_udp )
953                 {
954                         slapd_add( slap_listeners[l]->sl_sd );
955                         continue;
956                 }
957 #endif
958
959                 if ( listen( slap_listeners[l]->sl_sd, SLAPD_LISTEN ) == -1 ) {
960                         int err = sock_errno();
961 #ifdef NEW_LOGGING
962                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
963                                    "slapd_daemon_task: listen( %s, 5 ) failed errno=%d (%s)\n",
964                                    slap_listeners[l]->sl_url, err, sock_errstr(err) ));
965 #else
966                         Debug( LDAP_DEBUG_ANY,
967                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
968                                         slap_listeners[l]->sl_url, err,
969                                         sock_errstr(err) );
970 #endif
971                         return( (void*)-1 );
972                 }
973
974                 slapd_add( slap_listeners[l]->sl_sd );
975         }
976
977 #ifdef HAVE_NT_SERVICE_MANAGER
978         if ( started_event != NULL ) {
979                 ldap_pvt_thread_cond_signal( &started_event );
980         }
981 #endif
982         /* initialization complete. Here comes the loop. */
983
984         while ( !slapd_shutdown ) {
985                 ber_socket_t i;
986                 int ns;
987                 int at;
988                 ber_socket_t nfds;
989 #define SLAPD_EBADF_LIMIT 16
990                 int ebadf = 0;
991                 int emfile = 0;
992
993 #define SLAPD_IDLE_CHECK_LIMIT 4
994                 time_t  now;
995
996
997                 fd_set                  readfds;
998                 fd_set                  writefds;
999                 Sockaddr                from;
1000
1001 #if defined(SLAPD_RLOOKUPS)
1002                 struct hostent          *hp;
1003 #endif
1004                 struct timeval          zero;
1005                 struct timeval          *tvp;
1006
1007                 if( emfile ) {
1008                         now = slap_get_time();
1009                         connections_timeout_idle( now );
1010                 }
1011                 else if ( global_idletimeout > 0 ) {
1012                         now = slap_get_time();
1013                         if ( difftime( last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) {
1014                                 connections_timeout_idle( now );
1015                         }
1016                 }
1017
1018                 FD_ZERO( &writefds );
1019                 FD_ZERO( &readfds );
1020
1021                 zero.tv_sec = 0;
1022                 zero.tv_usec = 0;
1023
1024                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
1025
1026 #ifdef FD_SET_MANUAL_COPY
1027                 for( s = 0; s < nfds; s++ ) {
1028                         if(FD_ISSET( &slap_sd_readers, s )) {
1029                                 FD_SET( s, &readfds );
1030                         }
1031                         if(FD_ISSET( &slap_sd_writers, s )) {
1032                                 FD_SET( s, &writefds );
1033                         }
1034                 }
1035 #else
1036                 AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
1037                 AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
1038 #endif
1039                 assert(!FD_ISSET(wake_sds[0], &readfds));
1040                 FD_SET( wake_sds[0], &readfds );
1041
1042                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1043                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1044                                 continue;
1045                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
1046                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
1047                 }
1048
1049 #ifndef HAVE_WINSOCK
1050                 nfds = slap_daemon.sd_nfds;
1051 #else
1052                 nfds = dtblsize;
1053 #endif
1054
1055                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
1056
1057                 at = ldap_pvt_thread_pool_backload(&connection_pool);
1058
1059 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
1060                 tvp = NULL;
1061 #else
1062                 tvp = at ? &zero : NULL;
1063 #endif
1064
1065                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1066                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1067                                 continue;
1068
1069 #ifdef NEW_LOGGING
1070                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
1071                                    "slapd_daemon_task: select: listen=%d active_threads=%d tvp=%s\n",
1072                                    slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "zero" ));
1073 #else
1074                         Debug( LDAP_DEBUG_CONNS,
1075                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
1076                                         slap_listeners[l]->sl_sd, at,
1077                                         tvp == NULL ? "NULL" : "zero" );
1078 #endif
1079                 }
1080
1081                 switch(ns = select( nfds, &readfds,
1082 #ifdef HAVE_WINSOCK
1083                         /* don't pass empty fd_set */
1084                         ( writefds.fd_count > 0 ? &writefds : NULL ),
1085 #else
1086                         &writefds,
1087 #endif
1088                         NULL, tvp ))
1089                 {
1090                 case -1: {      /* failure - try again */
1091                                 int err = sock_errno();
1092
1093                                 if( err == EBADF
1094 #ifdef WSAENOTSOCK
1095                                         /* you'd think this would be EBADF */
1096                                         || err == WSAENOTSOCK
1097 #endif
1098                                 ) {
1099                                         if (++ebadf < SLAPD_EBADF_LIMIT)
1100                                                 continue;
1101                                 }
1102
1103                                 if( err != EINTR ) {
1104 #ifdef NEW_LOGGING
1105                                         LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
1106                                                    "slapd_daemon_task: select failed (%d): %s\n",
1107                                                    err, sock_errstr(err) ));
1108 #else
1109                                         Debug( LDAP_DEBUG_CONNS,
1110                                                 "daemon: select failed (%d): %s\n",
1111                                                 err, sock_errstr(err), 0 );
1112 #endif
1113                                         slapd_shutdown = -1;
1114                                 }
1115                         }
1116                         continue;
1117
1118                 case 0:         /* timeout - let threads run */
1119                         ebadf = 0;
1120 #ifdef NEW_LOGGING
1121                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1122                                    "slapd_daemon_task: select timeout - yielding\n" ));
1123 #else
1124                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
1125                             0, 0, 0 );
1126 #endif
1127                         ldap_pvt_thread_yield();
1128                         continue;
1129
1130                 default:        /* something happened - deal with it */
1131                         if( slapd_shutdown ) continue;
1132
1133                         ebadf = 0;
1134 #ifdef NEW_LOGGING
1135                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1136                                    "slapd_daemon_task: activity on %d descriptors\n", ns ));
1137 #else
1138                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
1139                                 ns, 0, 0 );
1140 #endif
1141                         /* FALL THRU */
1142                 }
1143
1144                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
1145                         char c[BUFSIZ];
1146                         tcp_read( wake_sds[0], c, sizeof(c) );
1147 #ifdef NO_THREADS
1148                         waking = 0;
1149 #endif
1150                         continue;
1151                 }
1152
1153                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1154                         ber_socket_t s;
1155                         socklen_t len = sizeof(from);
1156                         long id;
1157                         slap_ssf_t ssf = 0;
1158                         char *authid = NULL;
1159
1160                         char    *dnsname = NULL;
1161                         char    *peeraddr;
1162 #ifdef LDAP_PF_LOCAL
1163                         char    peername[MAXPATHLEN + sizeof("PATH=")];
1164 #elif defined(LDAP_PF_INET6)
1165                         char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
1166 #else
1167                         char    peername[sizeof("IP=255.255.255.255:65336")];
1168 #endif /* LDAP_PF_LOCAL */
1169
1170                         peername[0] = '\0';
1171
1172                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1173                                 continue;
1174
1175                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
1176                                 continue;
1177
1178 #ifdef LDAP_CONNECTIONLESS
1179                         if ( slap_listeners[l]->sl_is_udp )
1180                         {
1181                         /* The first time we receive a query, we set this
1182                          * up as a "connection". It remains open for the life
1183                          * of the slapd.
1184                          */
1185                                 if ( slap_listeners[l]->sl_is_udp < 2 )
1186                                 {
1187                                     id = connection_init(
1188                                         slap_listeners[l]->sl_sd,
1189                                         slap_listeners[l]->sl_url, "", "",
1190                                         slap_listeners[l]->sl_name,
1191                                         2, ssf, authid );
1192                                     slap_listeners[l]->sl_is_udp++;
1193                                 }
1194                                 continue;
1195                         }
1196 #endif
1197
1198                         s = accept( slap_listeners[l]->sl_sd,
1199                                 (struct sockaddr *) &from, &len );
1200                         if ( s == AC_SOCKET_INVALID ) {
1201                                 int err = sock_errno();
1202
1203 #ifdef EMFILE
1204                                 if( err == EMFILE ) {
1205                                         emfile++;
1206                                 } else
1207 #endif
1208 #ifdef ENFILE
1209                                 if( err == ENFILE ) {
1210                                         emfile++;
1211                                 } else 
1212 #endif
1213                                 {
1214                                         emfile=0;
1215                                 }
1216
1217                                 if( emfile < 3 ) {
1218 #ifdef NEW_LOGGING
1219                                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1220                                                 "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n",
1221                                                 (long)slap_listeners[l]->sl_sd, err, sock_errstr(err) ));
1222 #else
1223                                         Debug( LDAP_DEBUG_ANY,
1224                                             "daemon: accept(%ld) failed errno=%d (%s)\n",
1225                                             (long) slap_listeners[l]->sl_sd, err,
1226                                             sock_errstr(err) );
1227 #endif
1228                                 } else {
1229                                         /* prevent busy loop */
1230 #  ifdef HAVE_USLEEP
1231                                         if( emfile % 4 == 3 ) usleep( 250 );
1232 #  else
1233                                         if( emfile % 8 == 7 ) sleep( 1 );
1234 #  endif
1235                                 }
1236
1237                                 ldap_pvt_thread_yield();
1238                                 continue;
1239                         }
1240                         emfile = 0;
1241
1242 #ifndef HAVE_WINSOCK
1243                         /* make sure descriptor number isn't too great */
1244                         if ( s >= dtblsize ) {
1245 #ifdef NEW_LOGGING
1246                                 LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1247                                    "slapd_daemon_task: %ld beyond descriptor table size %ld\n",
1248                                    (long)s, (long)dtblsize ));
1249 #else
1250                                 Debug( LDAP_DEBUG_ANY,
1251                                         "daemon: %ld beyond descriptor table size %ld\n",
1252                                         (long) s, (long) dtblsize, 0 );
1253 #endif
1254
1255                                 slapd_close(s);
1256                                 ldap_pvt_thread_yield();
1257                                 continue;
1258                         }
1259 #endif
1260
1261 #ifdef LDAP_DEBUG
1262                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
1263
1264                         /* newly accepted stream should not be in any of the FD SETS */
1265                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
1266                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
1267                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
1268
1269                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
1270 #endif
1271
1272 #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY )
1273 #ifdef LDAP_PF_LOCAL
1274                         /* for IPv4 and IPv6 sockets only */
1275                         if ( from.sa_addr.sa_family != AF_LOCAL )
1276 #endif /* LDAP_PF_LOCAL */
1277                         {
1278                                 int rc;
1279                                 int tmp;
1280 #ifdef SO_KEEPALIVE
1281                                 /* enable keep alives */
1282                                 tmp = 1;
1283                                 rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
1284                                         (char *) &tmp, sizeof(tmp) );
1285                                 if ( rc == AC_SOCKET_ERROR ) {
1286                                         int err = sock_errno();
1287 #ifdef NEW_LOGGING
1288                                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1289                                                    "slapd_daemon_task: setsockopt( %ld, SO_KEEPALIVE) failed errno=%d (%s)\n",
1290                                                    (long)s, err, sock_errstr(err) ));
1291 #else
1292                                         Debug( LDAP_DEBUG_ANY,
1293                                                 "slapd(%ld): setsockopt(SO_KEEPALIVE) failed "
1294                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
1295 #endif
1296                                 }
1297 #endif
1298 #ifdef TCP_NODELAY
1299                                 /* enable no delay */
1300                                 tmp = 1;
1301                                 rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
1302                                         (char *)&tmp, sizeof(tmp) );
1303                                 if ( rc == AC_SOCKET_ERROR ) {
1304                                         int err = sock_errno();
1305 #ifdef NEW_LOGGING
1306                                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1307                                                    "slapd_daemon_task: setsockopt( %ld, TCP_NODELAY) failed errno=%d (%s)\n",
1308                                                    (long)s, err, sock_errstr(err) ));
1309 #else
1310                                         Debug( LDAP_DEBUG_ANY,
1311                                                 "slapd(%ld): setsockopt(TCP_NODELAY) failed "
1312                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
1313 #endif
1314                                 }
1315 #endif
1316                         }
1317 #endif
1318
1319 #ifdef NEW_LOGGING
1320                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
1321                                    "slapd_daemon_task: new connection on %ld\n", (long)s ));
1322 #else
1323                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
1324                                 (long) s, 0, 0 );
1325 #endif
1326                         switch ( from.sa_addr.sa_family ) {
1327 #  ifdef LDAP_PF_LOCAL
1328                         case AF_LOCAL:
1329                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
1330                                 ssf = LDAP_PVT_SASL_LOCAL_SSF;
1331                                 break;
1332 #endif /* LDAP_PF_LOCAL */
1333
1334 #  ifdef LDAP_PF_INET6
1335                         case AF_INET6:
1336                         if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
1337                                 peeraddr = inet_ntoa( *((struct in_addr *)
1338                                                         &from.sa_in6_addr.sin6_addr.s6_addr[12]) );
1339                                 sprintf( peername, "IP=%s:%d",
1340                                          peeraddr != NULL ? peeraddr : "unknown",
1341                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
1342                         } else {
1343                                 char addr[INET6_ADDRSTRLEN];
1344                                 sprintf( peername, "IP=%s %d",
1345                                          inet_ntop( AF_INET6,
1346                                                     &from.sa_in6_addr.sin6_addr,
1347                                                     addr, sizeof addr) ? addr : "unknown",
1348                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
1349                         }
1350                         break;
1351 #  endif /* LDAP_PF_INET6 */
1352
1353                         case AF_INET:
1354                         peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
1355                         sprintf( peername, "IP=%s:%d",
1356                                 peeraddr != NULL ? peeraddr : "unknown",
1357                                 (unsigned) ntohs( from.sa_in_addr.sin_port ) );
1358                                 break;
1359
1360                         default:
1361                                 slapd_close(s);
1362                                 continue;
1363                         }
1364
1365                         if ( ( from.sa_addr.sa_family == AF_INET )
1366 #ifdef LDAP_PF_INET6
1367                                 || ( from.sa_addr.sa_family == AF_INET6 )
1368 #endif
1369                         ) {
1370 #ifdef SLAPD_RLOOKUPS
1371 #  ifdef LDAP_PF_INET6
1372                                 if ( from.sa_addr.sa_family == AF_INET6 )
1373                                         hp = gethostbyaddr(
1374                                                 (char *)&(from.sa_in6_addr.sin6_addr),
1375                                                 sizeof(from.sa_in6_addr.sin6_addr),
1376                                                 AF_INET6 );
1377                                 else
1378 #  endif /* LDAP_PF_INET6 */
1379                                 hp = gethostbyaddr(
1380                                         (char *) &(from.sa_in_addr.sin_addr),
1381                                         sizeof(from.sa_in_addr.sin_addr),
1382                                         AF_INET );
1383                                 dnsname = hp ? ldap_pvt_str2lower( hp->h_name ) : NULL;
1384 #else
1385                                 dnsname = NULL;
1386 #endif /* SLAPD_RLOOKUPS */
1387
1388 #ifdef HAVE_TCPD
1389                                 if ( !hosts_ctl("slapd",
1390                                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
1391                                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
1392                                                 STRING_UNKNOWN ))
1393                                 {
1394                                         /* DENY ACCESS */
1395                                         Statslog( LDAP_DEBUG_ANY,
1396                                                 "fd=%ld host access from %s (%s) denied.\n",
1397                                                 (long) s,
1398                                                 dnsname != NULL ? dnsname : "unknown",
1399                                                 peeraddr != NULL ? peeraddr : "unknown",
1400                                                 0, 0 );
1401                                         slapd_close(s);
1402                                         continue;
1403                                 }
1404 #endif /* HAVE_TCPD */
1405                         }
1406
1407                         id = connection_init(s,
1408                                 slap_listeners[l]->sl_url,
1409                                 dnsname != NULL ? dnsname : "unknown",
1410                                 peername,
1411                                 slap_listeners[l]->sl_name,
1412 #ifdef HAVE_TLS
1413                                 slap_listeners[l]->sl_is_tls,
1414 #else
1415                                 0,
1416 #endif
1417                                 ssf,
1418                                 authid );
1419
1420                         if( authid ) ch_free(authid);
1421
1422                         if( id < 0 ) {
1423 #ifdef NEW_LOGGING
1424                                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
1425                                            "slapd_daemon_task: connection_init(%ld, %s, %s) failed.\n",
1426                                            (long)s, peername, slap_listeners[l]->sl_name ));
1427 #else
1428                                 Debug( LDAP_DEBUG_ANY,
1429                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
1430                                         (long) s,
1431                                         peername,
1432                                         slap_listeners[l]->sl_name );
1433 #endif
1434                                 slapd_close(s);
1435                                 continue;
1436                         }
1437
1438                         Statslog( LDAP_DEBUG_STATS,
1439                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
1440                                 id, (long) s,
1441                                 peername,
1442                                 slap_listeners[l]->sl_name,
1443                                 0 );
1444
1445                         slapd_add( s );
1446                         continue;
1447                 }
1448
1449 #ifdef LDAP_DEBUG
1450 #ifdef NEW_LOGGING
1451                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1452                            "slapd_daemon_task: activity on " ));
1453 #else
1454                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
1455 #endif
1456 #ifdef HAVE_WINSOCK
1457                 for ( i = 0; i < readfds.fd_count; i++ ) {
1458 #ifdef NEW_LOGGING
1459                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1460                                    " %d%s", readfds.fd_array[i], "r", 0 ));
1461 #else
1462                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1463                                 readfds.fd_array[i], "r", 0 );
1464 #endif
1465                 }
1466                 for ( i = 0; i < writefds.fd_count; i++ ) {
1467 #ifdef NEW_LOGGING
1468                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1469                                    " %d%s", writefds.fd_array[i], "w" ));
1470 #else
1471                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1472                                 writefds.fd_array[i], "w", 0 );
1473 #endif
1474                 }
1475
1476 #else
1477                 for ( i = 0; i < nfds; i++ ) {
1478                         int     r, w;
1479                         int     is_listener = 0;
1480
1481                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1482                                 if ( i == slap_listeners[l]->sl_sd ) {
1483 #ifdef LDAP_CONNECTIONLESS
1484                                 /* The listener is the data port. Don't
1485                                  * skip it.
1486                                  */
1487                                         if (slap_listeners[l]->sl_is_udp)
1488                                                 continue;
1489 #endif
1490                                         is_listener = 1;
1491                                         break;
1492                                 }
1493                         }
1494                         if ( is_listener ) {
1495                                 continue;
1496                         }
1497                         r = FD_ISSET( i, &readfds );
1498                         w = FD_ISSET( i, &writefds );
1499                         if ( r || w ) {
1500 #ifdef NEW_LOGGING
1501                                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1502                                            " %d%s%s", i,
1503                                            r ? "r" : "", w ? "w" : "" ));
1504 #else
1505                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
1506                                     r ? "r" : "", w ? "w" : "" );
1507 #endif
1508                         }
1509                 }
1510 #endif
1511 #ifdef NEW_LOGGING
1512                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2, "\n" ));
1513 #else
1514                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
1515 #endif
1516
1517 #endif
1518
1519                 /* loop through the writers */
1520 #ifdef HAVE_WINSOCK
1521                 for ( i = 0; i < writefds.fd_count; i++ )
1522 #else
1523                 for ( i = 0; i < nfds; i++ )
1524 #endif
1525                 {
1526                         ber_socket_t wd;
1527                         int is_listener = 0;
1528 #ifdef HAVE_WINSOCK
1529                         wd = writefds.fd_array[i];
1530 #else
1531                         if( ! FD_ISSET( i, &writefds ) ) {
1532                                 continue;
1533                         }
1534                         wd = i;
1535 #endif
1536
1537                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1538                                 if ( i == slap_listeners[l]->sl_sd ) {
1539 #ifdef LDAP_CONNECTIONLESS
1540                                         if (slap_listeners[l]->sl_is_udp)
1541                                                 continue;
1542 #endif
1543                                         is_listener = 1;
1544                                         break;
1545                                 }
1546                         }
1547                         if ( is_listener ) {
1548                                 continue;
1549                         }
1550 #ifdef NEW_LOGGING
1551                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1552                                    "slapd_daemon_task: write active on %d\n", wd ));
1553 #else
1554                         Debug( LDAP_DEBUG_CONNS,
1555                                 "daemon: write active on %d\n",
1556                                 wd, 0, 0 );
1557 #endif
1558                         /*
1559                          * NOTE: it is possible that the connection was closed
1560                          * and that the stream is now inactive.
1561                          * connection_write() must valid the stream is still
1562                          * active.
1563                          */
1564
1565                         if ( connection_write( wd ) < 0 ) {
1566                                 FD_CLR( (unsigned) wd, &readfds );
1567                                 slapd_close( wd );
1568                         }
1569                 }
1570
1571 #ifdef HAVE_WINSOCK
1572                 for ( i = 0; i < readfds.fd_count; i++ )
1573 #else
1574                 for ( i = 0; i < nfds; i++ )
1575 #endif
1576                 {
1577                         ber_socket_t rd;
1578                         int is_listener = 0;
1579
1580 #ifdef HAVE_WINSOCK
1581                         rd = readfds.fd_array[i];
1582 #else
1583                         if( ! FD_ISSET( i, &readfds ) ) {
1584                                 continue;
1585                         }
1586                         rd = i;
1587 #endif
1588
1589                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1590                                 if ( rd == slap_listeners[l]->sl_sd ) {
1591 #ifdef LDAP_CONNECTIONLESS
1592                                         if (slap_listeners[l]->sl_is_udp)
1593                                                 continue;
1594 #endif
1595                                         is_listener = 1;
1596                                         break;
1597                                 }
1598                         }
1599                         if ( is_listener ) {
1600                                 continue;
1601                         }
1602
1603 #ifdef NEW_LOGGING
1604                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1605                                    "slapd_daemon_task: read activity on %d\n", rd ));
1606 #else
1607                         Debug ( LDAP_DEBUG_CONNS,
1608                                 "daemon: read activity on %d\n", rd, 0, 0 );
1609 #endif
1610                         /*
1611                          * NOTE: it is possible that the connection was closed
1612                          * and that the stream is now inactive.
1613                          * connection_read() must valid the stream is still
1614                          * active.
1615                          */
1616
1617                         if ( connection_read( rd ) < 0 ) {
1618                                 slapd_close( rd );
1619                         }
1620                 }
1621                 ldap_pvt_thread_yield();
1622         }
1623
1624         if( slapd_shutdown > 0 ) {
1625 #ifdef NEW_LOGGING
1626                 LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1627                            "slapd_daemon_task: shutdown requested and initiated.\n"));
1628 #else
1629                 Debug( LDAP_DEBUG_TRACE,
1630                         "daemon: shutdown requested and initiated.\n",
1631                         0, 0, 0 );
1632 #endif
1633
1634         } else if ( slapd_shutdown < 0 ) {
1635 #ifdef HAVE_NT_SERVICE_MANAGER
1636                 if (slapd_shutdown == -1)
1637                 {
1638 #ifdef NEW_LOGGING
1639                         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1640                                    "slapd_daemon_task: shutdown initiated by Service Manager.\n"));
1641 #else
1642                         Debug( LDAP_DEBUG_TRACE,
1643                                "daemon: shutdown initiated by Service Manager.\n",
1644                                0, 0, 0);
1645 #endif
1646                 }
1647                 else
1648 #endif
1649                 {
1650 #ifdef NEW_LOGGING
1651                         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1652                                    "slapd_daemon_task: abnormal condition, shutdown initiated.\n" ));
1653 #else
1654                         Debug( LDAP_DEBUG_TRACE,
1655                                "daemon: abnormal condition, shutdown initiated.\n",
1656                                0, 0, 0 );
1657 #endif
1658                 }
1659         } else {
1660 #ifdef NEW_LOGGING
1661                 LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1662                            "slapd_daemon_task: no active streams, shutdown initiated.\n" ));
1663 #else
1664                 Debug( LDAP_DEBUG_TRACE,
1665                        "daemon: no active streams, shutdown initiated.\n",
1666                        0, 0, 0 );
1667 #endif
1668         }
1669
1670         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1671                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1672 #ifdef LDAP_PF_LOCAL
1673                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
1674                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1675                         }
1676 #endif /* LDAP_PF_LOCAL */
1677                         slapd_close( slap_listeners[l]->sl_sd );
1678                         break;
1679                 }
1680         }
1681
1682 #ifdef NEW_LOGGING
1683         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1684                    "slapd_daemon_task: shutdown waiting for %d threads to terminate.\n",
1685                    ldap_pvt_thread_pool_backload(&connection_pool) ));
1686 #else
1687         Debug( LDAP_DEBUG_ANY,
1688             "slapd shutdown: waiting for %d threads to terminate\n",
1689             ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
1690 #endif
1691         ldap_pvt_thread_pool_destroy(&connection_pool, 1);
1692
1693         return NULL;
1694 }
1695
1696
1697 int slapd_daemon( void )
1698 {
1699         int rc;
1700
1701         connections_init();
1702
1703 #define SLAPD_LISTENER_THREAD 1
1704 #if defined( SLAPD_LISTENER_THREAD )
1705         {
1706                 ldap_pvt_thread_t       listener_tid;
1707
1708                 /* listener as a separate THREAD */
1709                 rc = ldap_pvt_thread_create( &listener_tid,
1710                         0, slapd_daemon_task, NULL );
1711
1712                 if ( rc != 0 ) {
1713 #ifdef NEW_LOGGING
1714                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1715                                    "slapd_daemon: listener ldap_pvt_thread_create failed (%d).\n", rc ));
1716 #else
1717                         Debug( LDAP_DEBUG_ANY,
1718                         "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1719 #endif
1720                         return rc;
1721                 }
1722  
1723                 /* wait for the listener thread to complete */
1724                 ldap_pvt_thread_join( listener_tid, (void *) NULL );
1725         }
1726 #else
1727         /* experimental code */
1728         slapd_daemon_task( NULL );
1729 #endif
1730
1731         return 0;
1732
1733 }
1734
1735 int sockinit(void)
1736 {
1737 #if defined( HAVE_WINSOCK2 )
1738     WORD wVersionRequested;
1739         WSADATA wsaData;
1740         int err;
1741
1742         wVersionRequested = MAKEWORD( 2, 0 );
1743
1744         err = WSAStartup( wVersionRequested, &wsaData );
1745         if ( err != 0 ) {
1746                 /* Tell the user that we couldn't find a usable */
1747                 /* WinSock DLL.                                  */
1748                 return -1;
1749         }
1750
1751         /* Confirm that the WinSock DLL supports 2.0.*/
1752         /* Note that if the DLL supports versions greater    */
1753         /* than 2.0 in addition to 2.0, it will still return */
1754         /* 2.0 in wVersion since that is the version we      */
1755         /* requested.                                        */
1756
1757         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1758                 HIBYTE( wsaData.wVersion ) != 0 )
1759         {
1760             /* Tell the user that we couldn't find a usable */
1761             /* WinSock DLL.                                  */
1762             WSACleanup();
1763             return -1;
1764         }
1765
1766         /* The WinSock DLL is acceptable. Proceed. */
1767 #elif defined( HAVE_WINSOCK )
1768         WSADATA wsaData;
1769         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1770             return -1;
1771         }
1772 #endif
1773         return 0;
1774 }
1775
1776 int sockdestroy(void)
1777 {
1778 #if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
1779         WSACleanup();
1780 #endif
1781         return 0;
1782 }
1783
1784 RETSIGTYPE
1785 slap_sig_shutdown( int sig )
1786 {
1787 #ifdef NEW_LOGGING
1788         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1789                    "slap_sig_shutdown: signal %d\n", sig ));
1790 #else
1791         Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
1792 #endif
1793
1794         /*
1795          * If the NT Service Manager is controlling the server, we don't
1796          * want SIGBREAK to kill the server. For some strange reason,
1797          * SIGBREAK is generated when a user logs out.
1798          */
1799
1800 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
1801         if (is_NT_Service && sig == SIGBREAK)
1802 #ifdef NEW_LOGGING
1803             LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1804                        "slap_sig_shutdown: SIGBREAK ignored.\n" ));
1805 #else
1806             Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
1807                   0, 0, 0);
1808 #endif
1809         else
1810 #endif
1811         slapd_shutdown = sig;
1812
1813         WAKE_LISTENER(1);
1814
1815         /* reinstall self */
1816         (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
1817 }
1818
1819 RETSIGTYPE
1820 slap_sig_wake( int sig )
1821 {
1822         WAKE_LISTENER(1);
1823
1824         /* reinstall self */
1825         (void) SIGNAL_REINSTALL( sig, slap_sig_wake );
1826 }
1827
1828
1829 void slapd_add_internal(ber_socket_t s) {
1830         slapd_add(s);
1831 }