5 * Added locking of new_conn_mutex when traversing the c[] array.
14 #include <ac/signal.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
18 #include <ac/unistd.h>
20 #include "ldapconfig.h"
23 #ifdef HAVE_SYS_FILIO_H
24 #include <sys/filio.h>
25 #elif HAVE_SYS_IOCTL_H
26 #include <sys/ioctl.h>
32 int allow_severity = LOG_INFO;
33 int deny_severity = LOG_NOTICE;
34 #endif /* TCP Wrappers */
39 static volatile sig_atomic_t slapd_shutdown = 0;
40 static void set_shutdown(int sig);
41 static void do_nothing (int sig);
43 /* a link to the slapd.conf configuration parameters */
44 extern char *slapd_pid_file;
45 extern char *slapd_args_file;
54 unsigned long len, tag, msgid;
57 struct sockaddr_in addr;
64 dtblsize = sysconf( _SC_OPEN_MAX );
65 #elif HAVE_GETDTABLESIZE
66 dtblsize = getdtablesize();
72 if(dtblsize > FD_SETSIZE) {
73 dtblsize = FD_SETSIZE;
75 #endif /* !FD_SETSIZE */
77 c = (Connection *) ch_calloc( 1, dtblsize * sizeof(Connection) );
79 for ( i = 0; i < dtblsize; i++ ) {
86 c[i].c_sb.sb_options = LBER_NO_READ_AHEAD;
87 c[i].c_sb.sb_naddr = 0;
88 c[i].c_sb.sb_ber.ber_buf = NULL;
89 c[i].c_sb.sb_ber.ber_ptr = NULL;
90 c[i].c_sb.sb_ber.ber_end = NULL;
91 c[i].c_writewaiter = 0;
93 pthread_mutex_init( &c[i].c_dnmutex,
94 pthread_mutexattr_default );
95 pthread_mutex_init( &c[i].c_opsmutex,
96 pthread_mutexattr_default );
97 pthread_mutex_init( &c[i].c_pdumutex,
98 pthread_mutexattr_default );
99 pthread_cond_init( &c[i].c_wcv, pthread_condattr_default );
102 if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
103 Debug( LDAP_DEBUG_ANY, "socket() failed errno %d (%s)", errno,
104 errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
110 if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR, (char *) &i,
111 sizeof(i) ) == -1 ) {
112 Debug( LDAP_DEBUG_ANY, "setsockopt() failed errno %d (%s)",
113 errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
117 (void) memset( (void *) &addr, '\0', sizeof(addr) );
118 addr.sin_family = AF_INET;
119 addr.sin_addr.s_addr = INADDR_ANY;
120 addr.sin_port = htons( (int)port );
121 if ( bind( tcps, (struct sockaddr *) &addr, sizeof(addr) ) == -1 ) {
122 Debug( LDAP_DEBUG_ANY, "bind() failed errno %d (%s)\n",
123 errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
128 if ( listen( tcps, 5 ) == -1 ) {
129 Debug( LDAP_DEBUG_ANY, "listen() failed errno %d (%s)",
130 errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno] :
135 (void) SIGNAL( SIGPIPE, SIG_IGN );
136 (void) SIGNAL( LDAP_SIGUSR1, do_nothing );
137 (void) SIGNAL( LDAP_SIGUSR2, set_shutdown );
138 (void) SIGNAL( SIGTERM, set_shutdown );
139 (void) SIGNAL( SIGINT, set_shutdown );
140 (void) SIGNAL( SIGHUP, set_shutdown );
142 Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
144 if (( slapd_pid_file != NULL ) &&
145 (( fp = fopen( slapd_pid_file, "w" )) != NULL )) {
146 fprintf( fp, "%d\n", (int) getpid() );
150 if (( slapd_args_file != NULL ) &&
151 (( fp = fopen( slapd_args_file, "w" )) != NULL )) {
152 for ( i = 0; i < g_argc; i++ ) {
153 fprintf( fp, "%s ", g_argv[i] );
159 while ( !slapd_shutdown ) {
160 struct sockaddr_in from;
169 FD_ZERO( &writefds );
171 FD_SET( tcps, &readfds );
176 pthread_mutex_lock( &active_threads_mutex );
177 Debug( LDAP_DEBUG_CONNS,
178 "listening for connections on %d, activity on:",
181 pthread_mutex_lock( &new_conn_mutex );
182 for ( i = 0; i < dtblsize; i++ ) {
183 if ( c[i].c_sb.sb_sd != -1 ) {
184 FD_SET( c[i].c_sb.sb_sd, &readfds );
186 if ( c[i].c_writewaiter ) {
187 FD_SET( c[i].c_sb.sb_sd, &writefds );
189 Debug( LDAP_DEBUG_CONNS, " %dr%s", i,
190 c[i].c_writewaiter ? "w" : "", 0 );
193 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
194 pthread_mutex_unlock( &new_conn_mutex );
196 Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
197 active_threads, 0, 0 );
198 #if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
201 tvp = active_threads ? &zero : NULL;
203 pthread_mutex_unlock( &active_threads_mutex );
205 switch ( i = select( dtblsize, &readfds, &writefds, 0, tvp ) ) {
206 case -1: /* failure - try again */
207 Debug( LDAP_DEBUG_CONNS,
208 "select failed errno %d (%s)\n",
209 errno, errno > -1 && errno < sys_nerr ?
210 sys_errlist[errno] : "unknown", 0 );
213 case 0: /* timeout - let threads run */
214 Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n",
219 default: /* something happened - deal with it */
220 Debug( LDAP_DEBUG_CONNS, "select activity on %d descriptors\n", i, 0, 0 );
223 pthread_mutex_lock( ¤ttime_mutex );
224 time( ¤ttime );
225 pthread_mutex_unlock( ¤ttime_mutex );
228 pthread_mutex_lock( &new_conn_mutex );
229 if ( FD_ISSET( tcps, &readfds ) ) {
231 if ( (ns = accept( tcps, (struct sockaddr *) &from,
233 Debug( LDAP_DEBUG_ANY,
234 "accept() failed errno %d (%s)", errno,
235 errno > -1 && errno < sys_nerr ?
236 sys_errlist[errno] : "unknown", 0 );
237 pthread_mutex_unlock( &new_conn_mutex );
240 if ( ioctl( ns, FIONBIO, (caddr_t) &on ) == -1 ) {
241 Debug( LDAP_DEBUG_ANY,
242 "FIONBIO ioctl on %d failed\n", ns, 0, 0 );
245 Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
250 if ( getpeername( ns, (struct sockaddr *) &from, &len )
253 client_addr = inet_ntoa( from.sin_addr );
255 #if defined(SLAPD_RLOOKUPS) || defined(HAVE_TCPD)
256 hp = gethostbyaddr( (char *)
257 &(from.sin_addr.s_addr),
258 sizeof(from.sin_addr.s_addr), AF_INET );
261 client_name = hp->h_name;
263 /* normalize the domain */
264 for ( s = client_name; *s; s++ ) {
281 if(!hosts_ctl("slapd",
282 client_name != NULL ? client_name : STRING_UNKNOWN,
283 client_addr != NULL ? client_addr : STRING_UNKNOWN,
287 Statslog( LDAP_DEBUG_ANY,
288 "fd=%d connection from %s (%s) denied.\n",
290 client_name == NULL ? "unknown" : client_name,
291 client_addr == NULL ? "unknown" : client_addr,
295 pthread_mutex_unlock( &new_conn_mutex );
298 #endif /* HAVE_TCPD */
300 c[ns].c_sb.sb_sd = ns;
301 pthread_mutex_lock( &ops_mutex );
302 c[ns].c_connid = num_conns++;
303 pthread_mutex_unlock( &ops_mutex );
305 Statslog( LDAP_DEBUG_STATS,
306 "conn=%d fd=%d connection from %s (%s) accepted.\n",
308 client_name == NULL ? "unknown" : client_name,
309 client_addr == NULL ? "unknown" : client_addr,
312 if ( c[ns].c_addr != NULL ) {
313 free( c[ns].c_addr );
315 c[ns].c_addr = ch_strdup( client_addr );
317 if ( c[ns].c_domain != NULL ) {
318 free( c[ns].c_domain );
321 c[ns].c_domain = ch_strdup( client_name == NULL
322 ? "" : client_name );
324 pthread_mutex_lock( &c[ns].c_dnmutex );
325 if ( c[ns].c_dn != NULL ) {
329 if ( c[ns].c_cdn != NULL ) {
333 pthread_mutex_unlock( &c[ns].c_dnmutex );
334 c[ns].c_starttime = currenttime;
335 c[ns].c_opsinitiated = 0;
336 c[ns].c_opscompleted = 0;
338 pthread_mutex_unlock( &new_conn_mutex );
340 Debug( LDAP_DEBUG_CONNS, "activity on:", 0, 0, 0 );
341 for ( i = 0; i < dtblsize; i++ ) {
344 r = FD_ISSET( i, &readfds );
345 w = FD_ISSET( i, &writefds );
346 if ( i != tcps && (r || w) ) {
347 Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
348 r ? "r" : "", w ? "w" : "" );
351 Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
353 for ( i = 0; i < dtblsize; i++ ) {
354 if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
355 ! FD_ISSET( i, &writefds )) ) {
359 if ( FD_ISSET( i, &writefds ) ) {
360 Debug( LDAP_DEBUG_CONNS,
361 "signaling write waiter on %d\n", i, 0, 0 );
363 pthread_mutex_lock( &active_threads_mutex );
364 pthread_cond_signal( &c[i].c_wcv );
365 c[i].c_writewaiter = 0;
367 pthread_mutex_unlock( &active_threads_mutex );
370 if ( FD_ISSET( i, &readfds ) ) {
371 Debug( LDAP_DEBUG_CONNS,
372 "read activity on %d\n", i, 0, 0 );
374 connection_activity( &c[i] );
383 pthread_mutex_lock( &active_threads_mutex );
384 Debug( LDAP_DEBUG_ANY,
385 "slapd shutting down - waiting for %d threads to terminate\n",
386 active_threads, 0, 0 );
387 while ( active_threads > 0 ) {
388 pthread_cond_wait(&active_threads_cond, &active_threads_mutex);
390 pthread_mutex_unlock( &active_threads_mutex );
392 /* let backends do whatever cleanup they need to do */
393 Debug( LDAP_DEBUG_TRACE,
394 "slapd shutting down - waiting for backends to close down\n", 0, 0,
397 Debug( LDAP_DEBUG_ANY, "slapd stopping\n", 0, 0, 0 );
402 set_shutdown( int sig )
404 Debug( LDAP_DEBUG_ANY, "slapd got shutdown signal %d\n", sig, 0, 0 );
406 pthread_kill( listener_tid, LDAP_SIGUSR1 );
407 (void) SIGNAL( LDAP_SIGUSR2, set_shutdown );
408 (void) SIGNAL( SIGTERM, set_shutdown );
409 (void) SIGNAL( SIGINT, set_shutdown );
410 (void) SIGNAL( SIGHUP, set_shutdown );
414 do_nothing( int sig )
416 Debug( LDAP_DEBUG_TRACE, "slapd got do_nothing signal %d\n", sig, 0, 0 );
417 (void) SIGNAL( LDAP_SIGUSR1, do_nothing );