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