]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
Update copyright statements
[openldap] / servers / slapd / daemon.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 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( slap_strcopy(slapd_srvurls[i],
118                                         LDAP_SRVTYPE_PREFIX ), 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( slap_strcopy(slapd_srvurls[i],
130                                         LDAPS_SRVTYPE_PREFIX ), 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 #else
737                 s = inet_ntoa( ((struct sockaddr_in *) *sal)->sin_addr );
738 #endif
739                 port = ((struct sockaddr_in *)*sal) ->sin_port;
740                 l.sl_name = ch_malloc( sizeof("IP=255.255.255.255:65535") );
741                 sprintf( l.sl_name, "IP=%s:%d",
742                          s != NULL ? s : "unknown" , port );
743         } break;
744
745 #ifdef LDAP_PF_INET6
746         case AF_INET6: {
747                 char addr[INET6_ADDRSTRLEN];
748                 inet_ntop( AF_INET6, &((struct sockaddr_in6 *)*sal)->sin6_addr,
749                            addr, sizeof addr);
750                 port = ((struct sockaddr_in6 *)*sal)->sin6_port;
751                 l.sl_name = ch_malloc( strlen(addr) + sizeof("IP= 65535") );
752                 sprintf( l.sl_name, "IP=%s %d", addr, port );
753         } break;
754 #endif /* LDAP_PF_INET6 */
755
756         default:
757 #ifdef NEW_LOGGING
758                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
759                            "slap_open_listener: unsupported address family (%d)\n",
760                            (int)(*sal)->sa_family ));
761 #else
762                 Debug( LDAP_DEBUG_ANY, "daemon: unsupported address family (%d)\n",
763                         (int) (*sal)->sa_family, 0, 0 );
764 #endif
765                 break;
766         }
767
768         slap_free_listener_addresses(psal);
769
770         l.sl_url = ch_strdup( url );
771         li = ch_malloc( sizeof( Listener ) );
772         *li = l;
773
774 #ifdef NEW_LOGGING
775         LDAP_LOG(( "connection", LDAP_LEVEL_RESULTS,
776                    "slap_open_listener: daemon initialzed %s\n", l.sl_url ));
777 #else
778         Debug( LDAP_DEBUG_TRACE, "daemon: initialized %s\n",
779                 l.sl_url, 0, 0 );
780 #endif
781         return li;
782 }
783
784 static int sockinit(void);
785 static int sockdestroy(void);
786
787 int slapd_daemon_init( const char *urls )
788 {
789         int i, rc;
790         char **u;
791
792 #ifdef NEW_LOGGING
793         LDAP_LOG(( "connection", LDAP_LEVEL_ARGS,
794                    "slapd_daemon_init: %s\n",
795                    urls ? urls : "<null>" ));
796 #else
797         Debug( LDAP_DEBUG_ARGS, "daemon_init: %s\n",
798                 urls ? urls : "<null>", 0, 0 );
799 #endif
800         if( (rc = sockinit()) != 0 ) {
801                 return rc;
802         }
803
804 #ifdef HAVE_SYSCONF
805         dtblsize = sysconf( _SC_OPEN_MAX );
806 #elif HAVE_GETDTABLESIZE
807         dtblsize = getdtablesize();
808 #else
809         dtblsize = FD_SETSIZE;
810 #endif
811
812 #ifdef FD_SETSIZE
813         if(dtblsize > FD_SETSIZE) {
814                 dtblsize = FD_SETSIZE;
815         }
816 #endif  /* !FD_SETSIZE */
817
818         /* open a pipe (or something equivalent connected to itself).
819          * we write a byte on this fd whenever we catch a signal. The main
820          * loop will be select'ing on this socket, and will wake up when
821          * this byte arrives.
822          */
823         if( (rc = lutil_pair( wake_sds )) < 0 ) {
824 #ifdef NEW_LOGGING
825                 LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
826                            "slap_daemon_init: lutil_pair() failed rc=%d\n", rc ));
827 #else
828                 Debug( LDAP_DEBUG_ANY,
829                         "daemon: lutil_pair() failed rc=%d\n", rc, 0, 0 );
830 #endif
831                 return rc;
832         }
833
834         FD_ZERO( &slap_daemon.sd_readers );
835         FD_ZERO( &slap_daemon.sd_writers );
836
837         if( urls == NULL ) {
838                 urls = "ldap:///";
839         }
840
841         u = str2charray( urls, " " );
842
843         if( u == NULL || u[0] == NULL ) {
844 #ifdef NEW_LOGGING
845                 LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
846                            "slap_daemon_init: no urls (%s) provided.\n", urls ));
847 #else
848                 Debug( LDAP_DEBUG_ANY, "daemon_init: no urls (%s) provided.\n",
849                         urls, 0, 0 );
850 #endif
851                 return -1;
852         }
853
854         for( i=0; u[i] != NULL; i++ ) {
855 #ifdef NEW_LOGGING
856                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
857                            "slap_daemon_init: listen on %s\n.", u[i] ));
858 #else
859                 Debug( LDAP_DEBUG_TRACE, "daemon_init: listen on %s\n",
860                         u[i], 0, 0 );
861 #endif
862         }
863
864         if( i == 0 ) {
865 #ifdef NEW_LOGGING
866                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
867                            "slap_daemon_init: no listeners to open (%s)\n", urls ));
868 #else
869                 Debug( LDAP_DEBUG_ANY, "daemon_init: no listeners to open (%s)\n",
870                         urls, 0, 0 );
871 #endif
872                 charray_free( u );
873                 return -1;
874         }
875
876 #ifdef NEW_LOGGING
877         LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
878                    "slap_daemon_init: %d listeners to open...\n", i ));
879 #else
880         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners to open...\n",
881                 i, 0, 0 );
882 #endif
883         slap_listeners = ch_malloc( (i+1)*sizeof(Listener *) );
884
885         for(i = 0; u[i] != NULL; i++ ) {
886                 slap_listeners[i] = slap_open_listener( u[i] );
887
888                 if( slap_listeners[i] == NULL ) {
889                         charray_free( u );
890                         return -1;
891                 }
892         }
893         slap_listeners[i] = NULL;
894
895 #ifdef NEW_LOGGING
896         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
897                    "slap_daemon_init: %d listeners opened\n", i ));
898 #else
899         Debug( LDAP_DEBUG_TRACE, "daemon_init: %d listeners opened\n",
900                 i, 0, 0 );
901 #endif
902
903 #ifdef HAVE_SLP
904         slapd_slp_init( urls );
905         slapd_slp_reg();
906 #endif
907
908         charray_free( u );
909         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
910         return !i;
911 }
912
913
914 int
915 slapd_daemon_destroy(void)
916 {
917         connections_destroy();
918         tcp_close( wake_sds[1] );
919         tcp_close( wake_sds[0] );
920         sockdestroy();
921
922 #ifdef HAVE_SLP
923         slapd_slp_dereg();
924         slapd_slp_deinit();
925 #endif
926
927         return 0;
928 }
929
930
931 static void *
932 slapd_daemon_task(
933         void *ptr
934 )
935 {
936         int l;
937         time_t  last_idle_check = 0;
938         time( &starttime );
939
940         if ( global_idletimeout > 0 ) {
941                 last_idle_check = slap_get_time();
942         }
943         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
944                 if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
945                         continue;
946 #ifdef LDAP_CONNECTIONLESS
947                 /* Since this is connectionless, the data port is the
948                  * listening port. The listen() and accept() calls
949                  * are unnecessary.
950                  */
951                 if ( slap_listeners[l]->sl_is_udp )
952                 {
953                         slapd_add( slap_listeners[l]->sl_sd );
954                         continue;
955                 }
956 #endif
957
958                 if ( listen( slap_listeners[l]->sl_sd, SLAPD_LISTEN ) == -1 ) {
959                         int err = sock_errno();
960 #ifdef NEW_LOGGING
961                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
962                                    "slapd_daemon_task: listen( %s, 5 ) failed errno=%d (%s)\n",
963                                    slap_listeners[l]->sl_url, err, sock_errstr(err) ));
964 #else
965                         Debug( LDAP_DEBUG_ANY,
966                                 "daemon: listen(%s, 5) failed errno=%d (%s)\n",
967                                         slap_listeners[l]->sl_url, err,
968                                         sock_errstr(err) );
969 #endif
970                         return( (void*)-1 );
971                 }
972
973                 slapd_add( slap_listeners[l]->sl_sd );
974         }
975
976 #ifdef HAVE_NT_SERVICE_MANAGER
977         if ( started_event != NULL ) {
978                 ldap_pvt_thread_cond_signal( &started_event );
979         }
980 #endif
981         /* initialization complete. Here comes the loop. */
982
983         while ( !slapd_shutdown ) {
984                 ber_socket_t i;
985                 int ns;
986                 int at;
987                 ber_socket_t nfds;
988 #define SLAPD_EBADF_LIMIT 16
989                 int ebadf = 0;
990                 int emfile = 0;
991
992 #define SLAPD_IDLE_CHECK_LIMIT 4
993                 time_t  now;
994
995
996                 fd_set                  readfds;
997                 fd_set                  writefds;
998                 Sockaddr                from;
999
1000 #if defined(SLAPD_RLOOKUPS)
1001                 struct hostent          *hp;
1002 #endif
1003                 struct timeval          zero;
1004                 struct timeval          *tvp;
1005
1006                 if( emfile ) {
1007                         now = slap_get_time();
1008                         connections_timeout_idle( now );
1009                 }
1010                 else if ( global_idletimeout > 0 ) {
1011                         now = slap_get_time();
1012                         if ( difftime( last_idle_check+global_idletimeout/SLAPD_IDLE_CHECK_LIMIT, now ) < 0 ) {
1013                                 connections_timeout_idle( now );
1014                         }
1015                 }
1016
1017                 FD_ZERO( &writefds );
1018                 FD_ZERO( &readfds );
1019
1020                 zero.tv_sec = 0;
1021                 zero.tv_usec = 0;
1022
1023                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
1024
1025 #ifdef FD_SET_MANUAL_COPY
1026                 for( s = 0; s < nfds; s++ ) {
1027                         if(FD_ISSET( &slap_sd_readers, s )) {
1028                                 FD_SET( s, &readfds );
1029                         }
1030                         if(FD_ISSET( &slap_sd_writers, s )) {
1031                                 FD_SET( s, &writefds );
1032                         }
1033                 }
1034 #else
1035                 AC_MEMCPY( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
1036                 AC_MEMCPY( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
1037 #endif
1038                 assert(!FD_ISSET(wake_sds[0], &readfds));
1039                 FD_SET( wake_sds[0], &readfds );
1040
1041                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1042                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1043                                 continue;
1044                         if (!FD_ISSET(slap_listeners[l]->sl_sd, &readfds))
1045                             FD_SET( slap_listeners[l]->sl_sd, &readfds );
1046                 }
1047
1048 #ifndef HAVE_WINSOCK
1049                 nfds = slap_daemon.sd_nfds;
1050 #else
1051                 nfds = dtblsize;
1052 #endif
1053
1054                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
1055
1056                 at = ldap_pvt_thread_pool_backload(&connection_pool);
1057
1058 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
1059                 tvp = NULL;
1060 #else
1061                 tvp = at ? &zero : NULL;
1062 #endif
1063
1064                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1065                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1066                                 continue;
1067
1068 #ifdef NEW_LOGGING
1069                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
1070                                    "slapd_daemon_task: select: listen=%d active_threads=%d tvp=%s\n",
1071                                    slap_listeners[l]->sl_sd, at, tvp == NULL ? "NULL" : "zero" ));
1072 #else
1073                         Debug( LDAP_DEBUG_CONNS,
1074                                 "daemon: select: listen=%d active_threads=%d tvp=%s\n",
1075                                         slap_listeners[l]->sl_sd, at,
1076                                         tvp == NULL ? "NULL" : "zero" );
1077 #endif
1078                 }
1079
1080                 switch(ns = select( nfds, &readfds,
1081 #ifdef HAVE_WINSOCK
1082                         /* don't pass empty fd_set */
1083                         ( writefds.fd_count > 0 ? &writefds : NULL ),
1084 #else
1085                         &writefds,
1086 #endif
1087                         NULL, tvp ))
1088                 {
1089                 case -1: {      /* failure - try again */
1090                                 int err = sock_errno();
1091
1092                                 if( err == EBADF
1093 #ifdef WSAENOTSOCK
1094                                         /* you'd think this would be EBADF */
1095                                         || err == WSAENOTSOCK
1096 #endif
1097                                 ) {
1098                                         if (++ebadf < SLAPD_EBADF_LIMIT)
1099                                                 continue;
1100                                 }
1101
1102                                 if( err != EINTR ) {
1103 #ifdef NEW_LOGGING
1104                                         LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
1105                                                    "slapd_daemon_task: select failed (%d): %s\n",
1106                                                    err, sock_errstr(err) ));
1107 #else
1108                                         Debug( LDAP_DEBUG_CONNS,
1109                                                 "daemon: select failed (%d): %s\n",
1110                                                 err, sock_errstr(err), 0 );
1111 #endif
1112                                         slapd_shutdown = -1;
1113                                 }
1114                         }
1115                         continue;
1116
1117                 case 0:         /* timeout - let threads run */
1118                         ebadf = 0;
1119 #ifdef NEW_LOGGING
1120                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1121                                    "slapd_daemon_task: select timeout - yielding\n" ));
1122 #else
1123                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
1124                             0, 0, 0 );
1125 #endif
1126                         ldap_pvt_thread_yield();
1127                         continue;
1128
1129                 default:        /* something happened - deal with it */
1130                         if( slapd_shutdown ) continue;
1131
1132                         ebadf = 0;
1133 #ifdef NEW_LOGGING
1134                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1135                                    "slapd_daemon_task: activity on %d descriptors\n", ns ));
1136 #else
1137                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
1138                                 ns, 0, 0 );
1139 #endif
1140                         /* FALL THRU */
1141                 }
1142
1143                 if( FD_ISSET( wake_sds[0], &readfds ) ) {
1144                         char c[BUFSIZ];
1145                         tcp_read( wake_sds[0], c, sizeof(c) );
1146 #ifdef NO_THREADS
1147                         waking = 0;
1148 #endif
1149                         continue;
1150                 }
1151
1152                 for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1153                         ber_socket_t s;
1154                         socklen_t len = sizeof(from);
1155                         long id;
1156                         slap_ssf_t ssf = 0;
1157                         char *authid = NULL;
1158
1159                         char    *dnsname = NULL;
1160                         char    *peeraddr;
1161 #ifdef LDAP_PF_LOCAL
1162                         char    peername[MAXPATHLEN + sizeof("PATH=")];
1163 #elif defined(LDAP_PF_INET6)
1164                         char    peername[sizeof("IP=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535")];
1165 #else
1166                         char    peername[sizeof("IP=255.255.255.255:65336")];
1167 #endif /* LDAP_PF_LOCAL */
1168
1169                         peername[0] = '\0';
1170
1171                         if ( slap_listeners[l]->sl_sd == AC_SOCKET_INVALID )
1172                                 continue;
1173
1174                         if ( !FD_ISSET( slap_listeners[l]->sl_sd, &readfds ) )
1175                                 continue;
1176
1177 #ifdef LDAP_CONNECTIONLESS
1178                         if ( slap_listeners[l]->sl_is_udp )
1179                         {
1180                         /* The first time we receive a query, we set this
1181                          * up as a "connection". It remains open for the life
1182                          * of the slapd.
1183                          */
1184                                 if ( slap_listeners[l]->sl_is_udp < 2 )
1185                                 {
1186                                     id = connection_init(
1187                                         slap_listeners[l]->sl_sd,
1188                                         slap_listeners[l]->sl_url, "", "",
1189                                         slap_listeners[l]->sl_name,
1190                                         2, ssf, authid );
1191                                     slap_listeners[l]->sl_is_udp++;
1192                                 }
1193                                 continue;
1194                         }
1195 #endif
1196
1197                         s = accept( slap_listeners[l]->sl_sd,
1198                                 (struct sockaddr *) &from, &len );
1199                         if ( s == AC_SOCKET_INVALID ) {
1200                                 int err = sock_errno();
1201
1202 #ifdef EMFILE
1203                                 if( err == EMFILE ) {
1204                                         emfile++;
1205                                 } else
1206 #endif
1207 #ifdef ENFILE
1208                                 if( err == ENFILE ) {
1209                                         emfile++;
1210                                 } else 
1211 #endif
1212                                 {
1213                                         emfile=0;
1214                                 }
1215
1216                                 if( emfile < 3 ) {
1217 #ifdef NEW_LOGGING
1218                                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1219                                                 "slapd_daemon_task: accept(%ld) failed errno=%d (%s)\n",
1220                                                 (long)slap_listeners[l]->sl_sd, err, sock_errstr(err) ));
1221 #else
1222                                         Debug( LDAP_DEBUG_ANY,
1223                                             "daemon: accept(%ld) failed errno=%d (%s)\n",
1224                                             (long) slap_listeners[l]->sl_sd, err,
1225                                             sock_errstr(err) );
1226 #endif
1227                                 } else {
1228                                         /* prevent busy loop */
1229 #  ifdef HAVE_USLEEP
1230                                         if( emfile % 4 == 3 ) usleep( 250 );
1231 #  else
1232                                         if( emfile % 8 == 7 ) sleep( 1 );
1233 #  endif
1234                                 }
1235
1236                                 ldap_pvt_thread_yield();
1237                                 continue;
1238                         }
1239                         emfile = 0;
1240
1241 #ifndef HAVE_WINSOCK
1242                         /* make sure descriptor number isn't too great */
1243                         if ( s >= dtblsize ) {
1244 #ifdef NEW_LOGGING
1245                                 LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1246                                    "slapd_daemon_task: %ld beyond descriptor table size %ld\n",
1247                                    (long)s, (long)dtblsize ));
1248 #else
1249                                 Debug( LDAP_DEBUG_ANY,
1250                                         "daemon: %ld beyond descriptor table size %ld\n",
1251                                         (long) s, (long) dtblsize, 0 );
1252 #endif
1253
1254                                 slapd_close(s);
1255                                 ldap_pvt_thread_yield();
1256                                 continue;
1257                         }
1258 #endif
1259
1260 #ifdef LDAP_DEBUG
1261                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
1262
1263                         /* newly accepted stream should not be in any of the FD SETS */
1264                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
1265                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
1266                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
1267
1268                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
1269 #endif
1270
1271 #if defined( SO_KEEPALIVE ) || defined( TCP_NODELAY )
1272 #ifdef LDAP_PF_LOCAL
1273                         /* for IPv4 and IPv6 sockets only */
1274                         if ( from.sa_addr.sa_family != AF_LOCAL )
1275 #endif /* LDAP_PF_LOCAL */
1276                         {
1277                                 int rc;
1278                                 int tmp;
1279 #ifdef SO_KEEPALIVE
1280                                 /* enable keep alives */
1281                                 tmp = 1;
1282                                 rc = setsockopt( s, SOL_SOCKET, SO_KEEPALIVE,
1283                                         (char *) &tmp, sizeof(tmp) );
1284                                 if ( rc == AC_SOCKET_ERROR ) {
1285                                         int err = sock_errno();
1286 #ifdef NEW_LOGGING
1287                                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1288                                                    "slapd_daemon_task: setsockopt( %ld, SO_KEEPALIVE) failed errno=%d (%s)\n",
1289                                                    (long)s, err, sock_errstr(err) ));
1290 #else
1291                                         Debug( LDAP_DEBUG_ANY,
1292                                                 "slapd(%ld): setsockopt(SO_KEEPALIVE) failed "
1293                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
1294 #endif
1295                                 }
1296 #endif
1297 #ifdef TCP_NODELAY
1298                                 /* enable no delay */
1299                                 tmp = 1;
1300                                 rc = setsockopt( s, IPPROTO_TCP, TCP_NODELAY,
1301                                         (char *)&tmp, sizeof(tmp) );
1302                                 if ( rc == AC_SOCKET_ERROR ) {
1303                                         int err = sock_errno();
1304 #ifdef NEW_LOGGING
1305                                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1306                                                    "slapd_daemon_task: setsockopt( %ld, TCP_NODELAY) failed errno=%d (%s)\n",
1307                                                    (long)s, err, sock_errstr(err) ));
1308 #else
1309                                         Debug( LDAP_DEBUG_ANY,
1310                                                 "slapd(%ld): setsockopt(TCP_NODELAY) failed "
1311                                                 "errno=%d (%s)\n", (long) s, err, sock_errstr(err) );
1312 #endif
1313                                 }
1314 #endif
1315                         }
1316 #endif
1317
1318 #ifdef NEW_LOGGING
1319                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL1,
1320                                    "slapd_daemon_task: new connection on %ld\n", (long)s ));
1321 #else
1322                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
1323                                 (long) s, 0, 0 );
1324 #endif
1325                         switch ( from.sa_addr.sa_family ) {
1326 #  ifdef LDAP_PF_LOCAL
1327                         case AF_LOCAL:
1328                                 sprintf( peername, "PATH=%s", from.sa_un_addr.sun_path );
1329                                 ssf = LDAP_PVT_SASL_LOCAL_SSF;
1330                                 break;
1331 #endif /* LDAP_PF_LOCAL */
1332
1333 #  ifdef LDAP_PF_INET6
1334                         case AF_INET6:
1335                         if ( IN6_IS_ADDR_V4MAPPED(&from.sa_in6_addr.sin6_addr) ) {
1336                                 peeraddr = inet_ntoa( *((struct in_addr *)
1337                                                         &from.sa_in6_addr.sin6_addr.s6_addr[12]) );
1338                                 sprintf( peername, "IP=%s:%d",
1339                                          peeraddr != NULL ? peeraddr : "unknown",
1340                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
1341                         } else {
1342                                 char addr[INET6_ADDRSTRLEN];
1343                                 sprintf( peername, "IP=%s %d",
1344                                          inet_ntop( AF_INET6,
1345                                                     &from.sa_in6_addr.sin6_addr,
1346                                                     addr, sizeof addr) ? addr : "unknown",
1347                                          (unsigned) ntohs( from.sa_in6_addr.sin6_port ) );
1348                         }
1349                         break;
1350 #  endif /* LDAP_PF_INET6 */
1351
1352                         case AF_INET:
1353                         peeraddr = inet_ntoa( from.sa_in_addr.sin_addr );
1354                         sprintf( peername, "IP=%s:%d",
1355                                 peeraddr != NULL ? peeraddr : "unknown",
1356                                 (unsigned) ntohs( from.sa_in_addr.sin_port ) );
1357                                 break;
1358
1359                         default:
1360                                 slapd_close(s);
1361                                 continue;
1362                         }
1363
1364                         if ( ( from.sa_addr.sa_family == AF_INET )
1365 #ifdef LDAP_PF_INET6
1366                                 || ( from.sa_addr.sa_family == AF_INET6 )
1367 #endif
1368                         ) {
1369 #ifdef SLAPD_RLOOKUPS
1370 #  ifdef LDAP_PF_INET6
1371                                 if ( from.sa_addr.sa_family == AF_INET6 )
1372                                         hp = gethostbyaddr(
1373                                                 (char *)&(from.sa_in6_addr.sin6_addr),
1374                                                 sizeof(from.sa_in6_addr.sin6_addr),
1375                                                 AF_INET6 );
1376                                 else
1377 #  endif /* LDAP_PF_INET6 */
1378                                 hp = gethostbyaddr(
1379                                         (char *) &(from.sa_in_addr.sin_addr),
1380                                         sizeof(from.sa_in_addr.sin_addr),
1381                                         AF_INET );
1382                                 dnsname = hp ? ldap_pvt_str2lower( hp->h_name ) : NULL;
1383 #else
1384                                 dnsname = NULL;
1385 #endif /* SLAPD_RLOOKUPS */
1386
1387 #ifdef HAVE_TCPD
1388                                 if ( !hosts_ctl("slapd",
1389                                                 dnsname != NULL ? dnsname : STRING_UNKNOWN,
1390                                                 peeraddr != NULL ? peeraddr : STRING_UNKNOWN,
1391                                                 STRING_UNKNOWN ))
1392                                 {
1393                                         /* DENY ACCESS */
1394                                         Statslog( LDAP_DEBUG_ANY,
1395                                                 "fd=%ld host access from %s (%s) denied.\n",
1396                                                 (long) s,
1397                                                 dnsname != NULL ? dnsname : "unknown",
1398                                                 peeraddr != NULL ? peeraddr : "unknown",
1399                                                 0, 0 );
1400                                         slapd_close(s);
1401                                         continue;
1402                                 }
1403 #endif /* HAVE_TCPD */
1404                         }
1405
1406                         id = connection_init(s,
1407                                 slap_listeners[l]->sl_url,
1408                                 dnsname != NULL ? dnsname : "unknown",
1409                                 peername,
1410                                 slap_listeners[l]->sl_name,
1411 #ifdef HAVE_TLS
1412                                 slap_listeners[l]->sl_is_tls,
1413 #else
1414                                 0,
1415 #endif
1416                                 ssf,
1417                                 authid );
1418
1419                         if( authid ) ch_free(authid);
1420
1421                         if( id < 0 ) {
1422 #ifdef NEW_LOGGING
1423                                 LDAP_LOG(( "connection", LDAP_LEVEL_INFO,
1424                                            "slapd_daemon_task: connection_init(%ld, %s, %s) failed.\n",
1425                                            (long)s, peername, slap_listeners[l]->sl_name ));
1426 #else
1427                                 Debug( LDAP_DEBUG_ANY,
1428                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
1429                                         (long) s,
1430                                         peername,
1431                                         slap_listeners[l]->sl_name );
1432 #endif
1433                                 slapd_close(s);
1434                                 continue;
1435                         }
1436
1437                         Statslog( LDAP_DEBUG_STATS,
1438                                 "daemon: conn=%ld fd=%ld connection from %s (%s) accepted.\n",
1439                                 id, (long) s,
1440                                 peername,
1441                                 slap_listeners[l]->sl_name,
1442                                 0 );
1443
1444                         slapd_add( s );
1445                         continue;
1446                 }
1447
1448 #ifdef LDAP_DEBUG
1449 #ifdef NEW_LOGGING
1450                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1451                            "slapd_daemon_task: activity on " ));
1452 #else
1453                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
1454 #endif
1455 #ifdef HAVE_WINSOCK
1456                 for ( i = 0; i < readfds.fd_count; i++ ) {
1457 #ifdef NEW_LOGGING
1458                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1459                                    " %d%s", readfds.fd_array[i], "r", 0 ));
1460 #else
1461                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1462                                 readfds.fd_array[i], "r", 0 );
1463 #endif
1464                 }
1465                 for ( i = 0; i < writefds.fd_count; i++ ) {
1466 #ifdef NEW_LOGGING
1467                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1468                                    " %d%s", writefds.fd_array[i], "w" ));
1469 #else
1470                         Debug( LDAP_DEBUG_CONNS, " %d%s",
1471                                 writefds.fd_array[i], "w", 0 );
1472 #endif
1473                 }
1474
1475 #else
1476                 for ( i = 0; i < nfds; i++ ) {
1477                         int     r, w;
1478                         int     is_listener = 0;
1479
1480                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1481                                 if ( i == slap_listeners[l]->sl_sd ) {
1482 #ifdef LDAP_CONNECTIONLESS
1483                                 /* The listener is the data port. Don't
1484                                  * skip it.
1485                                  */
1486                                         if (slap_listeners[l]->sl_is_udp)
1487                                                 continue;
1488 #endif
1489                                         is_listener = 1;
1490                                         break;
1491                                 }
1492                         }
1493                         if ( is_listener ) {
1494                                 continue;
1495                         }
1496                         r = FD_ISSET( i, &readfds );
1497                         w = FD_ISSET( i, &writefds );
1498                         if ( r || w ) {
1499 #ifdef NEW_LOGGING
1500                                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1501                                            " %d%s%s", i,
1502                                            r ? "r" : "", w ? "w" : "" ));
1503 #else
1504                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
1505                                     r ? "r" : "", w ? "w" : "" );
1506 #endif
1507                         }
1508                 }
1509 #endif
1510 #ifdef NEW_LOGGING
1511                 LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2, "\n" ));
1512 #else
1513                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
1514 #endif
1515
1516 #endif
1517
1518                 /* loop through the writers */
1519 #ifdef HAVE_WINSOCK
1520                 for ( i = 0; i < writefds.fd_count; i++ )
1521 #else
1522                 for ( i = 0; i < nfds; i++ )
1523 #endif
1524                 {
1525                         ber_socket_t wd;
1526                         int is_listener = 0;
1527 #ifdef HAVE_WINSOCK
1528                         wd = writefds.fd_array[i];
1529 #else
1530                         if( ! FD_ISSET( i, &writefds ) ) {
1531                                 continue;
1532                         }
1533                         wd = i;
1534 #endif
1535
1536                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1537                                 if ( i == slap_listeners[l]->sl_sd ) {
1538 #ifdef LDAP_CONNECTIONLESS
1539                                         if (slap_listeners[l]->sl_is_udp)
1540                                                 continue;
1541 #endif
1542                                         is_listener = 1;
1543                                         break;
1544                                 }
1545                         }
1546                         if ( is_listener ) {
1547                                 continue;
1548                         }
1549 #ifdef NEW_LOGGING
1550                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1551                                    "slapd_daemon_task: write active on %d\n", wd ));
1552 #else
1553                         Debug( LDAP_DEBUG_CONNS,
1554                                 "daemon: write active on %d\n",
1555                                 wd, 0, 0 );
1556 #endif
1557                         /*
1558                          * NOTE: it is possible that the connection was closed
1559                          * and that the stream is now inactive.
1560                          * connection_write() must valid the stream is still
1561                          * active.
1562                          */
1563
1564                         if ( connection_write( wd ) < 0 ) {
1565                                 FD_CLR( (unsigned) wd, &readfds );
1566                                 slapd_close( wd );
1567                         }
1568                 }
1569
1570 #ifdef HAVE_WINSOCK
1571                 for ( i = 0; i < readfds.fd_count; i++ )
1572 #else
1573                 for ( i = 0; i < nfds; i++ )
1574 #endif
1575                 {
1576                         ber_socket_t rd;
1577                         int is_listener = 0;
1578
1579 #ifdef HAVE_WINSOCK
1580                         rd = readfds.fd_array[i];
1581 #else
1582                         if( ! FD_ISSET( i, &readfds ) ) {
1583                                 continue;
1584                         }
1585                         rd = i;
1586 #endif
1587
1588                         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1589                                 if ( rd == slap_listeners[l]->sl_sd ) {
1590 #ifdef LDAP_CONNECTIONLESS
1591                                         if (slap_listeners[l]->sl_is_udp)
1592                                                 continue;
1593 #endif
1594                                         is_listener = 1;
1595                                         break;
1596                                 }
1597                         }
1598                         if ( is_listener ) {
1599                                 continue;
1600                         }
1601
1602 #ifdef NEW_LOGGING
1603                         LDAP_LOG(( "connection", LDAP_LEVEL_DETAIL2,
1604                                    "slapd_daemon_task: read activity on %d\n", rd ));
1605 #else
1606                         Debug ( LDAP_DEBUG_CONNS,
1607                                 "daemon: read activity on %d\n", rd, 0, 0 );
1608 #endif
1609                         /*
1610                          * NOTE: it is possible that the connection was closed
1611                          * and that the stream is now inactive.
1612                          * connection_read() must valid the stream is still
1613                          * active.
1614                          */
1615
1616                         if ( connection_read( rd ) < 0 ) {
1617                                 slapd_close( rd );
1618                         }
1619                 }
1620                 ldap_pvt_thread_yield();
1621         }
1622
1623         if( slapd_shutdown > 0 ) {
1624 #ifdef NEW_LOGGING
1625                 LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1626                            "slapd_daemon_task: shutdown requested and initiated.\n"));
1627 #else
1628                 Debug( LDAP_DEBUG_TRACE,
1629                         "daemon: shutdown requested and initiated.\n",
1630                         0, 0, 0 );
1631 #endif
1632
1633         } else if ( slapd_shutdown < 0 ) {
1634 #ifdef HAVE_NT_SERVICE_MANAGER
1635                 if (slapd_shutdown == -1)
1636                 {
1637 #ifdef NEW_LOGGING
1638                         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1639                                    "slapd_daemon_task: shutdown initiated by Service Manager.\n"));
1640 #else
1641                         Debug( LDAP_DEBUG_TRACE,
1642                                "daemon: shutdown initiated by Service Manager.\n",
1643                                0, 0, 0);
1644 #endif
1645                 }
1646                 else
1647 #endif
1648                 {
1649 #ifdef NEW_LOGGING
1650                         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1651                                    "slapd_daemon_task: abnormal condition, shutdown initiated.\n" ));
1652 #else
1653                         Debug( LDAP_DEBUG_TRACE,
1654                                "daemon: abnormal condition, shutdown initiated.\n",
1655                                0, 0, 0 );
1656 #endif
1657                 }
1658         } else {
1659 #ifdef NEW_LOGGING
1660                 LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1661                            "slapd_daemon_task: no active streams, shutdown initiated.\n" ));
1662 #else
1663                 Debug( LDAP_DEBUG_TRACE,
1664                        "daemon: no active streams, shutdown initiated.\n",
1665                        0, 0, 0 );
1666 #endif
1667         }
1668
1669         for ( l = 0; slap_listeners[l] != NULL; l++ ) {
1670                 if ( slap_listeners[l]->sl_sd != AC_SOCKET_INVALID ) {
1671 #ifdef LDAP_PF_LOCAL
1672                         if ( slap_listeners[l]->sl_sa.sa_addr.sa_family == AF_LOCAL ) {
1673                                 unlink( slap_listeners[l]->sl_sa.sa_un_addr.sun_path );
1674                         }
1675 #endif /* LDAP_PF_LOCAL */
1676                         slapd_close( slap_listeners[l]->sl_sd );
1677                 }
1678                 if ( slap_listeners[l]->sl_url )
1679                         free ( slap_listeners[l]->sl_url );
1680                 if ( slap_listeners[l]->sl_name )
1681                         free ( slap_listeners[l]->sl_name );
1682                 free ( slap_listeners[l] );
1683         }
1684         free ( slap_listeners );
1685         slap_listeners = NULL;
1686
1687 #ifdef NEW_LOGGING
1688         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1689                    "slapd_daemon_task: shutdown waiting for %d threads to terminate.\n",
1690                    ldap_pvt_thread_pool_backload(&connection_pool) ));
1691 #else
1692         Debug( LDAP_DEBUG_ANY,
1693             "slapd shutdown: waiting for %d threads to terminate\n",
1694             ldap_pvt_thread_pool_backload(&connection_pool), 0, 0 );
1695 #endif
1696         ldap_pvt_thread_pool_destroy(&connection_pool, 1);
1697
1698         return NULL;
1699 }
1700
1701
1702 int slapd_daemon( void )
1703 {
1704         int rc;
1705
1706         connections_init();
1707
1708 #define SLAPD_LISTENER_THREAD 1
1709 #if defined( SLAPD_LISTENER_THREAD )
1710         {
1711                 ldap_pvt_thread_t       listener_tid;
1712
1713                 /* listener as a separate THREAD */
1714                 rc = ldap_pvt_thread_create( &listener_tid,
1715                         0, slapd_daemon_task, NULL );
1716
1717                 if ( rc != 0 ) {
1718 #ifdef NEW_LOGGING
1719                         LDAP_LOG(( "connection", LDAP_LEVEL_ERR,
1720                                    "slapd_daemon: listener ldap_pvt_thread_create failed (%d).\n", rc ));
1721 #else
1722                         Debug( LDAP_DEBUG_ANY,
1723                         "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
1724 #endif
1725                         return rc;
1726                 }
1727  
1728                 /* wait for the listener thread to complete */
1729                 ldap_pvt_thread_join( listener_tid, (void *) NULL );
1730         }
1731 #else
1732         /* experimental code */
1733         slapd_daemon_task( NULL );
1734 #endif
1735
1736         return 0;
1737
1738 }
1739
1740 int sockinit(void)
1741 {
1742 #if defined( HAVE_WINSOCK2 )
1743     WORD wVersionRequested;
1744         WSADATA wsaData;
1745         int err;
1746
1747         wVersionRequested = MAKEWORD( 2, 0 );
1748
1749         err = WSAStartup( wVersionRequested, &wsaData );
1750         if ( err != 0 ) {
1751                 /* Tell the user that we couldn't find a usable */
1752                 /* WinSock DLL.                                  */
1753                 return -1;
1754         }
1755
1756         /* Confirm that the WinSock DLL supports 2.0.*/
1757         /* Note that if the DLL supports versions greater    */
1758         /* than 2.0 in addition to 2.0, it will still return */
1759         /* 2.0 in wVersion since that is the version we      */
1760         /* requested.                                        */
1761
1762         if ( LOBYTE( wsaData.wVersion ) != 2 ||
1763                 HIBYTE( wsaData.wVersion ) != 0 )
1764         {
1765             /* Tell the user that we couldn't find a usable */
1766             /* WinSock DLL.                                  */
1767             WSACleanup();
1768             return -1;
1769         }
1770
1771         /* The WinSock DLL is acceptable. Proceed. */
1772 #elif defined( HAVE_WINSOCK )
1773         WSADATA wsaData;
1774         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
1775             return -1;
1776         }
1777 #endif
1778         return 0;
1779 }
1780
1781 int sockdestroy(void)
1782 {
1783 #if defined( HAVE_WINSOCK2 ) || defined( HAVE_WINSOCK )
1784         WSACleanup();
1785 #endif
1786         return 0;
1787 }
1788
1789 RETSIGTYPE
1790 slap_sig_shutdown( int sig )
1791 {
1792 #ifdef NEW_LOGGING
1793         LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1794                    "slap_sig_shutdown: signal %d\n", sig ));
1795 #else
1796         Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: signal %d\n", sig, 0, 0);
1797 #endif
1798
1799         /*
1800          * If the NT Service Manager is controlling the server, we don't
1801          * want SIGBREAK to kill the server. For some strange reason,
1802          * SIGBREAK is generated when a user logs out.
1803          */
1804
1805 #if HAVE_NT_SERVICE_MANAGER && SIGBREAK
1806         if (is_NT_Service && sig == SIGBREAK)
1807 #ifdef NEW_LOGGING
1808             LDAP_LOG(( "connection", LDAP_LEVEL_CRIT,
1809                        "slap_sig_shutdown: SIGBREAK ignored.\n" ));
1810 #else
1811             Debug(LDAP_DEBUG_TRACE, "slap_sig_shutdown: SIGBREAK ignored.\n",
1812                   0, 0, 0);
1813 #endif
1814         else
1815 #endif
1816         slapd_shutdown = sig;
1817
1818         WAKE_LISTENER(1);
1819
1820         /* reinstall self */
1821         (void) SIGNAL_REINSTALL( sig, slap_sig_shutdown );
1822 }
1823
1824 RETSIGTYPE
1825 slap_sig_wake( int sig )
1826 {
1827         WAKE_LISTENER(1);
1828
1829         /* reinstall self */
1830         (void) SIGNAL_REINSTALL( sig, slap_sig_wake );
1831 }
1832
1833
1834 void slapd_add_internal(ber_socket_t s) {
1835         slapd_add(s);
1836 }