]> git.sur5r.net Git - openldap/blob - servers/slapd/daemon.c
eb26b8feded137a5058ee9e6029907d0e708c733
[openldap] / servers / slapd / daemon.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/ctype.h>
6 #include <ac/errno.h>
7 #include <ac/signal.h>
8 #include <ac/socket.h>
9 #include <ac/string.h>
10 #include <ac/time.h>
11 #include <ac/unistd.h>
12
13 #include "ldap_defaults.h"
14 #include "slap.h"
15
16 #ifdef HAVE_TCPD
17 #include <tcpd.h>
18
19 int allow_severity = LOG_INFO;
20 int deny_severity = LOG_NOTICE;
21 #endif /* TCP Wrappers */
22
23 /* globals */
24 ber_socket_t dtblsize;
25 static ber_socket_t tcps;
26
27 #ifdef HAVE_WINSOCK2
28 /* in nt_main.c */
29 extern ldap_pvt_thread_cond_t                   started_event;
30
31 /* forward reference */
32 void hit_socket();
33 /* In wsa_err.c */
34 char *WSAGetLastErrorString();
35 static ldap_pvt_thread_t hit_tid;
36
37 #define WAKE_LISTENER(w) \
38 do {\
39     if( w ) {\
40         ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
41         hit_socket(); \
42     }\
43 } while(0)
44 #else
45 #define WAKE_LISTENER(w) \
46 do {\
47     if( w ) {\
48         ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );\
49     }\
50 } while(0)
51 #endif
52
53 #ifndef HAVE_WINSOCK
54 static 
55 #endif
56 volatile sig_atomic_t slapd_shutdown = 0;
57
58 static int daemon_initialized = 0;
59 static ldap_pvt_thread_t        listener_tid;
60 static volatile sig_atomic_t slapd_listener = 0;
61 void sockinit();
62
63 struct slap_daemon {
64         ldap_pvt_thread_mutex_t sd_mutex;
65
66         int sd_nactives;
67
68 #ifndef HAVE_WINSOCK
69         /* In winsock, accept() returns values higher than dtblsize
70                 so don't bother with this optimization */
71         int sd_nfds;
72 #endif
73
74         fd_set sd_actives;
75         fd_set sd_readers;
76         fd_set sd_writers;
77 } slap_daemon; 
78
79 /*
80  * Add a descriptor to daemon control
81  */
82 static void slapd_add(ber_socket_t s) {
83         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
84
85         assert( !FD_ISSET( s, &slap_daemon.sd_actives ));
86         assert( !FD_ISSET( s, &slap_daemon.sd_readers ));
87         assert( !FD_ISSET( s, &slap_daemon.sd_writers ));
88
89 #ifndef HAVE_WINSOCK
90         if (s >= slap_daemon.sd_nfds) {
91                 slap_daemon.sd_nfds = s + 1;
92         }
93 #endif
94
95         FD_SET( s, &slap_daemon.sd_actives );
96         FD_SET( s, &slap_daemon.sd_readers );
97
98         Debug( LDAP_DEBUG_CONNS, "daemon: added %ld%s%s\n",
99                 (long) s,
100             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
101                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
102
103         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
104 }
105
106 /*
107  * Remove the descriptor from daemon control
108  */
109 void slapd_remove(ber_socket_t s, int wake) {
110         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
111         WAKE_LISTENER(wake);
112
113         Debug( LDAP_DEBUG_CONNS, "daemon: removing %ld%s%s\n",
114                 (long) s,
115             FD_ISSET(s, &slap_daemon.sd_readers) ? "r" : "",
116                 FD_ISSET(s, &slap_daemon.sd_writers) ? "w" : "" );
117
118         FD_CLR( s, &slap_daemon.sd_actives );
119         FD_CLR( s, &slap_daemon.sd_readers );
120         FD_CLR( s, &slap_daemon.sd_writers );
121
122         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
123 }
124
125 void slapd_clr_write(ber_socket_t s, int wake) {
126         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
127         WAKE_LISTENER(wake);
128
129         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
130         FD_CLR( s, &slap_daemon.sd_writers );
131
132         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
133
134         if( wake ) {
135                 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
136         }
137 }
138
139 void slapd_set_write(ber_socket_t s, int wake) {
140         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
141     WAKE_LISTENER(wake);
142
143         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
144         FD_SET( (unsigned) s, &slap_daemon.sd_writers );
145
146         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
147
148         if( wake ) {
149                 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
150         }
151 }
152
153 void slapd_clr_read(ber_socket_t s, int wake) {
154         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
155     WAKE_LISTENER(wake);
156
157         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
158         FD_CLR( s, &slap_daemon.sd_readers );
159
160         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
161
162         if( wake ) {
163                 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
164         }
165 }
166
167 void slapd_set_read(ber_socket_t s, int wake) {
168         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
169     WAKE_LISTENER(wake);
170
171         assert( FD_ISSET( s, &slap_daemon.sd_actives) );
172         FD_SET( s, &slap_daemon.sd_readers );
173
174         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
175
176         if( wake ) {
177                 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
178         }
179 }
180
181 static void slapd_close(ber_socket_t s) {
182         Debug( LDAP_DEBUG_CONNS, "daemon: closing %ld\n",
183                 (long) s, 0, 0 );
184         tcp_close(s);
185 }
186
187
188
189 int
190 set_socket( struct sockaddr_in *addr )
191 {
192         ber_socket_t    tcps = AC_SOCKET_INVALID;
193
194     if ( !daemon_initialized ) sockinit();
195
196 #ifdef HAVE_SYSCONF
197         dtblsize = sysconf( _SC_OPEN_MAX );
198 #elif HAVE_GETDTABLESIZE
199         dtblsize = getdtablesize();
200 #else
201         dtblsize = FD_SETSIZE;
202 #endif
203
204 #ifdef FD_SETSIZE
205         if(dtblsize > FD_SETSIZE) {
206                 dtblsize = FD_SETSIZE;
207         }
208 #endif  /* !FD_SETSIZE */
209
210         if( addr != NULL ) {
211                 int     tmp;
212
213                 if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID ) {
214 #ifndef HAVE_WINSOCK
215                         int err = errno;
216                         Debug( LDAP_DEBUG_ANY,
217                                 "daemon: socket() failed errno %d (%s)\n", err,
218                         err > -1 && err < sys_nerr ? sys_errlist[err] :
219                         "unknown", 0 );
220 #else
221                         Debug( LDAP_DEBUG_ANY, 
222                                 "daemon: socket() failed errno %d (%s)\n",
223                                 WSAGetLastError(),
224                         WSAGetLastErrorString(), 0 );
225 #endif
226                         return( -1 );
227                 }
228
229 #ifndef HAVE_WINSOCK
230                 if ( tcps >= dtblsize ) {
231                         Debug( LDAP_DEBUG_ANY,
232                                 "daemon: listener descriptor %ld is too great %ld\n",
233                                 (long) tcps, (long) dtblsize, 0 );
234                         return( -1);
235                 }
236 #endif
237
238 #ifdef SO_REUSEADDR
239                 tmp = 1;
240                 if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR,
241                         (char *) &tmp, sizeof(tmp) ) == -1 )
242                 {
243                         int err = errno;
244                         Debug( LDAP_DEBUG_ANY,
245                                "slapd(%ld): setsockopt() failed errno %d (%s)\n",
246                         (long) tcps, err,
247                                 err > -1 && err < sys_nerr
248                                         ? sys_errlist[err] : "unknown" );
249                 }
250 #endif
251 #ifdef SO_KEEPALIVE
252                 tmp = 1;
253                 if ( setsockopt( tcps, SOL_SOCKET, SO_KEEPALIVE,
254                         (char *) &tmp, sizeof(tmp) ) == -1 )
255                 {
256                         int err = errno;
257                         Debug( LDAP_DEBUG_ANY,
258                                 "slapd(%ld): setsockopt(KEEPALIVE) failed errno %d (%s)\n",
259                         (long) tcps, err,
260                                 err > -1 && err < sys_nerr
261                                         ? sys_errlist[err] : "unknown" );
262                 }
263 #endif
264
265
266                 if ( bind( tcps, (struct sockaddr *) addr, sizeof(*addr) ) == -1 ) {
267                         int err = errno;
268                         Debug( LDAP_DEBUG_ANY, "daemon: bind(%ld) failed errno %d (%s)\n",
269                         (long) tcps, err,
270                                 err > -1 && err < sys_nerr
271                                         ? sys_errlist[err] : "unknown" );
272                         return -1;
273                 }
274         }
275
276         return tcps;
277 }
278
279 static void *
280 slapd_daemon_task(
281         void *ptr
282 )
283 {
284         int inetd;
285         struct slapd_args *args = (struct slapd_args *) ptr;
286         struct sockaddr_in *slapd_addr = args->addr;
287
288         tcps  = args->tcps;
289
290         inetd = ( slapd_addr == NULL);
291     if ( !daemon_initialized ) sockinit();
292
293         slapd_listener=1;
294
295         ldap_pvt_thread_mutex_init( &slap_daemon.sd_mutex );
296         FD_ZERO( &slap_daemon.sd_readers );
297         FD_ZERO( &slap_daemon.sd_writers );
298
299         if( !inetd ) {
300                 if ( listen( tcps, 5 ) == -1 ) {
301                         int err = errno;
302                         Debug( LDAP_DEBUG_ANY,
303                                 "daemon: listen(%ld, 5) failed errno %d (%s)\n",
304                             (long) tcps, err,
305                                 err > -1 && err < sys_nerr
306                                         ? sys_errlist[err] : "unknown" );
307                         return( (void*)-1 );
308                 }
309
310                 slapd_add( tcps );
311
312         } else {
313                 if( connection_init( (ber_socket_t) 0, NULL, NULL ) ) {
314                         Debug( LDAP_DEBUG_ANY,
315                                 "connection_init(%d) failed.\n",
316                                 0, 0, 0 );
317                         return( (void*)-1 );
318                 }
319
320                 slapd_add( 0 );
321         }
322
323 #ifdef HAVE_WINSOCK
324         if ( started_event != NULL )
325                 ldap_pvt_thread_cond_signal( &started_event );
326 #endif
327         /* initialization complete. Here comes the loop. */
328
329         while ( !slapd_shutdown ) {
330                 ber_socket_t i;
331                 int ns;
332                 ber_socket_t nfds;
333                 int ebadf = 0;
334 #define SLAPD_EBADF_LIMIT 10
335
336                 fd_set                  readfds;
337                 fd_set                  writefds;
338
339                 struct sockaddr_in      from;
340 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
341         struct hostent          *hp;
342 #endif
343                 struct timeval          zero;
344                 struct timeval          *tvp;
345
346                 char    *client_name;
347                 char    *client_addr;
348
349                 FD_ZERO( &writefds );
350                 FD_ZERO( &readfds );
351
352                 zero.tv_sec = 0;
353                 zero.tv_usec = 0;
354
355                 ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
356
357 #ifdef FD_SET_MANUAL_COPY
358                 for( s = 0; s < nfds; s++ ) {
359                         if(FD_ISSET( &slap_sd_writers, s )) {
360                                 FD_SET( &writefds, s );
361                         }
362                         if(FD_ISSET( &slap_sd_writers, s )) {
363                                 FD_SET( &writefds, s );
364                         }
365                 }
366 #else
367                 memcpy( &readfds, &slap_daemon.sd_readers, sizeof(fd_set) );
368                 memcpy( &writefds, &slap_daemon.sd_writers, sizeof(fd_set) );
369 #endif
370
371                 FD_SET( (unsigned) tcps, &readfds );
372
373 #ifndef HAVE_WINSOCK
374                 nfds = slap_daemon.sd_nfds;
375 #else
376                 nfds = dtblsize;
377 #endif
378
379                 ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
380
381                 ldap_pvt_thread_mutex_lock( &active_threads_mutex );
382 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
383                 tvp = NULL;
384 #else
385                 tvp = active_threads ? &zero : NULL;
386 #endif
387
388                 Debug( LDAP_DEBUG_CONNS,
389                         "daemon: select: tcps=%d active_threads=%d tvp=%s\n",
390                     tcps, active_threads,
391                         tvp == NULL ? "NULL" : "zero" );
392            
393
394                 ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
395
396                 switch(ns = select( nfds, &readfds, &writefds, 0, tvp )) {
397                 case -1: {      /* failure - try again */
398 #ifdef HAVE_WINSOCK
399                                 int err = WSAGetLastError();
400 #else
401                                 int err = errno;
402 #endif
403
404                                 if( err == EBADF && ++ebadf < SLAPD_EBADF_LIMIT) {
405                                         continue;
406                                 }
407
408                                 if( err != EINTR ) {
409                                         Debug( LDAP_DEBUG_CONNS,
410                                                 "daemon: select failed (%d): %s\n",
411                                                 err,
412                                                 err >= 0 && err < sys_nerr
413                                                         ? sys_errlist[err] : "unknown",
414                                                 0 );
415
416
417                                 slapd_shutdown = -1;
418                                 }
419                         }
420                         continue;
421
422                 case 0:         /* timeout - let threads run */
423                         ebadf = 0;
424                         Debug( LDAP_DEBUG_CONNS, "daemon: select timeout - yielding\n",
425                             0, 0, 0 );
426                 ldap_pvt_thread_yield();
427                         continue;
428
429                 default:        /* something happened - deal with it */
430                         ebadf = 0;
431                         Debug( LDAP_DEBUG_CONNS, "daemon: activity on %d descriptors\n",
432                                 ns, 0, 0 );
433                         /* FALL THRU */
434                 }
435
436                 if ( FD_ISSET( tcps, &readfds ) ) {
437                         ber_int_t s;
438                         int len = sizeof(from);
439                         long id;
440
441                         if ( (s = accept( tcps,
442                                 (struct sockaddr *) &from, &len )) == AC_SOCKET_INVALID )
443                         {
444                                 int err = errno;
445                                 Debug( LDAP_DEBUG_ANY,
446                                     "daemon: accept(%ld) failed errno %d (%s)\n", err,
447                                     (long) tcps, err >= 0 && err < sys_nerr ?
448                                     sys_errlist[err] : "unknown");
449                                 continue;
450                         }
451
452 #ifdef LDAP_DEBUG
453                         ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
454
455                         /* newly accepted stream should not be in any of the FD SETS */
456
457                         assert( !FD_ISSET( s, &slap_daemon.sd_actives) );
458                         assert( !FD_ISSET( s, &slap_daemon.sd_readers) );
459                         assert( !FD_ISSET( s, &slap_daemon.sd_writers) );
460
461                         ldap_pvt_thread_mutex_unlock( &slap_daemon.sd_mutex );
462 #endif
463
464 #ifndef HAVE_WINSOCK
465                         /* make sure descriptor number isn't too great */
466                         if ( s >= dtblsize ) {
467                                 Debug( LDAP_DEBUG_ANY,
468                                         "daemon: %ld beyond descriptor table size %ld\n",
469                                         (long) s, (long) dtblsize, 0 );
470                                 slapd_close(s);
471                                 continue;
472                         }
473 #endif
474                    
475                         Debug( LDAP_DEBUG_CONNS, "daemon: new connection on %ld\n",
476                                 (long) s, 0, 0 );
477
478                         len = sizeof(from);
479                         if ( getpeername( s, (struct sockaddr *) &from, &len ) == 0 ) {
480                                 client_addr = inet_ntoa( from.sin_addr );
481
482 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
483                                 hp = gethostbyaddr( (char *)
484                                     &(from.sin_addr.s_addr),
485                                     sizeof(from.sin_addr.s_addr), AF_INET );
486
487                                 if(hp) {
488                                         char *p;
489                                         client_name = hp->h_name;
490
491                                         /* normalize the domain */
492                                         for ( p = client_name; *p; p++ ) {
493                                                 *p = TOLOWER( (unsigned char) *p );
494                                         }
495
496                                 } else {
497                                         client_name = NULL;
498                                 }
499 #else
500                                 client_name = NULL;
501 #endif
502
503                         } else {
504                                 client_name = NULL;;
505                                 client_addr = NULL;
506                         }
507
508 #ifdef HAVE_TCPD
509                         if(!hosts_ctl("slapd",
510                                 client_name != NULL ? client_name : STRING_UNKNOWN,
511                                 client_addr != NULL ? client_addr : STRING_UNKNOWN,
512                                 STRING_UNKNOWN))
513                         {
514                                 /* DENY ACCESS */
515                                 Statslog( LDAP_DEBUG_ANY,
516                                  "fd=%ld connection from %s (%s) denied.\n",
517                                         (long) s,
518                                         client_name == NULL ? "unknown" : client_name,
519                                         client_addr == NULL ? "unknown" : client_addr,
520                                   0, 0 );
521
522                                 slapd_close(s);
523                                 continue;
524                         }
525 #endif /* HAVE_TCPD */
526
527                         if( (id = connection_init(s, client_name, client_addr)) < 0 ) {
528                                 Debug( LDAP_DEBUG_ANY,
529                                         "daemon: connection_init(%ld, %s, %s) failed.\n",
530                                         (long) s,
531                                         client_name == NULL ? "unknown" : client_name,
532                                         client_addr == NULL ? "unknown" : client_addr);
533                                 slapd_close(s);
534                                 continue;
535                         }
536
537                         Statslog( LDAP_DEBUG_STATS,
538                                 "daemon: conn=%d fd=%ld connection from %s (%s) accepted.\n",
539                                 id, (long) s,
540                                 client_name == NULL ? "unknown" : client_name,
541                                 client_addr == NULL ? "unknown" : client_addr,
542                                 0 );
543
544                         slapd_add( s );
545                         continue;
546                 }
547
548 #ifdef LDAP_DEBUG
549                 Debug( LDAP_DEBUG_CONNS, "daemon: activity on:", 0, 0, 0 );
550 #ifdef HAVE_WINSOCK
551                 for ( i = 0; i < readfds.fd_count; i++ ) {
552                         Debug( LDAP_DEBUG_CONNS, " %d%s", readfds.fd_array[i], "r" );
553                 }
554                 for ( i = 0; i < writefds.fd_count; i++ ) {
555                         Debug( LDAP_DEBUG_CONNS, " %d%s", writefds.fd_array[i], "w" );
556                 }
557 #else
558                 for ( i = 0; i < nfds; i++ ) {
559                         int     a, r, w;
560
561                         r = FD_ISSET( i, &readfds );
562                         w = FD_ISSET( i, &writefds );
563                         if ( i != tcps && (r || w) ) {
564                                 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
565                                     r ? "r" : "", w ? "w" : "" );
566                         }
567                 }
568 #endif
569                 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
570 #endif
571
572                 /* loop through the writers */
573 #ifdef HAVE_WINSOCK
574                 for ( i = 0; i < writefds.fd_count; i++ )
575 #else
576                 for ( i = 0; i < nfds; i++ )
577 #endif
578                 {
579                         ber_socket_t wd;
580
581 #ifdef HAVE_WINSOCK
582                         wd = writefds.fd_array[i];
583 #else
584                         if( ! FD_ISSET( i, &writefds ) ) {
585                                 continue;
586                         }
587                         wd = i;
588 #endif
589
590                         if ( wd == tcps ) {
591                                 continue;
592                         }
593                         Debug( LDAP_DEBUG_CONNS,
594                                 "daemon: write active on %d\n",
595                                 wd, 0, 0 );
596
597                         /*
598                          * NOTE: it is possible that the connection was closed
599                          * and that the stream is now inactive.
600                          * connection_write() must valid the stream is still
601                          * active.
602                          */
603
604                         if ( connection_write( wd ) < 0 ) {
605                                 FD_CLR( (unsigned) wd, &readfds );
606                                 slapd_close( wd );
607                         }
608                 }
609
610 #ifdef HAVE_WINSOCK
611                 for ( i = 0; i < readfds.fd_count; i++ )
612 #else
613                 for ( i = 0; i < nfds; i++ )
614 #endif
615                 {
616                         ber_socket_t rd;
617
618 #ifdef HAVE_WINSOCK
619                         rd = readfds.fd_array[i];
620 #else
621                         if( ! FD_ISSET( i, &readfds ) ) {
622                                 continue;
623                         }
624                         rd = i;
625 #endif
626
627                         if ( rd == tcps ) {
628                                 continue;
629                         }
630
631                         Debug ( LDAP_DEBUG_CONNS,
632                                 "daemon: read activity on %d\n", rd, 0, 0 );
633
634                         /*
635                          * NOTE: it is possible that the connection was closed
636                          * and that the stream is now inactive.
637                          * connection_read() must valid the stream is still
638                          * active.
639                          */
640
641                         if ( connection_read( rd ) < 0 ) {
642                                 slapd_close( rd );
643                         }
644                 }
645                 ldap_pvt_thread_yield();
646         }
647
648         if( slapd_shutdown > 0 ) {
649                 Debug( LDAP_DEBUG_TRACE,
650                         "daemon: shutdown requested and initiated.\n",
651                         0, 0, 0 );
652
653         } else if ( slapd_shutdown < 0 ) {
654                 Debug( LDAP_DEBUG_TRACE,
655                         "daemon: abnormal condition, shutdown initiated.\n",
656                         0, 0, 0 );
657         } else {
658                 Debug( LDAP_DEBUG_TRACE,
659                         "daemon: no active streams, shutdown initiated.\n",
660                         0, 0, 0 );
661         }
662
663         if( tcps >= 0 ) {
664                 slapd_close( tcps );
665         }
666
667         ldap_pvt_thread_mutex_lock( &active_threads_mutex );
668         Debug( LDAP_DEBUG_ANY,
669             "slapd shutdown: waiting for %d threads to terminate\n",
670             active_threads, 0, 0 );
671         while ( active_threads > 0 ) {
672                 ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
673         }
674         ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
675
676         return NULL;
677 }
678
679
680 int slapd_daemon( struct slapd_args *args )
681 {
682         int rc;
683
684     if ( !daemon_initialized ) sockinit();
685
686         connections_init();
687
688 #define SLAPD_LISTENER_THREAD 1
689 #if defined( SLAPD_LISTENER_THREAD ) || !defined(HAVE_PTHREADS)
690
691         /* listener as a separate THREAD */
692         rc = ldap_pvt_thread_create( &listener_tid,
693                 0, slapd_daemon_task, args );
694
695         if ( rc != 0 ) {
696                 Debug( LDAP_DEBUG_ANY,
697                     "listener ldap_pvt_thread_create failed (%d)\n", rc, 0, 0 );
698                 goto destory;
699         }
700
701         /* wait for the listener thread to complete */
702         ldap_pvt_thread_join( listener_tid, (void *) NULL );
703 #else
704         /* expermimental code */
705         listener_tid = pthread_self();
706         slapd_daemon_task( args );
707 #endif
708
709         rc = 0;
710
711 destory:
712         connections_destroy();
713
714 #ifdef HAVE_WINSOCK
715     WSACleanup( );
716 #endif
717
718         return rc;
719 }
720
721 #ifdef HAVE_WINSOCK2
722 void sockinit()
723 {
724     WORD wVersionRequested;
725         WSADATA wsaData;
726         int err;
727  
728         wVersionRequested = MAKEWORD( 2, 0 );
729  
730         err = WSAStartup( wVersionRequested, &wsaData );
731         if ( err != 0 ) {
732                 /* Tell the user that we couldn't find a usable */
733                 /* WinSock DLL.                                  */
734                 return;
735         }
736  
737         /* Confirm that the WinSock DLL supports 2.0.*/
738         /* Note that if the DLL supports versions greater    */
739         /* than 2.0 in addition to 2.0, it will still return */
740         /* 2.0 in wVersion since that is the version we      */
741         /* requested.                                        */
742  
743         if ( LOBYTE( wsaData.wVersion ) != 2 ||
744                 HIBYTE( wsaData.wVersion ) != 0 )
745         {
746             /* Tell the user that we couldn't find a usable */
747             /* WinSock DLL.                                  */
748             WSACleanup( );
749             return; 
750         }
751     daemon_initialized = 1;
752 }       /* The WinSock DLL is acceptable. Proceed. */
753
754 void hit_socket()
755 {
756         ber_socket_t s;
757         int on = 1;
758         extern struct sockaddr_in       bind_addr;
759
760         /* throw something at the socket to terminate the select() in the daemon thread. */
761         if (( s = socket( AF_INET, SOCK_STREAM, 0 )) == AC_SOCKET_INVALID )
762                 Debug( LDAP_DEBUG_ANY,
763                         "slap_set_shutdown: socket failed\n\tWSAGetLastError=%d (%s)\n",
764                         WSAGetLastError(), WSAGetLastErrorString(), 0 );
765
766         if ( ioctlsocket( s, FIONBIO, &on ) == -1 ) 
767                 Debug( LDAP_DEBUG_ANY,
768                         "slap_set_shutdown:FIONBIO ioctl on %d faled\n\tWSAGetLastError=%d (%s)\n",
769                         s, WSAGetLastError(), WSAGetLastError() );
770         
771         bind_addr.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
772
773         if ( connect( s, (struct sockaddr *)&bind_addr, sizeof( struct sockaddr_in )) == SOCKET_ERROR ) {
774                 Debug( LDAP_DEBUG_ANY,
775                         "hit_socket: error on connect: %d\n", WSAGetLastError(), 0 );
776                 /* we can probably expect some error to occur here, mostly WSAEWOULDBLOCK */
777         }
778
779         tcp_close(s);
780 }
781
782 #elif HAVE_WINSOCK
783 void sockinit()
784 {       WSADATA wsaData;
785         if ( WSAStartup( 0x0101, &wsaData ) != 0 ) {
786             return( NULL );
787         }
788     daemon_initialized = 1;
789 }
790 #else
791 void sockinit()
792 {
793     daemon_initialized = 1;
794 }
795 #endif
796
797 void
798 slap_set_shutdown( int sig )
799 {
800         slapd_shutdown = sig;
801 #ifndef HAVE_WINSOCK
802         if(slapd_listener) {
803                 ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
804         }
805 #else
806         Debug( LDAP_DEBUG_TRACE, "Shutdown %d ordered", sig, 0 );
807         /* trying to "hit" the socket seems to always get a */
808         /* EWOULDBLOCK error, so just close the listen socket to */
809         /* break out of the select since we're shutting down anyway */
810         tcp_close( tcps );
811 #endif
812         /* reinstall self */
813         (void) SIGNAL( sig, slap_set_shutdown );
814 }
815
816 void
817 slap_do_nothing( int sig )
818 {
819         /* reinstall self */
820         (void) SIGNAL( sig, slap_do_nothing );
821 }