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