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