daemon.c 10.5 KB
Newer Older
1
2
3
4
5
6
7

/* Revision history
 *
 * 5-Jun-96	hodges
 *	Added locking of new_conn_mutex when traversing the c[] array.
 */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
8
#include "portable.h"
9
10
11
12
13
14
15
16
17
18
19

#include <stdio.h>

#include <ac/ctype.h>
#include <ac/errno.h>
#include <ac/signal.h>
#include <ac/socket.h>
#include <ac/string.h>
#include <ac/time.h>
#include <ac/unistd.h>

Kurt Zeilenga's avatar
Kurt Zeilenga committed
20
#include "ldapconfig.h"
21
22
23
#include "slap.h"

#ifdef HAVE_SYS_FILIO_H
Kurt Zeilenga's avatar
Kurt Zeilenga committed
24
#include <sys/filio.h>
25
#elif HAVE_SYS_IOCTL_H
Kurt Zeilenga's avatar
Kurt Zeilenga committed
26
#include <sys/ioctl.h>
27
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
28

29
30
#ifdef HAVE_TCPD
#include <tcpd.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
31

32
33
34
int allow_severity = LOG_INFO;
int deny_severity = LOG_NOTICE;
#endif /* TCP Wrappers */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
35
36
37
38

int		dtblsize;
Connection	*c;

39
static int slapd_shutdown = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
40

41
42
43
/* a link to the slapd.conf configuration parameters */
extern char *slapd_pid_file;
extern char *slapd_args_file;
44

45
46
47
void *
slapd_daemon(
    void *port
Kurt Zeilenga's avatar
Kurt Zeilenga committed
48
49
50
51
52
53
54
55
56
57
58
59
60
)
{
	Operation		*o;
	BerElement		ber;
	unsigned long		len, tag, msgid;
	int			i;
	int			tcps, ns;
	struct sockaddr_in	addr;
	fd_set			readfds;
	fd_set			writefds;
	FILE			*fp;
	int			on = 1;

61
62
63
64
65
66
67
68
69
70
71
72
73
#ifdef HAVE_SYSCONF
	dtblsize = sysconf( _SC_OPEN_MAX );
#elif HAVE_GETDTABLESIZE
	dtblsize = getdtablesize();
#else
	dtblsize = FD_SETSIZE
#endif

#ifdef FD_SETSIZE
	if(dtblsize > FD_SETSIZE) {
		dtblsize = FD_SETSIZE;
	}
#endif	/* !FD_SETSIZE */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
74
75
76
77
78

	c = (Connection *) ch_calloc( 1, dtblsize * sizeof(Connection) );

	for ( i = 0; i < dtblsize; i++ ) {
		c[i].c_dn = NULL;
79
		c[i].c_cdn = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
80
81
82
83
84
85
86
87
88
		c[i].c_addr = NULL;
		c[i].c_domain = NULL;
		c[i].c_ops = NULL;
		c[i].c_sb.sb_sd = -1;
		c[i].c_sb.sb_options = LBER_NO_READ_AHEAD;
		c[i].c_sb.sb_naddr = 0;
		c[i].c_sb.sb_ber.ber_buf = NULL;
		c[i].c_sb.sb_ber.ber_ptr = NULL;
		c[i].c_sb.sb_ber.ber_end = NULL;
89
		c[i].c_sb.sb_max_incoming = 1 << 18;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
90
91
		c[i].c_writewaiter = 0;
		c[i].c_connid = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
92
93
94
95
		ldap_pvt_thread_mutex_init( &c[i].c_dnmutex );
		ldap_pvt_thread_mutex_init( &c[i].c_opsmutex );
		ldap_pvt_thread_mutex_init( &c[i].c_pdumutex );
		ldap_pvt_thread_cond_init( &c[i].c_wcv );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
97
98
	}

	if ( (tcps = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
99
100
101
		int err = errno;
		Debug( LDAP_DEBUG_ANY, "socket() failed errno %d (%s)", err,
		    err > -1 && err < sys_nerr ? sys_errlist[err] :
Kurt Zeilenga's avatar
Kurt Zeilenga committed
102
103
104
105
106
107
108
		    "unknown", 0 );
		exit( 1 );
	}

	i = 1;
	if ( setsockopt( tcps, SOL_SOCKET, SO_REUSEADDR, (char *) &i,
	    sizeof(i) ) == -1 ) {
109
		int err = errno;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
110
		Debug( LDAP_DEBUG_ANY, "setsockopt(reuse) failed errno %d (%s)",
111
		    err, err > -1 && err < sys_nerr ? sys_errlist[err] :
Kurt Zeilenga's avatar
Kurt Zeilenga committed
112
113
114
		    "unknown", 0 );
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
115
116
117
118
#ifdef SO_KEEPALIVE
	i = 1;
	if ( setsockopt( tcps, SOL_SOCKET, SO_KEEPALIVE, (char *) &i,
	    sizeof(i) ) == -1 ) {
119
		int err = errno;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
120
		Debug( LDAP_DEBUG_ANY, "setsockopt(keepalive) failed errno %d (%s)",
121
		    err, err > -1 && err < sys_nerr ? sys_errlist[err] :
Kurt Zeilenga's avatar
Kurt Zeilenga committed
122
123
124
125
		    "unknown", 0 );
	}
#endif

126
127
128
129
130
131
132
133
134
135
136
#ifdef TCP_NODELAY
	i = 1;
	if ( setsockopt( tcps, IPPROTO_TCP, TCP_NODELAY, (char *) &i,
	    sizeof(i) ) == -1 ) {
		int err = errno;
		Debug( LDAP_DEBUG_ANY, "setsockopt(TCP_NODELAY) failed errno %d (%s)",
		    err, err > -1 && err < sys_nerr ? sys_errlist[err] :
		    "unknown", 0 );
	}
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
137
138
139
	(void) memset( (void *) &addr, '\0', sizeof(addr) );
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
140
	addr.sin_port = htons( (int)port );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
141
	if ( bind( tcps, (struct sockaddr *) &addr, sizeof(addr) ) == -1 ) {
142
		int err = errno;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
143
		Debug( LDAP_DEBUG_ANY, "bind() failed errno %d (%s)\n",
144
		    err, err > -1 && err < sys_nerr ? sys_errlist[err] :
Kurt Zeilenga's avatar
Kurt Zeilenga committed
145
146
147
148
149
		    "unknown", 0 );
		exit( 1 );
	}

	if ( listen( tcps, 5 ) == -1 ) {
150
		int err = errno;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
151
		Debug( LDAP_DEBUG_ANY, "listen() failed errno %d (%s)",
152
		    err, err > -1 && err < sys_nerr ? sys_errlist[err] :
Kurt Zeilenga's avatar
Kurt Zeilenga committed
153
154
155
156
157
		    "unknown", 0 );
		exit( 1 );
	}

	Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
158

159
160
	if (( slapd_pid_file != NULL ) &&
			(( fp = fopen( slapd_pid_file, "w" )) != NULL )) {
161
		fprintf( fp, "%d\n", (int) getpid() );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
162
163
		fclose( fp );
	}
164
165
166

	if (( slapd_args_file != NULL ) &&
			(( fp = fopen( slapd_args_file, "w" )) != NULL )) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		for ( i = 0; i < g_argc; i++ ) {
			fprintf( fp, "%s ", g_argv[i] );
		}
		fprintf( fp, "\n" );
		fclose( fp );
	}

	while ( !slapd_shutdown ) {
		struct sockaddr_in	from;
		struct hostent		*hp;
		struct timeval		zero;
		struct timeval		*tvp;
		int			len, pid;

181
182
183
		char	*client_name;
		char	*client_addr;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
184
185
186
187
		FD_ZERO( &writefds );
		FD_ZERO( &readfds );
		FD_SET( tcps, &readfds );

188
189
190
		zero.tv_sec = 0;
		zero.tv_usec = 0;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
191
		ldap_pvt_thread_mutex_lock( &active_threads_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
192
193
194
		Debug( LDAP_DEBUG_CONNS,
		    "listening for connections on %d, activity on:",
		    tcps, 0, 0 );
195

Kurt Zeilenga's avatar
Kurt Zeilenga committed
196
		ldap_pvt_thread_mutex_lock( &new_conn_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
197
198
199
200
201
202
203
204
205
206
207
208
		for ( i = 0; i < dtblsize; i++ ) {
			if ( c[i].c_sb.sb_sd != -1 ) {
				FD_SET( c[i].c_sb.sb_sd, &readfds );

				if ( c[i].c_writewaiter ) {
					FD_SET( c[i].c_sb.sb_sd, &writefds );
				}
				Debug( LDAP_DEBUG_CONNS, " %dr%s", i,
				    c[i].c_writewaiter ? "w" : "", 0 );
			}
		}
		Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
209
		ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
210
211
212

		Debug( LDAP_DEBUG_CONNS, "before select active_threads %d\n",
		    active_threads, 0, 0 );
213
#if defined( HAVE_YIELDING_SELECT ) || defined( NO_THREADS )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
214
215
216
217
		tvp = NULL;
#else
		tvp = active_threads ? &zero : NULL;
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
218
		ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
219

220
		switch ( i = select( dtblsize, &readfds, &writefds, 0, tvp ) ) {
221
222
		case -1:	{ /* failure - try again */
			int err = errno;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
223
224
			Debug( LDAP_DEBUG_CONNS,
			    "select failed errno %d (%s)\n",
225
226
227
			    err, err > -1 && err < sys_nerr ?
			    sys_errlist[err] : "unknown", 0 );
			} continue;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
228
229
230
231

		case 0:		/* timeout - let threads run */
			Debug( LDAP_DEBUG_CONNS, "select timeout - yielding\n",
			    0, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
232
			ldap_pvt_thread_yield();
Kurt Zeilenga's avatar
Kurt Zeilenga committed
233
234
235
			continue;

		default:	/* something happened - deal with it */
236
			Debug( LDAP_DEBUG_CONNS, "select activity on %d descriptors\n", i, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
237
238
			;	/* FALL */
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
239
		ldap_pvt_thread_mutex_lock( &currenttime_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
240
		time( &currenttime );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
241
		ldap_pvt_thread_mutex_unlock( &currenttime_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
242
243

		/* new connection */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
244
		ldap_pvt_thread_mutex_lock( &new_conn_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
245
246
247
		if ( FD_ISSET( tcps, &readfds ) ) {
			len = sizeof(from);
			if ( (ns = accept( tcps, (struct sockaddr *) &from,
248
249
250
			    &len )) == -1 )
			{
				int err = errno;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
251
				Debug( LDAP_DEBUG_ANY,
252
253
254
				    "accept() failed errno %d (%s)", err,
				    err > -1 && err < sys_nerr ?
				    sys_errlist[err] : "unknown", 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
255
				ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
256
257
258
259
				continue;
			}
			if ( ioctl( ns, FIONBIO, (caddr_t) &on ) == -1 ) {
				Debug( LDAP_DEBUG_ANY,
260
				    "FIONBIO ioctl on %d failed\n", ns, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
261
			}
262

Kurt Zeilenga's avatar
Kurt Zeilenga committed
263
264
265
266
			Debug( LDAP_DEBUG_CONNS, "new connection on %d\n", ns,
			    0, 0 );

			len = sizeof(from);
267

Kurt Zeilenga's avatar
Kurt Zeilenga committed
268
269
			if ( getpeername( ns, (struct sockaddr *) &from, &len )
			    == 0 ) {
270
271
272
				char *s;
				client_addr = inet_ntoa( from.sin_addr );

273
#ifdef SLAPD_RLOOKUPS
Kurt Zeilenga's avatar
Kurt Zeilenga committed
274
				hp = gethostbyaddr( (char *)
275
276
				    &(from.sin_addr),
				    sizeof(from.sin_addr), AF_INET );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
277

278
279
				if(hp) {
					client_name = hp->h_name;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
280

281
282
					/* normalize the domain */
					for ( s = client_name; *s; s++ ) {
283
						*s = TOLOWER( (unsigned char) *s );
284
285
286
287
					}

				} else {
					client_name = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
288
				}
289
290
291
292
#else
				client_name = NULL;
#endif

Kurt Zeilenga's avatar
Kurt Zeilenga committed
293
			} else {
294
295
296
297
298
				client_name = NULL;;
				client_addr = NULL;
			}

#ifdef HAVE_TCPD
299
300
301
			if(!hosts_ctl("slapd",
				client_name != NULL ? client_name : STRING_UNKNOWN,
				client_addr != NULL ? client_addr : STRING_UNKNOWN,
302
303
304
				STRING_UNKNOWN))
			{
				/* DENY ACCESS */
305
306
307
				Statslog( LDAP_DEBUG_ANY,
			   	 "fd=%d connection from %s (%s) denied.\n",
			   	 	ns,
308
309
						client_name == NULL ? "unknown" : client_name,
						client_addr == NULL ? "unknown" : client_addr,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
310
			   	  0, 0 );
311
312

				close(ns);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
313
				ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
314
315
316
317
				continue;
			}
#endif /* HAVE_TCPD */

318
			c[ns].c_sb.sb_sd = ns;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
319
			ldap_pvt_thread_mutex_lock( &ops_mutex );
320
			c[ns].c_connid = num_conns++;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
321
			ldap_pvt_thread_mutex_unlock( &ops_mutex );
322

323
324
325
326
327
328
329
330
331
332
			Statslog( LDAP_DEBUG_STATS,
			    "conn=%d fd=%d connection from %s (%s) accepted.\n",
			    	c[ns].c_connid, ns,
					client_name == NULL ? "unknown" : client_name,
					client_addr == NULL ? "unknown" : client_addr,
			     0 );

			if ( c[ns].c_addr != NULL ) {
				free( c[ns].c_addr );
			}
333
334
335

			c[ns].c_addr = ch_strdup( client_addr == NULL
				? "" : client_addr );
336
337
338

			if ( c[ns].c_domain != NULL ) {
				free( c[ns].c_domain );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
339
			}
340

341
			c[ns].c_domain = ch_strdup( client_name == NULL
342
343
				? "" : client_name );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
344
			ldap_pvt_thread_mutex_lock( &c[ns].c_dnmutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
345
346
347
348
			if ( c[ns].c_dn != NULL ) {
				free( c[ns].c_dn );
				c[ns].c_dn = NULL;
			}
349
350
351
352
			if ( c[ns].c_cdn != NULL ) {
				free( c[ns].c_cdn );
				c[ns].c_cdn = NULL;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
353
			ldap_pvt_thread_mutex_unlock( &c[ns].c_dnmutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
354
355
356
357
			c[ns].c_starttime = currenttime;
			c[ns].c_opsinitiated = 0;
			c[ns].c_opscompleted = 0;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
358
		ldap_pvt_thread_mutex_unlock( &new_conn_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

		Debug( LDAP_DEBUG_CONNS, "activity on:", 0, 0, 0 );
		for ( i = 0; i < dtblsize; i++ ) {
			int	r, w;

			r = FD_ISSET( i, &readfds );
			w = FD_ISSET( i, &writefds );
			if ( i != tcps && (r || w) ) {
				Debug( LDAP_DEBUG_CONNS, " %d%s%s", i,
				    r ? "r" : "", w ? "w" : "" );
			}
		}
		Debug( LDAP_DEBUG_CONNS, "\n", 0, 0, 0 );

		for ( i = 0; i < dtblsize; i++ ) {
			if ( i == tcps || (! FD_ISSET( i, &readfds ) &&
			    ! FD_ISSET( i, &writefds )) ) {
				continue;
			}

			if ( FD_ISSET( i, &writefds ) ) {
				Debug( LDAP_DEBUG_CONNS,
				    "signaling write waiter on %d\n", i, 0, 0 );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
383
				ldap_pvt_thread_mutex_lock( &active_threads_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
384
				active_threads++;
385
386
				c[i].c_writewaiter = 0;
				ldap_pvt_thread_cond_signal( &c[i].c_wcv );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
387
				ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
388
389
390
391
392
393
394
395
396
397
			}

			if ( FD_ISSET( i, &readfds ) ) {
				Debug( LDAP_DEBUG_CONNS,
				    "read activity on %d\n", i, 0, 0 );

				connection_activity( &c[i] );
			}
		}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
398
		ldap_pvt_thread_yield();
Kurt Zeilenga's avatar
Kurt Zeilenga committed
399
400
401
	}

	close( tcps );
402

Kurt Zeilenga's avatar
Kurt Zeilenga committed
403
	ldap_pvt_thread_mutex_lock( &active_threads_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
404
405
406
407
	Debug( LDAP_DEBUG_ANY,
	    "slapd shutting down - waiting for %d threads to terminate\n",
	    active_threads, 0, 0 );
	while ( active_threads > 0 ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
408
		ldap_pvt_thread_cond_wait(&active_threads_cond, &active_threads_mutex);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
409
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
410
	ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
411
412
413
414
415
416
417

	/* let backends do whatever cleanup they need to do */
	Debug( LDAP_DEBUG_TRACE,
	    "slapd shutting down - waiting for backends to close down\n", 0, 0,
	    0 );
	be_close();
	Debug( LDAP_DEBUG_ANY, "slapd stopping\n", 0, 0, 0 );
418

419
	return NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
420
421
}

422
423
void
slap_set_shutdown( int sig )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
424
425
{
	slapd_shutdown = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
426
	ldap_pvt_thread_kill( listener_tid, LDAP_SIGUSR1 );
427
428
429

	/* reinstall self */
	(void) SIGNAL( sig, slap_set_shutdown );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
430
431
}

432
433
void
slap_do_nothing( int sig )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
434
{
435
436
	/* reinstall self */
	(void) SIGNAL( sig, slap_do_nothing );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
437
}