daemon.c 95 KB
Newer Older
1
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
2
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
4
 * Copyright 1998-2020 The OpenLDAP Foundation.
5
 * Portions Copyright 2007 by Howard Chu, Symas Corporation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of Michigan at Ann Arbor. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
26
 */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
27
28
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
29
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
30
31
32
33
34
35
36
37

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

38
#include "slap.h"
Howard Chu's avatar
Howard Chu committed
39
#include "ldap_pvt_thread.h"
40
#include "lutil.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
41

42
43
#include "ldap_rq.h"

Howard Chu's avatar
Howard Chu committed
44
45
46
47
#ifdef HAVE_POLL
#include <poll.h>
#endif

48
#ifdef HAVE_KQUEUE
49
50
51
52
# include <sys/types.h>
# include <sys/event.h>
# include <sys/time.h>
#elif defined(HAVE_SYS_EPOLL_H) && defined(HAVE_EPOLL)
Kurt Zeilenga's avatar
cleanup    
Kurt Zeilenga committed
53
# include <sys/epoll.h>
54
55
56
57
58
#elif defined(SLAP_X_DEVPOLL) && defined(HAVE_SYS_DEVPOLL_H) && defined(HAVE_DEVPOLL)
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <sys/devpoll.h>
59
#endif /* ! kqueue && ! epoll && ! /dev/poll */
Howard Chu's avatar
Howard Chu committed
60

Kurt Zeilenga's avatar
Kurt Zeilenga committed
61
#ifdef HAVE_TCPD
62
63
int allow_severity = LOG_INFO;
int deny_severity = LOG_NOTICE;
64
#endif /* TCP Wrappers */
65

Kurt Zeilenga's avatar
Kurt Zeilenga committed
66
#ifdef LDAP_PF_LOCAL
Kurt Zeilenga's avatar
cleanup    
Kurt Zeilenga committed
67
# include <sys/stat.h>
68
/* this should go in <ldap.h> as soon as it is accepted */
Kurt Zeilenga's avatar
cleanup    
Kurt Zeilenga committed
69
# define LDAPI_MOD_URLEXT		"x-mod"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
70
#endif /* LDAP_PF_LOCAL */
71

72
#ifdef LDAP_PF_INET6
73
int slap_inet4or6 = AF_UNSPEC;
74
#else /* ! INETv6 */
75
int slap_inet4or6 = AF_INET;
76
#endif /* ! INETv6 */
77

78
/* globals */
79
80
81
time_t starttime;
ber_socket_t dtblsize;
slap_ssf_t local_ssf = LDAP_PVT_SASL_LOCAL_SSF;
82
struct runqueue_s slapd_rq;
83

84
85
86
int slapd_daemon_threads = 1;
int slapd_daemon_mask;

87
88
89
90
91
#ifdef LDAP_TCP_BUFFER
int slapd_tcp_rmem;
int slapd_tcp_wmem;
#endif /* LDAP_TCP_BUFFER */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
92
Listener **slap_listeners = NULL;
93
static volatile sig_atomic_t listening = 1; /* 0 when slap_listeners closed */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
94

95
#ifndef SLAPD_LISTEN_BACKLOG
96
#define SLAPD_LISTEN_BACKLOG 2048
97
#endif /* ! SLAPD_LISTEN_BACKLOG */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
98

99
100
#define	DAEMON_ID(fd)	(fd & slapd_daemon_mask)

101
102
103
typedef ber_socket_t sdpair[2];

static sdpair *wake_sds;
104
static ldap_pvt_thread_mutex_t emfile_mutex;
105
static int emfile;
106

107
static volatile int waking;
108
#define WAKE_LISTENER(l,w)	do { \
Howard Chu's avatar
Howard Chu committed
109
	if (w) { \
Howard Chu's avatar
Howard Chu committed
110
		(void)!tcp_write( SLAP_FD2SOCK(wake_sds[l][1]), "0", 1 ); \
Howard Chu's avatar
Howard Chu committed
111
	} \
112
} while (0)
113

Kurt Zeilenga's avatar
cleanup    
Kurt Zeilenga committed
114
115
volatile sig_atomic_t slapd_shutdown = 0;
volatile sig_atomic_t slapd_gentle_shutdown = 0;
116
117
volatile sig_atomic_t slapd_abrupt_shutdown = 0;

118
119
120
121
122
123
124
125
126
#ifdef HAVE_WINSOCK
ldap_pvt_thread_mutex_t slapd_ws_mutex;
SOCKET *slapd_ws_sockets;
#define	SD_READ 1
#define	SD_WRITE	2
#define	SD_ACTIVE	4
#define	SD_LISTENER	8
#endif

127
#ifdef HAVE_TCPD
128
static ldap_pvt_thread_mutex_t	sd_tcpd_mutex;
129
130
#endif /* TCP Wrappers */

131
132
133
typedef struct slap_daemon_st {
	ldap_pvt_thread_mutex_t	sd_mutex;

134
135
	ber_socket_t		sd_nactives;
	int			sd_nwriters;
136
	int			sd_nfds;
137
	ldap_pvt_thread_t	sd_tid;
138

139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#if defined(HAVE_KQUEUE)
	uint8_t*        sd_fdmodes; /* indexed by fd */
	Listener**      sd_l;       /* indexed by fd */
	/* Double buffer the kqueue changes to avoid holding the sd_mutex \
	 * during a kevent() call. \
	 */
	struct kq_change {
	    struct kevent*  sd_changes;
	    int             sd_nchanges;
	    int             sd_maxchanges;
	}               sd_kqc[2];
	int             sd_changeidx; /* index to current change buffer */
	int             sd_kq;
#elif defined(HAVE_EPOLL)

154
155
156
	struct epoll_event	*sd_epolls;
	int			*sd_index;
	int			sd_epfd;
157
158
159
160
161
162
#elif defined(SLAP_X_DEVPOLL) && defined(HAVE_DEVPOLL)
	/* eXperimental */
	struct pollfd		*sd_pollfd;
	int			*sd_index;
	Listener		**sd_l;
	int			sd_dpfd;
163
#else /* ! kqueue && ! epoll && ! /dev/poll */
164
165
166
167
#ifdef HAVE_WINSOCK
	char	*sd_flags;
	char	*sd_rflags;
#else /* ! HAVE_WINSOCK */
168
169
170
	fd_set			sd_actives;
	fd_set			sd_readers;
	fd_set			sd_writers;
171
#endif /* ! HAVE_WINSOCK */
172
#endif /* ! kqueue && ! epoll && ! /dev/poll */
173
174
} slap_daemon_st;

175
static slap_daemon_st *slap_daemon;
176

177
178
179
180
181
182
183
/*
 * NOTE: naming convention for macros:
 *
 * - SLAP_SOCK_* and SLAP_EVENT_* for public interface that deals
 *   with file descriptors and events respectively
 *
 * - SLAP_<type>_* for private interface; type by now is one of
184
 *   EPOLL, DEVPOLL, SELECT, KQUEUE
185
186
187
 *
 * private interface should not be used in the code.
 */
188
#ifdef HAVE_KQUEUE
189
190
# define SLAP_EVENT_FNAME		    "kqueue"
# define SLAP_EVENTS_ARE_INDEXED	0
191
# define SLAP_EVENT_MAX(t)             (2 * dtblsize)  /* each fd can have a read & a write event */
192
193
194
195

# define SLAP_EVENT_DECL \
     static struct kevent* events = NULL

196
# define SLAP_EVENT_INIT(t) do {\
197
    if (!events) { \
198
        events = ch_malloc(sizeof(*events) * SLAP_EVENT_MAX(t)); \
199
200
201
    } \
} while (0)

202
# define SLAP_SOCK_INIT(t) do { \
203
204
    int kq_i; \
    size_t kq_nbytes; \
Ondřej Kuzník's avatar
Ondřej Kuzník committed
205
    Debug(LDAP_DEBUG_ANY, "daemon: SLAP_SOCK_INIT: dtblsize=%d\n", dtblsize); \
206
207
    slap_daemon[t].sd_nfds       = 0; \
    slap_daemon[t].sd_changeidx  = 0; \
208
    for (kq_i = 0;  kq_i < 2;  kq_i++) { \
209
        struct kq_change* kqc = &slap_daemon[t].sd_kqc[kq_i]; \
210
211
212
213
214
        kqc->sd_nchanges   = 0; \
        kqc->sd_maxchanges = 256; /* will grow as needed */ \
        kq_nbytes = sizeof(*kqc->sd_changes) * kqc->sd_maxchanges; \
        kqc->sd_changes = ch_calloc(1, kq_nbytes); \
    } \
215
216
217
218
219
    kq_nbytes = sizeof(*slap_daemon[t].sd_fdmodes) * dtblsize; \
    slap_daemon[t].sd_fdmodes = ch_calloc(1, kq_nbytes); \
    kq_nbytes = sizeof(*slap_daemon[t].sd_l) * dtblsize; \
    slap_daemon[t].sd_l = ch_calloc(1, kq_nbytes); \
    slap_daemon[t].sd_kq = kqueue(); \
220
221
} while (0)

222
223
224
225
226
227
228
229
/* a kqueue fd obtained before a fork can't be used in child process.
 * close it and reacquire it.
 */
# define SLAP_SOCK_INIT2() do { \
	close(slap_daemon[0].sd_kq); \
	slap_daemon[0].sd_kq = kqueue(); \
} while (0)

230
# define SLAP_SOCK_DESTROY(t) do { \
231
	int kq_i; \
232
233
234
    if (slap_daemon[t].sd_kq > 0) { \
        close(slap_daemon[t].sd_kq); \
        slap_daemon[t].sd_kq = -1; \
235
236
    } \
    for (kq_i = 0;  kq_i < 2;  kq_i++) { \
237
238
239
        if (slap_daemon[t].sd_kqc[kq_i].sd_changes != NULL) { \
            ch_free(slap_daemon[t].sd_kqc[kq_i].sd_changes); \
            slap_daemon[t].sd_kqc[kq_i].sd_changes = NULL; \
240
        } \
241
242
        slap_daemon[t].sd_kqc[kq_i].sd_nchanges = 0; \
        slap_daemon[t].sd_kqc[kq_i].sd_maxchanges = 0; \
243
    } \
244
245
246
    if (slap_daemon[t].sd_l != NULL) { \
        ch_free(slap_daemon[t].sd_l); \
        slap_daemon[t].sd_l = NULL; \
247
    } \
248
249
250
    if (slap_daemon[t].sd_fdmodes != NULL) { \
        ch_free(slap_daemon[t].sd_fdmodes); \
        slap_daemon[t].sd_fdmodes = NULL; \
251
    } \
252
    slap_daemon[t].sd_nfds = 0; \
253
254
255
256
257
258
} while (0)

# define SLAP_KQUEUE_SOCK_ACTIVE        0x01
# define SLAP_KQUEUE_SOCK_READ_ENABLED  0x02
# define SLAP_KQUEUE_SOCK_WRITE_ENABLED 0x04

259
260
261
262
# define SLAP_SOCK_IS_ACTIVE(t,s)  (slap_daemon[t].sd_fdmodes[(s)] != 0)
# define SLAP_SOCK_NOT_ACTIVE(t,s) (slap_daemon[t].sd_fdmodes[(s)] == 0)
# define SLAP_SOCK_IS_READ(t,s)    (slap_daemon[t].sd_fdmodes[(s)] & SLAP_KQUEUE_SOCK_READ_ENABLED)
# define SLAP_SOCK_IS_WRITE(t,s)   (slap_daemon[t].sd_fdmodes[(s)] & SLAP_KQUEUE_SOCK_WRITE_ENABLED)
263
264
265
266
267
268
269

/*
 * SLAP_SOCK_SET_* & SLAP_SOCK_CLR_* get called a _lot_.  Since kevent()
 * processes changes before it looks for events, batch up the changes which
 * will get submitted the next time kevent() is called for events.
 */

270
# define SLAP_KQUEUE_CHANGE(t, s, filter, flag) do { \
271
272
273
274
    /* If maxchanges is reached, have to realloc to make room for more. \
     * Ideally we'd call kevent(), but the daemon thread could be sitting \
     * in kevent() waiting for events. \
     */ \
275
    struct kq_change* kqc = &slap_daemon[t].sd_kqc[slap_daemon[t].sd_changeidx]; \
276
277
278
279
280
    if (kqc->sd_nchanges == kqc->sd_maxchanges) { \
        /* Don't want to do this very often.  Double the size. */ \
        size_t kq_nbytes; \
        Debug(LDAP_DEBUG_CONNS, \
              "daemon: SLAP_KQUEUE_CHANGE: increasing slap_daemon.sd_kqc[%d].maxchanges from %d to %d\n", \
281
              slap_daemon[t].sd_changeidx, kqc->sd_maxchanges, 2*kqc->sd_maxchanges); \
282
283
284
285
286
        kqc->sd_maxchanges += kqc->sd_maxchanges; \
        kq_nbytes = sizeof(*kqc->sd_changes) * kqc->sd_maxchanges; \
        kqc->sd_changes = ch_realloc(kqc->sd_changes, kq_nbytes); \
    } \
    EV_SET(&kqc->sd_changes[kqc->sd_nchanges++], \
287
           (s), (filter), (flag), 0, 0, slap_daemon[t].sd_l[(s)]); \
288
289
} while (0)

290
291
292
293
# define SLAP_KQUEUE_SOCK_SET(t, s, filter, mode) do { \
    if ((slap_daemon[t].sd_fdmodes[(s)] & (mode)) != (mode)) { \
        slap_daemon[t].sd_fdmodes[(s)] |= (mode); \
        SLAP_KQUEUE_CHANGE(t, (s), (filter), EV_ENABLE); \
294
295
296
    } \
} while (0)

297
298
299
300
# define SLAP_KQUEUE_SOCK_CLR(t, s, filter, mode) do { \
    if (slap_daemon[t].sd_fdmodes[(s)] & (mode)) { \
        slap_daemon[t].sd_fdmodes[(s)] &= ~(mode); \
        SLAP_KQUEUE_CHANGE(t, (s), (filter), EV_DISABLE); \
301
302
303
    } \
} while (0)

304
305
306
307
# define SLAP_SOCK_SET_READ(t, s)  SLAP_KQUEUE_SOCK_SET(t, (s), EVFILT_READ,  SLAP_KQUEUE_SOCK_READ_ENABLED)
# define SLAP_SOCK_SET_WRITE(t, s) SLAP_KQUEUE_SOCK_SET(t, (s), EVFILT_WRITE, SLAP_KQUEUE_SOCK_WRITE_ENABLED)
# define SLAP_SOCK_CLR_READ(t, s)  SLAP_KQUEUE_SOCK_CLR(t, (s), EVFILT_READ,  SLAP_KQUEUE_SOCK_READ_ENABLED)
# define SLAP_SOCK_CLR_WRITE(t, s) SLAP_KQUEUE_SOCK_CLR(t, (s), EVFILT_WRITE, SLAP_KQUEUE_SOCK_WRITE_ENABLED)
308
309
310
311
312

/* kqueue doesn't need to do anything to clear the event. */
# define SLAP_EVENT_CLR_READ(i)     do {} while (0)
# define SLAP_EVENT_CLR_WRITE(i)    do {} while (0)

313
# define SLAP_SOCK_ADD(t, s, l) do { \
314
    assert( s < dtblsize ); \
315
316
317
318
319
    slap_daemon[t].sd_l[(s)] = (l); \
    slap_daemon[t].sd_fdmodes[(s)] = SLAP_KQUEUE_SOCK_ACTIVE | SLAP_KQUEUE_SOCK_READ_ENABLED; \
    ++slap_daemon[t].sd_nfds; \
    SLAP_KQUEUE_CHANGE(t, (s), EVFILT_READ, EV_ADD); \
    SLAP_KQUEUE_CHANGE(t, (s), EVFILT_WRITE, EV_ADD | EV_DISABLE); \
320
321
} while (0)

322
323
324
325
326
327
# define SLAP_SOCK_DEL(t, s) do { \
    SLAP_KQUEUE_CHANGE(t, (s), EVFILT_READ, EV_DELETE); \
    SLAP_KQUEUE_CHANGE(t, (s), EVFILT_WRITE, EV_DELETE); \
    slap_daemon[t].sd_l[(s)] = NULL; \
    slap_daemon[t].sd_fdmodes[(s)] = 0; \
    --slap_daemon[t].sd_nfds; \
328
329
} while (0)

330
# define SLAP_EVENT_FD(t, i)          (events[(i)].ident)
331

332
333
# define SLAP_EVENT_IS_READ(t, i) \
    (events[(i)].filter == EVFILT_READ && SLAP_SOCK_IS_READ(t, SLAP_EVENT_FD(0, i)))
334

335
336
# define SLAP_EVENT_IS_WRITE(t, i) \
    (events[(i)].filter == EVFILT_WRITE && SLAP_SOCK_IS_WRITE(t, SLAP_EVENT_FD(0, i)))
337

338
339
# define SLAP_EVENT_IS_LISTENER(t, i) \
    (events[(i)].udata && SLAP_SOCK_IS_READ(t, SLAP_EVENT_FD(t, i)))
340

341
342
343
# define SLAP_EVENT_LISTENER(t, i)    ((Listener*)(events[(i)].udata))

# define SLAP_EVENT_WAIT(t, tvp, nsp) do { \
344
345
346
347
348
349
350
351
352
353
354
355
    struct timespec  kq_ts; \
    struct timespec* kq_tsp; \
    int kq_idx; \
    if (tvp) { \
        TIMEVAL_TO_TIMESPEC((tvp), &kq_ts); \
        kq_tsp = &kq_ts; \
    } else { \
        kq_tsp = NULL; \
    } \
    /* Save the change buffer index for use when the mutex is unlocked, \
     * then switch the index so new changes go to the other buffer. \
     */ \
356
357
358
359
360
361
362
363
364
365
    ldap_pvt_thread_mutex_lock( &slap_daemon[t].sd_mutex ); \
    kq_idx = slap_daemon[t].sd_changeidx; \
    slap_daemon[t].sd_changeidx ^= 1; \
    ldap_pvt_thread_mutex_unlock( &slap_daemon[t].sd_mutex ); \
    *(nsp) = kevent(slap_daemon[t].sd_kq, \
                    slap_daemon[t].sd_kqc[kq_idx].sd_nchanges \
                        ? slap_daemon[t].sd_kqc[kq_idx].sd_changes : NULL, \
                    slap_daemon[t].sd_kqc[kq_idx].sd_nchanges, \
                    events, SLAP_EVENT_MAX(t), kq_tsp); \
    slap_daemon[t].sd_kqc[kq_idx].sd_nchanges = 0; \
366
367
368
369
370
} while(0)

/*-------------------------------------------------------------------------------*/

#elif defined(HAVE_EPOLL)
371
372
373
374
/***************************************
 * Use epoll infrastructure - epoll(4) *
 ***************************************/
# define SLAP_EVENT_FNAME		"epoll"
375
# define SLAP_EVENTS_ARE_INDEXED	0
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# define SLAP_EPOLL_SOCK_IX(t,s)		(slap_daemon[t].sd_index[(s)])
# define SLAP_EPOLL_SOCK_EP(t,s)		(slap_daemon[t].sd_epolls[SLAP_EPOLL_SOCK_IX(t,s)])
# define SLAP_EPOLL_SOCK_EV(t,s)		(SLAP_EPOLL_SOCK_EP(t,s).events)
# define SLAP_SOCK_IS_ACTIVE(t,s)		(SLAP_EPOLL_SOCK_IX(t,s) != -1)
# define SLAP_SOCK_NOT_ACTIVE(t,s)	(SLAP_EPOLL_SOCK_IX(t,s) == -1)
# define SLAP_EPOLL_SOCK_IS_SET(t,s, mode)	(SLAP_EPOLL_SOCK_EV(t,s) & (mode))

# define SLAP_SOCK_IS_READ(t,s)		SLAP_EPOLL_SOCK_IS_SET(t,(s), EPOLLIN)
# define SLAP_SOCK_IS_WRITE(t,s)		SLAP_EPOLL_SOCK_IS_SET(t,(s), EPOLLOUT)

# define SLAP_EPOLL_SOCK_SET(t,s, mode)	do { \
	if ( (SLAP_EPOLL_SOCK_EV(t,s) & (mode)) != (mode) ) {	\
		SLAP_EPOLL_SOCK_EV(t,s) |= (mode); \
		epoll_ctl( slap_daemon[t].sd_epfd, EPOLL_CTL_MOD, (s), \
			&SLAP_EPOLL_SOCK_EP(t,s) ); \
391
	} \
392
} while (0)
393

394
395
396
397
398
# define SLAP_EPOLL_SOCK_CLR(t,s, mode)	do { \
	if ( (SLAP_EPOLL_SOCK_EV(t,s) & (mode)) ) { \
		SLAP_EPOLL_SOCK_EV(t,s) &= ~(mode);	\
		epoll_ctl( slap_daemon[t].sd_epfd, EPOLL_CTL_MOD, s, \
			&SLAP_EPOLL_SOCK_EP(t,s) ); \
399
	} \
400
401
} while (0)

402
403
# define SLAP_SOCK_SET_READ(t,s)		SLAP_EPOLL_SOCK_SET(t,s, EPOLLIN)
# define SLAP_SOCK_SET_WRITE(t,s)		SLAP_EPOLL_SOCK_SET(t,s, EPOLLOUT)
404

405
406
# define SLAP_SOCK_CLR_READ(t,s)		SLAP_EPOLL_SOCK_CLR(t,(s), EPOLLIN)
# define SLAP_SOCK_CLR_WRITE(t,s)		SLAP_EPOLL_SOCK_CLR(t,(s), EPOLLOUT)
407

408
409
410
411
412
413
#  define SLAP_SOCK_SET_SUSPEND(t,s) \
	( slap_daemon[t].sd_suspend[SLAP_EPOLL_SOCK_IX(t,s)] = 1 )
#  define SLAP_SOCK_CLR_SUSPEND(t,s) \
	( slap_daemon[t].sd_suspend[SLAP_EPOLL_SOCK_IX(t,s)] = 0 )
#  define SLAP_SOCK_IS_SUSPEND(t,s) \
	( slap_daemon[t].sd_suspend[SLAP_EPOLL_SOCK_IX(t,s)] == 1 )
414

415
# define SLAP_EPOLL_EVENT_CLR(i, mode)	(revents[(i)].events &= ~(mode))
416

417
# define SLAP_EVENT_MAX(t)			slap_daemon[t].sd_nfds
Howard Chu's avatar
Howard Chu committed
418

Howard Chu's avatar
Howard Chu committed
419
420
/* If a Listener address is provided, store that as the epoll data.
 * Otherwise, store the address of this socket's slot in the
421
422
 * index array. If we can't do this add, the system is out of
 * resources and we need to shutdown.
Howard Chu's avatar
Howard Chu committed
423
 */
424
# define SLAP_SOCK_ADD(t, s, l)		do { \
425
	int rc; \
426
427
428
429
430
	SLAP_EPOLL_SOCK_IX(t,(s)) = slap_daemon[t].sd_nfds; \
	SLAP_EPOLL_SOCK_EP(t,(s)).data.ptr = (l) ? (l) : (void *)(&SLAP_EPOLL_SOCK_IX(t,s)); \
	SLAP_EPOLL_SOCK_EV(t,(s)) = EPOLLIN; \
	rc = epoll_ctl(slap_daemon[t].sd_epfd, EPOLL_CTL_ADD, \
		(s), &SLAP_EPOLL_SOCK_EP(t,(s))); \
431
	if ( rc == 0 ) { \
432
		slap_daemon[t].sd_nfds++; \
433
	} else { \
434
		int saved_errno = errno; \
435
		Debug( LDAP_DEBUG_ANY, \
436
			"daemon: epoll_ctl(ADD,fd=%d) failed, errno=%d, shutting down\n", \
437
			s, saved_errno ); \
438
439
440
441
		slapd_shutdown = 2; \
	} \
} while (0)

442
443
444
# define SLAP_EPOLL_EV_LISTENER(t,ptr) \
	(((int *)(ptr) >= slap_daemon[t].sd_index && \
	(int *)(ptr) <= &slap_daemon[t].sd_index[dtblsize]) ? 0 : 1 )
445

446
# define SLAP_EPOLL_EV_PTRFD(t,ptr)		(SLAP_EPOLL_EV_LISTENER(t,ptr) ? \
447
	((Listener *)ptr)->sl_sd : \
448
	(ber_socket_t) ((int *)(ptr) - slap_daemon[t].sd_index))
449

450
451
# define SLAP_SOCK_DEL(t,s)		do { \
	int fd, rc, index = SLAP_EPOLL_SOCK_IX(t,(s)); \
452
	if ( index < 0 ) break; \
453
454
455
456
457
458
459
460
	rc = epoll_ctl(slap_daemon[t].sd_epfd, EPOLL_CTL_DEL, \
		(s), &SLAP_EPOLL_SOCK_EP(t,(s))); \
	slap_daemon[t].sd_epolls[index] = \
		slap_daemon[t].sd_epolls[slap_daemon[t].sd_nfds-1]; \
	fd = SLAP_EPOLL_EV_PTRFD(t,slap_daemon[t].sd_epolls[index].data.ptr); \
	slap_daemon[t].sd_index[fd] = index; \
	slap_daemon[t].sd_index[(s)] = -1; \
	slap_daemon[t].sd_nfds--; \
461
462
} while (0)

463
464
# define SLAP_EVENT_CLR_READ(i)		SLAP_EPOLL_EVENT_CLR((i), EPOLLIN)
# define SLAP_EVENT_CLR_WRITE(i)	SLAP_EPOLL_EVENT_CLR((i), EPOLLOUT)
465

466
# define SLAP_EPOLL_EVENT_CHK(i, mode)	(revents[(i)].events & mode)
467

468
469
# define SLAP_EVENT_IS_READ(i)		SLAP_EPOLL_EVENT_CHK((i), EPOLLIN)
# define SLAP_EVENT_IS_WRITE(i)		SLAP_EPOLL_EVENT_CHK((i), EPOLLOUT)
470
471
# define SLAP_EVENT_IS_LISTENER(t,i)	SLAP_EPOLL_EV_LISTENER(t,revents[(i)].data.ptr)
# define SLAP_EVENT_LISTENER(t,i)		((Listener *)(revents[(i)].data.ptr))
472

473
# define SLAP_EVENT_FD(t,i)		SLAP_EPOLL_EV_PTRFD(t,revents[(i)].data.ptr)
474

475
476
477
# define SLAP_SOCK_INIT(t)		do { \
	int j; \
	slap_daemon[t].sd_epolls = ch_calloc(1, \
478
479
		( sizeof(struct epoll_event) * 2 \
			+ sizeof(int) ) * dtblsize * 2); \
480
481
482
	slap_daemon[t].sd_index = (int *)&slap_daemon[t].sd_epolls[ 2 * dtblsize ]; \
	slap_daemon[t].sd_epfd = epoll_create( dtblsize / slapd_daemon_threads ); \
	for ( j = 0; j < dtblsize; j++ ) slap_daemon[t].sd_index[j] = -1; \
483
484
} while (0)

485
486
# define SLAP_SOCK_INIT2()

487
488
489
490
491
492
# define SLAP_SOCK_DESTROY(t)		do { \
	if ( slap_daemon[t].sd_epolls != NULL ) { \
		ch_free( slap_daemon[t].sd_epolls ); \
		slap_daemon[t].sd_epolls = NULL; \
		slap_daemon[t].sd_index = NULL; \
		close( slap_daemon[t].sd_epfd ); \
493
494
495
	} \
} while ( 0 )

496
# define SLAP_EVENT_DECL		struct epoll_event *revents
497

498
499
# define SLAP_EVENT_INIT(t)		do { \
	revents = slap_daemon[t].sd_epolls + dtblsize; \
500
501
} while (0)

502
503
# define SLAP_EVENT_WAIT(t, tvp, nsp)	do { \
	*(nsp) = epoll_wait( slap_daemon[t].sd_epfd, revents, \
504
		dtblsize, (tvp) ? ((tvp)->tv_sec * 1000 + (tvp)->tv_usec / 1000) : -1 ); \
505
} while (0)
506

507
#elif defined(SLAP_X_DEVPOLL) && defined(HAVE_DEVPOLL)
Howard Chu's avatar
Howard Chu committed
508

509
510
511
512
513
514
515
516
517
518
519
520
/*************************************************************
 * Use Solaris' (>= 2.7) /dev/poll infrastructure - poll(7d) *
 *************************************************************/
# define SLAP_EVENT_FNAME		"/dev/poll"
# define SLAP_EVENTS_ARE_INDEXED	0
/*
 * - sd_index	is used much like with epoll()
 * - sd_l	is maintained as an array containing the address
 *		of the listener; the index is the fd itself
 * - sd_pollfd	is used to keep track of what data has been
 *		registered in /dev/poll
 */
521
522
523
524
525
526
527
528
529
530
531
# define SLAP_DEVPOLL_SOCK_IX(t,s)	(slap_daemon[t].sd_index[(s)])
# define SLAP_DEVPOLL_SOCK_LX(t,s)	(slap_daemon[t].sd_l[(s)])
# define SLAP_DEVPOLL_SOCK_EP(t,s)	(slap_daemon[t].sd_pollfd[SLAP_DEVPOLL_SOCK_IX(t,(s))])
# define SLAP_DEVPOLL_SOCK_FD(t,s)	(SLAP_DEVPOLL_SOCK_EP(t,(s)).fd)
# define SLAP_DEVPOLL_SOCK_EV(t,s)	(SLAP_DEVPOLL_SOCK_EP(t,(s)).events)
# define SLAP_SOCK_IS_ACTIVE(t,s)		(SLAP_DEVPOLL_SOCK_IX(t,(s)) != -1)
# define SLAP_SOCK_NOT_ACTIVE(t,s)	(SLAP_DEVPOLL_SOCK_IX(t,(s)) == -1)
# define SLAP_SOCK_IS_SET(t,s, mode)	(SLAP_DEVPOLL_SOCK_EV(t,(s)) & (mode))

# define SLAP_SOCK_IS_READ(t,s)		SLAP_SOCK_IS_SET(t,(s), POLLIN)
# define SLAP_SOCK_IS_WRITE(t,s)		SLAP_SOCK_IS_SET(t,(s), POLLOUT)
532
533
534
535

/* as far as I understand, any time we need to communicate with the kernel
 * about the number and/or properties of a file descriptor we need it to
 * wait for, we have to rewrite the whole set */
536
# define SLAP_DEVPOLL_WRITE_POLLFD(t,s, pfd, n, what, shdn)	do { \
537
538
539
	int rc; \
	size_t size = (n) * sizeof( struct pollfd ); \
	/* FIXME: use pwrite? */ \
540
	rc = write( slap_daemon[t].sd_dpfd, (pfd), size ); \
541
	if ( rc != size ) { \
542
		int saved_errno = errno; \
543
544
		Debug( LDAP_DEBUG_ANY, "daemon: " SLAP_EVENT_FNAME ": " \
			"%s fd=%d failed errno=%d\n", \
545
			(what), (s), saved_errno ); \
546
547
548
549
550
551
		if ( (shdn) ) { \
			slapd_shutdown = 2; \
		} \
	} \
} while (0)

552
# define SLAP_DEVPOLL_SOCK_SET(t,s, mode) 	do { \
553
	Debug( LDAP_DEBUG_CONNS, "SLAP_SOCK_SET_%s(%d)=%d\n", \
554
		(mode) == POLLIN ? "READ" : "WRITE", (s), \
555
556
		( (SLAP_DEVPOLL_SOCK_EV(t,(s)) & (mode)) != (mode) ) ); \
	if ( (SLAP_DEVPOLL_SOCK_EV(t,(s)) & (mode)) != (mode) ) { \
557
		struct pollfd pfd; \
558
559
560
561
		SLAP_DEVPOLL_SOCK_EV(t,(s)) |= (mode); \
		pfd.fd = SLAP_DEVPOLL_SOCK_FD(t,(s)); \
		pfd.events = /* (mode) */ SLAP_DEVPOLL_SOCK_EV(t,(s)); \
		SLAP_DEVPOLL_WRITE_POLLFD(t,(s), &pfd, 1, "SET", 0); \
562
563
564
	} \
} while (0)

565
# define SLAP_DEVPOLL_SOCK_CLR(t,s, mode)		do { \
566
	Debug( LDAP_DEBUG_CONNS, "SLAP_SOCK_CLR_%s(%d)=%d\n", \
567
		(mode) == POLLIN ? "READ" : "WRITE", (s), \
568
569
		( (SLAP_DEVPOLL_SOCK_EV(t,(s)) & (mode)) == (mode) ) ); \
	if ((SLAP_DEVPOLL_SOCK_EV(t,(s)) & (mode)) == (mode) ) { \
570
		struct pollfd pfd[2]; \
571
572
		SLAP_DEVPOLL_SOCK_EV(t,(s)) &= ~(mode); \
		pfd[0].fd = SLAP_DEVPOLL_SOCK_FD(t,(s)); \
573
		pfd[0].events = POLLREMOVE; \
574
575
		pfd[1] = SLAP_DEVPOLL_SOCK_EP(t,(s)); \
		SLAP_DEVPOLL_WRITE_POLLFD(t,(s), &pfd[0], 2, "CLR", 0); \
576
577
578
	} \
} while (0)

579
580
# define SLAP_SOCK_SET_READ(t,s)		SLAP_DEVPOLL_SOCK_SET(t,s, POLLIN)
# define SLAP_SOCK_SET_WRITE(t,s)		SLAP_DEVPOLL_SOCK_SET(t,s, POLLOUT)
581

582
583
# define SLAP_SOCK_CLR_READ(t,s)		SLAP_DEVPOLL_SOCK_CLR(t,(s), POLLIN)
# define SLAP_SOCK_CLR_WRITE(t,s)		SLAP_DEVPOLL_SOCK_CLR(t,(s), POLLOUT)
584

585
586
587
588
589
590
#  define SLAP_SOCK_SET_SUSPEND(t,s) \
	( slap_daemon[t].sd_suspend[SLAP_DEVPOLL_SOCK_IX(t,(s))] = 1 )
#  define SLAP_SOCK_CLR_SUSPEND(t,s) \
	( slap_daemon[t].sd_suspend[SLAP_DEVPOLL_SOCK_IX(t,(s))] = 0 )
#  define SLAP_SOCK_IS_SUSPEND(t,s) \
	( slap_daemon[t].sd_suspend[SLAP_DEVPOLL_SOCK_IX(t,(s))] == 1 )
591
592
593

# define SLAP_DEVPOLL_EVENT_CLR(i, mode)	(revents[(i)].events &= ~(mode))

594
# define SLAP_EVENT_MAX(t)			slap_daemon[t].sd_nfds
595
596
597
598
599

/* If a Listener address is provided, store that in the sd_l array.
 * If we can't do this add, the system is out of resources and we 
 * need to shutdown.
 */
600
# define SLAP_SOCK_ADD(t, s, l)		do { \
Ondřej Kuzník's avatar
Ondřej Kuzník committed
601
	Debug( LDAP_DEBUG_CONNS, "SLAP_SOCK_ADD(%d, %p)\n", (s), (l) ); \
602
603
604
605
	SLAP_DEVPOLL_SOCK_IX(t,(s)) = slap_daemon[t].sd_nfds; \
	SLAP_DEVPOLL_SOCK_LX(t,(s)) = (l); \
	SLAP_DEVPOLL_SOCK_FD(t,(s)) = (s); \
	SLAP_DEVPOLL_SOCK_EV(t,(s)) = POLLIN; \
606
	SLAP_DEVPOLL_WRITE_POLLFD(t,(s), &SLAP_DEVPOLL_SOCK_EP(t, (s)), 1, "ADD", 1); \
607
	slap_daemon[t].sd_nfds++; \
608
609
610
611
} while (0)

# define SLAP_DEVPOLL_EV_LISTENER(ptr)	((ptr) != NULL)

612
613
# define SLAP_SOCK_DEL(t,s)		do { \
	int fd, index = SLAP_DEVPOLL_SOCK_IX(t,(s)); \
Ondřej Kuzník's avatar
Ondřej Kuzník committed
614
	Debug( LDAP_DEBUG_CONNS, "SLAP_SOCK_DEL(%d)\n", (s) ); \
615
	if ( index < 0 ) break; \
616
617
618
619
620
621
	if ( index < slap_daemon[t].sd_nfds - 1 ) { \
		struct pollfd pfd = slap_daemon[t].sd_pollfd[index]; \
		fd = slap_daemon[t].sd_pollfd[slap_daemon[t].sd_nfds - 1].fd; \
		slap_daemon[t].sd_pollfd[index] = slap_daemon[t].sd_pollfd[slap_daemon[t].sd_nfds - 1]; \
		slap_daemon[t].sd_pollfd[slap_daemon[t].sd_nfds - 1] = pfd; \
		slap_daemon[t].sd_index[fd] = index; \
622
	} \
623
624
625
626
627
	slap_daemon[t].sd_index[(s)] = -1; \
	slap_daemon[t].sd_pollfd[slap_daemon[t].sd_nfds - 1].events = POLLREMOVE; \
	SLAP_DEVPOLL_WRITE_POLLFD(t,(s), &slap_daemon[t].sd_pollfd[slap_daemon[t].sd_nfds - 1], 1, "DEL", 0); \
	slap_daemon[t].sd_pollfd[slap_daemon[t].sd_nfds - 1].events = 0; \
	slap_daemon[t].sd_nfds--; \
628
629
630
631
632
633
634
} while (0)

# define SLAP_EVENT_CLR_READ(i)		SLAP_DEVPOLL_EVENT_CLR((i), POLLIN)
# define SLAP_EVENT_CLR_WRITE(i)	SLAP_DEVPOLL_EVENT_CLR((i), POLLOUT)

# define SLAP_DEVPOLL_EVENT_CHK(i, mode)	(revents[(i)].events & (mode))

635
# define SLAP_EVENT_FD(t,i)		(revents[(i)].fd)
636
637
638

# define SLAP_EVENT_IS_READ(i)		SLAP_DEVPOLL_EVENT_CHK((i), POLLIN)
# define SLAP_EVENT_IS_WRITE(i)		SLAP_DEVPOLL_EVENT_CHK((i), POLLOUT)
639
640
# define SLAP_EVENT_IS_LISTENER(t,i)	SLAP_DEVPOLL_EV_LISTENER(SLAP_DEVPOLL_SOCK_LX(t, SLAP_EVENT_FD(t,(i))))
# define SLAP_EVENT_LISTENER(t,i)		SLAP_DEVPOLL_SOCK_LX(t, SLAP_EVENT_FD(t,(i)))
641

642
643
644
645
646
647
648
649
650
651
# define SLAP_SOCK_DESTROY(t)		do { \
	if ( slap_daemon[t].sd_pollfd != NULL ) { \
		ch_free( slap_daemon[t].sd_pollfd ); \
		slap_daemon[t].sd_pollfd = NULL; \
		slap_daemon[t].sd_index = NULL; \
		slap_daemon[t].sd_l = NULL; \
		close( slap_daemon[t].sd_dpfd ); \
	} \
} while ( 0 )

652
653
# define SLAP_SOCK_INIT(t)		do { \
	slap_daemon[t].sd_pollfd = ch_calloc( 1, \
654
655
656
		( sizeof(struct pollfd) * 2 \
			+ sizeof( int ) \
			+ sizeof( Listener * ) ) * dtblsize ); \
657
658
659
660
	slap_daemon[t].sd_index = (int *)&slap_daemon[t].sd_pollfd[ 2 * dtblsize ]; \
	slap_daemon[t].sd_l = (Listener **)&slap_daemon[t].sd_index[ dtblsize ]; \
	slap_daemon[t].sd_dpfd = open( SLAP_EVENT_FNAME, O_RDWR ); \
	if ( slap_daemon[t].sd_dpfd == -1 ) { \
661
		int saved_errno = errno; \
662
663
		Debug( LDAP_DEBUG_ANY, "daemon: " SLAP_EVENT_FNAME ": " \
			"open(\"" SLAP_EVENT_FNAME "\") failed errno=%d\n", \
664
			saved_errno ); \
665
		SLAP_SOCK_DESTROY(t); \
666
667
668
		return -1; \
	} \
	for ( i = 0; i < dtblsize; i++ ) { \
669
670
		slap_daemon[t].sd_pollfd[i].fd = -1; \
		slap_daemon[t].sd_index[i] = -1; \
671
672
673
	} \
} while (0)

674
675
# define SLAP_SOCK_INIT2()

676
677
# define SLAP_EVENT_DECL		struct pollfd *revents

678
679
# define SLAP_EVENT_INIT(t)		do { \
	revents = &slap_daemon[t].sd_pollfd[ dtblsize ]; \
680
681
} while (0)

682
# define SLAP_EVENT_WAIT(t, tvp, nsp)	do { \
683
	struct dvpoll		sd_dvpoll; \
684
	sd_dvpoll.dp_timeout = (tvp) ? ((tvp)->tv_sec * 1000 + (tvp)->tv_usec / 1000) : -1; \
685
686
	sd_dvpoll.dp_nfds = dtblsize; \
	sd_dvpoll.dp_fds = revents; \
687
	*(nsp) = ioctl( slap_daemon[t].sd_dpfd, DP_POLL, &sd_dvpoll ); \
688
689
} while (0)

690
#else /* ! kqueue && ! epoll && ! /dev/poll */
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
# ifdef HAVE_WINSOCK
# define SLAP_EVENT_FNAME		"WSselect"
/* Winsock provides a "select" function but its fd_sets are
 * actually arrays of sockets. Since these sockets are handles
 * and not a contiguous range of small integers, we manage our
 * own "fd" table of socket handles and use their indices as
 * descriptors.
 *
 * All of our listener/connection structures use fds; the actual
 * I/O functions use sockets. The SLAP_FD2SOCK macro in proto-slap.h
 * handles the mapping.
 *
 * Despite the mapping overhead, this is about 45% more efficient
 * than just using Winsock's select and FD_ISSET directly.
 *
 * Unfortunately Winsock's select implementation doesn't scale well
 * as the number of connections increases. This probably needs to be
 * rewritten to use the Winsock overlapped/asynchronous I/O functions.
 */
# define SLAP_EVENTS_ARE_INDEXED	1
711
712
# define SLAP_EVENT_DECL		fd_set readfds, writefds; char *rflags
# define SLAP_EVENT_INIT(t)	do { \
713
714
715
	int i; \
	FD_ZERO( &readfds ); \
	FD_ZERO( &writefds ); \
716
717
718
719
	rflags = slap_daemon[t].sd_rflags; \
	memset( rflags, 0, slap_daemon[t].sd_nfds ); \
	for ( i=0; i<slap_daemon[t].sd_nfds; i++ ) { \
		if ( slap_daemon[t].sd_flags[i] & SD_READ ) \
720
			FD_SET( slapd_ws_sockets[i], &readfds );\
721
		if ( slap_daemon[t].sd_flags[i] & SD_WRITE ) \
722
723
724
			FD_SET( slapd_ws_sockets[i], &writefds ); \
	} } while ( 0 )

725
# define SLAP_EVENT_MAX(t)		slap_daemon[t].sd_nfds
726

727
# define SLAP_EVENT_WAIT(t, tvp, nsp)	do { \
728
	int i; \
Pierangelo Masarati's avatar
Pierangelo Masarati committed
729
	*(nsp) = select( SLAP_EVENT_MAX(t), &readfds, \
730
731
732
733
		nwriters > 0 ? &writefds : NULL, NULL, (tvp) ); \
	for ( i=0; i<readfds.fd_count; i++) { \
		int fd = slapd_sock2fd(readfds.fd_array[i]); \
		if ( fd >= 0 ) { \
734
			slap_daemon[t].sd_rflags[fd] = SD_READ; \
735
736
737
738
739
740
			if ( fd >= *(nsp)) *(nsp) = fd+1; \
		} \
	} \
	for ( i=0; i<writefds.fd_count; i++) { \
		int fd = slapd_sock2fd(writefds.fd_array[i]); \
		if ( fd >= 0 ) { \
741
			slap_daemon[t].sd_rflags[fd] = SD_WRITE; \
742
743
744
745
746
			if ( fd >= *(nsp)) *(nsp) = fd+1; \
		} \
	} \
} while (0)

747
748
# define SLAP_EVENT_IS_READ(fd)		(rflags[fd] & SD_READ)
# define SLAP_EVENT_IS_WRITE(fd)	(rflags[fd] & SD_WRITE)
749

750
751
# define SLAP_EVENT_CLR_READ(fd) 	rflags[fd] &= ~SD_READ
# define SLAP_EVENT_CLR_WRITE(fd)	rflags[fd] &= ~SD_WRITE
752

753
754
# define SLAP_SOCK_INIT(t)		do { \
	if (!t) { \
755
756
757
	ldap_pvt_thread_mutex_init( &slapd_ws_mutex ); \
	slapd_ws_sockets = ch_malloc( dtblsize * ( sizeof(SOCKET) + 2)); \
	memset( slapd_ws_sockets, -1, dtblsize * sizeof(SOCKET) ); \
758
759
760
761
	} \
	slap_daemon[t].sd_flags = (char *)(slapd_ws_sockets + dtblsize); \
	slap_daemon[t].sd_rflags = slap_daemon[t].sd_flags + dtblsize; \
	memset( slap_daemon[t].sd_flags, 0, dtblsize ); \
Howard Chu's avatar
Howard Chu committed
762
763
	slapd_ws_sockets[t*2] = wake_sds[t][0]; \
	slapd_ws_sockets[t*2+1] = wake_sds[t][1]; \
764
765
	wake_sds[t][0] = t*2; \
	wake_sds[t][1] = t*2+1; \
Howard Chu's avatar
Howard Chu committed
766
	slap_daemon[t].sd_nfds = t*2 + 2; \
767
768
	} while ( 0 )

769
770
# define SLAP_SOCK_INIT2()

771
# define SLAP_SOCK_DESTROY(t)	do { \
772
	ch_free( slapd_ws_sockets ); slapd_ws_sockets = NULL; \
773
774
	slap_daemon[t].sd_flags = NULL; \
	slap_daemon[t].sd_rflags = NULL; \
775
776
777
	ldap_pvt_thread_mutex_destroy( &slapd_ws_mutex ); \
	} while ( 0 )

778
779
780
781
# define SLAP_SOCK_IS_ACTIVE(t,fd) ( slap_daemon[t].sd_flags[fd] & SD_ACTIVE )
# define SLAP_SOCK_IS_READ(t,fd) ( slap_daemon[t].sd_flags[fd] & SD_READ )
# define SLAP_SOCK_IS_WRITE(t,fd) ( slap_daemon[t].sd_flags[fd] & SD_WRITE )
# define SLAP_SOCK_NOT_ACTIVE(t,fd)	(!slap_daemon[t].sd_flags[fd])
782

783
784
# define SLAP_SOCK_SET_READ(t,fd)		( slap_daemon[t].sd_flags[fd] |= SD_READ )
# define SLAP_SOCK_SET_WRITE(t,fd)		( slap_daemon[t].sd_flags[fd] |= SD_WRITE )
785

786
787
# define SLAP_SELECT_ADDTEST(t,s)	do { \
	if ((s) >= slap_daemon[t].sd_nfds) slap_daemon[t].sd_nfds = (s)+1; \
788
789
} while (0)

790
791
# define SLAP_SOCK_CLR_READ(t,fd)		( slap_daemon[t].sd_flags[fd] &= ~SD_READ )
# define SLAP_SOCK_CLR_WRITE(t,fd)		( slap_daemon[t].sd_flags[fd] &= ~SD_WRITE )
792

793
794
795
# define SLAP_SOCK_ADD(t,s, l)	do { \
	SLAP_SELECT_ADDTEST(t,(s)); \
	slap_daemon[t].sd_flags[s] = SD_ACTIVE|SD_READ; \
796
797
} while ( 0 )

798
799
# define SLAP_SOCK_DEL(t,s) do { \
	slap_daemon[t].sd_flags[s] = 0; \
800
801
802
803
	slapd_sockdel( s ); \
} while ( 0 )

# else /* !HAVE_WINSOCK */
804
805
806
807
808

/**************************************
 * Use select system call - select(2) *
 **************************************/
# define SLAP_EVENT_FNAME		"select"
809
/* select */
810
811
# define SLAP_EVENTS_ARE_INDEXED	1
# define SLAP_EVENT_DECL		fd_set readfds, writefds
812

813
814
# define SLAP_EVENT_INIT(t)		do { \
	AC_MEMCPY( &readfds, &slap_daemon[t].sd_readers, sizeof(fd_set) );	\
815
	if ( nwriters )	{ \
816
		AC_MEMCPY( &writefds, &slap_daemon[t].sd_writers, sizeof(fd_set) ); \
817
818
819
820
821
822
	} else { \
		FD_ZERO( &writefds ); \
	} \
} while (0)

# ifdef FD_SETSIZE
823
#  define SLAP_SELECT_CHK_SETSIZE	do { \
824
825
	if (dtblsize > FD_SETSIZE) dtblsize = FD_SETSIZE; \
} while (0)
826
827
828
# else /* ! FD_SETSIZE */
#  define SLAP_SELECT_CHK_SETSIZE	do { ; } while (0)
# endif /* ! FD_SETSIZE */
829

830
# define SLAP_SOCK_INIT(t)			do { \
831
	SLAP_SELECT_CHK_SETSIZE; \
832
833
834
	FD_ZERO(&slap_daemon[t].sd_actives); \
	FD_ZERO(&slap_daemon[t].sd_readers); \
	FD_ZERO(&slap_daemon[t].sd_writers); \
835
836
} while (0)

837
838
# define SLAP_SOCK_INIT2()

839
# define SLAP_SOCK_DESTROY(t)
840

841
842
843
# define SLAP_SOCK_IS_ACTIVE(t,fd)	FD_ISSET((fd), &slap_daemon[t].sd_actives)
# define SLAP_SOCK_IS_READ(t,fd)		FD_ISSET((fd), &slap_daemon[t].sd_readers)
# define SLAP_SOCK_IS_WRITE(t,fd)		FD_ISSET((fd), &slap_daemon[t].sd_writers)
844

845
846
# define SLAP_SOCK_NOT_ACTIVE(t,fd)	(!SLAP_SOCK_IS_ACTIVE(t,fd) && \
	 !SLAP_SOCK_IS_READ(t,fd) && !SLAP_SOCK_IS_WRITE(t,fd))
847

848
849
# define SLAP_SOCK_SET_READ(t,fd)	FD_SET((fd), &slap_daemon[t].sd_readers)
# define SLAP_SOCK_SET_WRITE(t,fd)	FD_SET((fd), &slap_daemon[t].sd_writers)
850

851
852
853
# define SLAP_EVENT_MAX(t)		slap_daemon[t].sd_nfds
# define SLAP_SELECT_ADDTEST(t,s)	do { \
	if ((s) >= slap_daemon[t].sd_nfds) slap_daemon[t].sd_nfds = (s)+1; \
854
855
} while (0)

856
857
# define SLAP_SOCK_CLR_READ(t,fd)		FD_CLR((fd), &slap_daemon[t].sd_readers)
# define SLAP_SOCK_CLR_WRITE(t,fd)	FD_CLR((fd), &slap_daemon[t].sd_writers)
858

859
860
861
862
# define SLAP_SOCK_ADD(t,s, l)		do { \
	SLAP_SELECT_ADDTEST(t,(s)); \
	FD_SET((s), &slap_daemon[t].sd_actives); \
	FD_SET((s), &slap_daemon[t].sd_readers); \
863
} while (0)
864

865
866
867
868
# define SLAP_SOCK_DEL(t,s)		do { \
	FD_CLR((s), &slap_daemon[t].sd_actives); \
	FD_CLR((s), &slap_daemon[t].sd_readers); \
	FD_CLR((s), &slap_daemon[t].sd_writers); \
869
} while (0)
870

871
872
# define SLAP_EVENT_IS_READ(fd)		FD_ISSET((fd), &readfds)
# define SLAP_EVENT_IS_WRITE(fd)	FD_ISSET((fd), &writefds)
873

874
875
# define SLAP_EVENT_CLR_READ(fd) 	FD_CLR((fd), &readfds)
# define SLAP_EVENT_CLR_WRITE(fd)	FD_CLR((fd), &writefds)
876

877
# define SLAP_EVENT_WAIT(t, tvp, nsp)	do { \
Pierangelo Masarati's avatar
Pierangelo Masarati committed
878
	*(nsp) = select( SLAP_EVENT_MAX(t), &readfds, \
879
880
		nwriters > 0 ? &writefds : NULL, NULL, (tvp) ); \
} while (0)
881
# endif /* !HAVE_WINSOCK */
882
#endif /* ! kqueue && ! epoll && ! /dev/poll */
883
884
885
886
887
888
889
890

#ifdef HAVE_SLP
/*
 * SLP related functions
 */
#include <slp.h>

#define LDAP_SRVTYPE_PREFIX "service:ldap://"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
891
892
#define LDAPS_SRVTYPE_PREFIX "service:ldaps://"
static char** slapd_srvurls = NULL;
893
static SLPHandle slapd_hslp = 0;
894
int slapd_register_slp = 0;
895
const char *slapd_slp_attrs = NULL;
896
897

static SLPError slapd_slp_cookie;
898

899
900
901
static void
slapd_slp_init( const char* urls )
{
902
	int i;
903
	SLPError err;
904

905
	slapd_srvurls = ldap_str2charray( urls, " " );
906

907
	if ( slapd_srvurls == NULL ) return;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
908
909

	/* find and expand INADDR_ANY URLs */
910
911
	for ( i = 0; slapd_srvurls[i] != NULL; i++ ) {
		if ( strcmp( slapd_srvurls[i], "ldap:///" ) == 0 ) {
Howard Chu's avatar
Howard Chu committed
912
			slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
913
				global_host_bv.bv_len +
Howard Chu's avatar
Howard Chu committed
914
915
				sizeof( LDAP_SRVTYPE_PREFIX ) );
			strcpy( lutil_strcopy(slapd_srvurls[i],
916
				LDAP_SRVTYPE_PREFIX ), global_host_bv.bv_val );
917
		} else if ( strcmp( slapd_srvurls[i], "ldaps:///" ) == 0 ) {
Howard Chu's avatar
Howard Chu committed
918
			slapd_srvurls[i] = (char *) ch_realloc( slapd_srvurls[i],
919
				global_host_bv.bv_len +
Howard Chu's avatar
Howard Chu committed
920
921
				sizeof( LDAPS_SRVTYPE_PREFIX ) );
			strcpy( lutil_strcopy(slapd_srvurls[i],
922
				LDAPS_SRVTYPE_PREFIX ), global_host_bv.bv_val );
923
924
925
926
		}
	}

	/* open the SLP handle */
927
928
	err = SLPOpen( "en", 0, &slapd_hslp );

929
	if ( err != SLP_OK ) {
930
		Debug( LDAP_DEBUG_CONNS, "daemon: SLPOpen() failed with %ld\n",
931
			(long)err );
932
	}
933
934
}

935
936
937
938
static void
slapd_slp_deinit( void )
{
	if ( slapd_srvurls == NULL ) return;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
939

940
	ldap_charray_free( slapd_srvurls );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
941
	slapd_srvurls = NULL;
942
943
944
945
946

	/* close the SLP handle */
	SLPClose( slapd_hslp );
}

947
948
949
950
951
static void
slapd_slp_regreport(
	SLPHandle	hslp,
	SLPError	errcode,
	void		*cookie )
952
{
953
954
	/* return the error code in the cookie */
	*(SLPError*)cookie = errcode; 
955
956
}

957
958
959
static void
slapd_slp_reg()
{
960
	int i;
961
	SLPError err;
962

963
	if ( slapd_srvurls == NULL ) return;
964

965
966
	for ( i = 0; slapd_srvurls[i] != NULL; i++ ) {
		if ( strncmp( slapd_srvurls[i], LDAP_SRVTYPE_PREFIX,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
967
				sizeof( LDAP_SRVTYPE_PREFIX ) - 1 ) == 0 ||
968
			strncmp( slapd_srvurls[i], LDAPS_SRVTYPE_PREFIX,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
969
970
				sizeof( LDAPS_SRVTYPE_PREFIX ) - 1 ) == 0 )
		{
971
			err = SLPReg( slapd_hslp,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
972
973
974
				slapd_srvurls[i],
				SLP_LIFETIME_MAXIMUM,
				"ldap",
975
976
				(slapd_slp_attrs) ? slapd_slp_attrs : "",
				SLP_TRUE,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
977
				slapd_slp_regreport,
978
				&slapd_slp_cookie );
979

980
			if ( err != SLP_OK || slapd_slp_cookie != SLP_OK ) {
981
982
983
984
				Debug( LDAP_DEBUG_CONNS,
					"daemon: SLPReg(%s) failed with %ld, cookie = %ld\n",
					slapd_srvurls[i], (long)err, (long)slapd_slp_cookie );
			}	
Kurt Zeilenga's avatar
Kurt Zeilenga committed
985
		}
986
987
988
	}
}

989
990
991
static void
slapd_slp_dereg( void )
{
992
	int i;
993
	SLPError err;
994

995
	if ( slapd_srvurls == NULL ) return;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
996

997
	for ( i = 0; slapd_srvurls[i] != NULL; i++ ) {
998
		err = SLPDereg( slapd_hslp,
999
1000
			slapd_srvurls[i],
			slapd_slp_regreport,
1001
			&slapd_slp_cookie );
1002
		
1003
		if ( err != SLP_OK || slapd_slp_cookie != SLP_OK ) {
1004
1005
1006
1007
			Debug( LDAP_DEBUG_CONNS,
				"daemon: SLPDereg(%s) failed with %ld, cookie = %ld\n",
				slapd_srvurls[i], (long)err, (long)slapd_slp_cookie );
		}
1008
1009
1010
	}
}
#endif /* HAVE_SLP */
1011

1012
1013
1014
1015
1016
1017
1018
1019