slap.h 15 KB
Newer Older
Ondřej Kuzník's avatar
Ondřej Kuzník committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* slap.h - stand alone ldap server include file */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
 * Copyright 1998-2015 The OpenLDAP Foundation.
 * 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.
 */

#ifndef _SLAP_H_
#define _SLAP_H_

#include "ldap_defaults.h"

#include <stdio.h>
#include <ac/stdlib.h>

#include <sys/types.h>
#include <ac/syslog.h>
#include <ac/regex.h>
#include <ac/signal.h>
#include <ac/socket.h>
#include <ac/time.h>
#include <ac/param.h>

#include "avl.h"

#ifndef ldap_debug
#define ldap_debug slap_debug
#endif

#include "ldap_log.h"

#include <ldap.h>
#include <ldap_schema.h>

#include "lber_pvt.h"
#include "ldap_pvt.h"
#include "ldap_pvt_thread.h"
#include "ldap_queue.h"

#include <event2/event.h>

LDAP_BEGIN_DECL

/*
 * SLAPD Memory allocation macros
 *
 * Unlike ch_*() routines, these routines do not assert() upon
 * allocation error.  They are intended to be used instead of
 * ch_*() routines where the caller has implemented proper
 * checking for and handling of allocation errors.
 *
 * Patches to convert ch_*() calls to SLAP_*() calls welcomed.
 */
#define SLAP_MALLOC(s) ber_memalloc( ( s ) )
#define SLAP_CALLOC(n, s) ber_memcalloc( ( n ), ( s ) )
#define SLAP_REALLOC(p, s) ber_memrealloc( ( p ), ( s ) )
#define SLAP_FREE(p) ber_memfree( ( p ) )
#define SLAP_VFREE(v) ber_memvfree( (void **)( v ) )
#define SLAP_STRDUP(s) ber_strdup( ( s ) )
#define SLAP_STRNDUP(s, l) ber_strndup( ( s ), ( l ) )

#define SERVICE_NAME OPENLDAP_PACKAGE "-slapd"
#define SLAPD_ANONYMOUS ""
#define SLAP_STRING_UNKNOWN "unknown"

#define SLAP_MAX_WORKER_THREADS ( 16 )

87
88
#define SLAP_SB_MAX_INCOMING_CLIENT ( ( 1 << 18 ) - 1 )
#define SLAP_SB_MAX_INCOMING_UPSTREAM ( ( 1 << 24 ) - 1 )
Ondřej Kuzník's avatar
Ondřej Kuzník committed
89

Ondřej Kuzník's avatar
Ondřej Kuzník committed
90
91
#define SLAP_CONN_MAX_PDUS_PER_CYCLE_DEFAULT 10

Ondřej Kuzník's avatar
Ondřej Kuzník committed
92
93
94
95
96
#define SLAP_TEXT_BUFLEN ( 256 )

/* unknown config file directive */
#define SLAP_CONF_UNKNOWN ( -1026 )

97
98
#define BER_BV_OPTIONAL( bv ) ( BER_BVISNULL( bv ) ? NULL : ( bv ) )

Ondřej Kuzník's avatar
Ondřej Kuzník committed
99
100
101
102
LDAP_SLAPD_V (int) slap_debug;

typedef unsigned long slap_mask_t;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
103
typedef struct Backend Backend;
104
typedef struct PendingConnection PendingConnection;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
105
typedef struct Connection Connection;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
106
typedef struct Operation Operation;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* end of forward declarations */

typedef union Sockaddr {
    struct sockaddr sa_addr;
    struct sockaddr_in sa_in_addr;
#ifdef LDAP_PF_INET6
    struct sockaddr_storage sa_storage;
    struct sockaddr_in6 sa_in6_addr;
#endif
#ifdef LDAP_PF_LOCAL
    struct sockaddr_un sa_un_addr;
#endif
} Sockaddr;

#ifdef LDAP_PF_INET6
extern int slap_inet4or6;
#endif

125
typedef LDAP_CIRCLEQ_HEAD(BeSt, Backend) slap_b_head;
126
typedef LDAP_CIRCLEQ_HEAD(ClientSt, Connection) slap_c_head;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
127
128

LDAP_SLAPD_V (slap_b_head) backend;
129
LDAP_SLAPD_V (slap_c_head) clients;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
130
131
LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) backend_mutex;
LDAP_SLAPD_V (Backend *) current_backend;
132
LDAP_SLAPD_V (struct slap_bindconf) bindconf;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
133
LDAP_SLAPD_V (struct berval) lloadd_identity;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
134

Ondřej Kuzník's avatar
Ondřej Kuzník committed
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
LDAP_SLAPD_V (int) slapMode;
#define SLAP_UNDEFINED_MODE 0x0000
#define SLAP_SERVER_MODE 0x0001
#define SLAP_TOOL_MODE 0x0002
#define SLAP_MODE 0x0003

#define SLAP_SERVER_RUNNING 0x8000

#define SB_TLS_DEFAULT ( -1 )
#define SB_TLS_OFF 0
#define SB_TLS_ON 1
#define SB_TLS_CRITICAL 2

typedef struct slap_keepalive {
    int sk_idle;
    int sk_probes;
    int sk_interval;
} slap_keepalive;

typedef struct slap_bindconf {
    struct berval sb_uri;
    int sb_version;
    int sb_tls;
    int sb_method;
    int sb_timeout_api;
    int sb_timeout_net;
    struct berval sb_binddn;
    struct berval sb_cred;
    struct berval sb_saslmech;
    char *sb_secprops;
    struct berval sb_realm;
    struct berval sb_authcId;
    struct berval sb_authzId;
    slap_keepalive sb_keepalive;
#ifdef HAVE_TLS
    void *sb_tls_ctx;
    char *sb_tls_cert;
    char *sb_tls_key;
    char *sb_tls_cacert;
    char *sb_tls_cacertdir;
    char *sb_tls_reqcert;
    char *sb_tls_reqsan;
    char *sb_tls_cipher_suite;
    char *sb_tls_protocol_min;
    char *sb_tls_ecname;
#ifdef HAVE_OPENSSL
    char *sb_tls_crlcheck;
#endif
    int sb_tls_int_reqcert;
    int sb_tls_int_reqsan;
    int sb_tls_do_init;
#endif
} slap_bindconf;

typedef struct slap_verbmasks {
    struct berval word;
    const slap_mask_t mask;
} slap_verbmasks;

typedef struct slap_cf_aux_table {
    struct berval key;
    int off;
    char type;
    char quote;
    void *aux;
} slap_cf_aux_table;

typedef int slap_cf_aux_table_parse_x( struct berval *val,
        void *bc,
        slap_cf_aux_table *tab0,
        const char *tabmsg,
        int unparse );

#define SLAP_RESTRICT_OP_ADD 0x0001U
#define SLAP_RESTRICT_OP_BIND 0x0002U
#define SLAP_RESTRICT_OP_COMPARE 0x0004U
#define SLAP_RESTRICT_OP_DELETE 0x0008U
#define SLAP_RESTRICT_OP_EXTENDED 0x0010U
#define SLAP_RESTRICT_OP_MODIFY 0x0020U
#define SLAP_RESTRICT_OP_RENAME 0x0040U
#define SLAP_RESTRICT_OP_SEARCH 0x0080U
#define SLAP_RESTRICT_OP_MASK 0x00FFU

#define SLAP_RESTRICT_READONLY 0x80000000U

#define SLAP_RESTRICT_EXOP_START_TLS 0x0100U
#define SLAP_RESTRICT_EXOP_MODIFY_PASSWD 0x0200U
#define SLAP_RESTRICT_EXOP_WHOAMI 0x0400U
#define SLAP_RESTRICT_EXOP_CANCEL 0x0800U
#define SLAP_RESTRICT_EXOP_MASK 0xFF00U

#define SLAP_RESTRICT_OP_READS \
    ( SLAP_RESTRICT_OP_COMPARE | SLAP_RESTRICT_OP_SEARCH )
#define SLAP_RESTRICT_OP_WRITES \
    ( SLAP_RESTRICT_OP_ADD | SLAP_RESTRICT_OP_DELETE | SLAP_RESTRICT_OP_MODIFY | SLAP_RESTRICT_OP_RENAME )
#define SLAP_RESTRICT_OP_ALL \
    ( SLAP_RESTRICT_OP_READS | SLAP_RESTRICT_OP_WRITES | SLAP_RESTRICT_OP_BIND | SLAP_RESTRICT_OP_EXTENDED )

typedef struct config_reply_s ConfigReply; /* config.h */

typedef struct Listener Listener;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
237
typedef enum {
238
#ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
Ondřej Kuzník's avatar
Ondřej Kuzník committed
239
    LLOAD_FEATURE_VC = 1 << 0,
240
#endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
241
242
243
    LLOAD_FEATURE_PROXYAUTHZ = 1 << 1,
} lload_features_t;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
244
245
246
247
248
249
enum lload_tls_type {
    LLOAD_CLEARTEXT = 0,
    LLOAD_LDAPS,
    LLOAD_STARTTLS,
};

250
251
252
253
254
255
256
257
258
struct PendingConnection {
    Backend *backend;

    struct event *event;
    ber_socket_t fd;

    LDAP_LIST_ENTRY(PendingConnection) next;
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
259
/* Can hold mutex when locking a linked connection */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
260
struct Backend {
Ondřej Kuzník's avatar
Ondřej Kuzník committed
261
    ldap_pvt_thread_mutex_t b_mutex;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
262

263
    struct berval b_uri;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
264
265
266
267
    int b_proto, b_port;
    enum lload_tls_type b_tls;
    char *b_host;

268
269
270
271
    int b_retry_timeout, b_failed;
    struct event *b_retry_event;
    struct timeval b_retry_tv;

Ondřej Kuzník's avatar
Ondřej Kuzník committed
272
    int b_numconns, b_numbindconns;
273
    int b_bindavail, b_active, b_opening;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
274
    LDAP_CIRCLEQ_HEAD(ConnSt, Connection) b_conns, b_bindconns, b_preparing;
275
    LDAP_LIST_HEAD(ConnectingSt, PendingConnection) b_connecting;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
276

277
278
279
    long b_max_pending, b_max_conn_pending;
    long b_n_ops_executing;

280
    LDAP_CIRCLEQ_ENTRY(Backend) b_next;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
281
282
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
283
typedef int (*OperationHandler)( Operation *op, BerElement *ber );
284
typedef int (*RequestHandler)( Connection *c, Operation *op );
Ondřej Kuzník's avatar
Ondřej Kuzník committed
285
286
287
288
typedef struct lload_exop_handlers_t {
    struct berval oid;
    RequestHandler func;
} ExopHandler;
289
290
291

typedef int (*CONNECTION_PDU_CB)( Connection *c );
typedef void (*CONNECTION_DESTROY_CB)( Connection *c );
Ondřej Kuzník's avatar
Ondřej Kuzník committed
292

Ondřej Kuzník's avatar
Ondřej Kuzník committed
293
/* connection state (protected by c_mutex) */
294
enum sc_state {
Ondřej Kuzník's avatar
Ondřej Kuzník committed
295
    SLAP_C_INVALID = 0, /* MUST BE ZERO (0) */
296
    SLAP_C_READY,       /* ready */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
297
    SLAP_C_CLOSING,     /* closing */
298
    SLAP_C_ACTIVE,      /* exclusive operation (tls setup, ...) in progress */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
299
300
    SLAP_C_BINDING,     /* binding */
};
301
enum sc_type {
Ondřej Kuzník's avatar
Ondřej Kuzník committed
302
303
    SLAP_C_OPEN = 0,  /* regular connection */
    SLAP_C_PREPARING, /* upstream connection not assigned yet */
304
    SLAP_C_BIND, /* connection used to handle bind client requests if VC not enabled */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
305
    SLAP_C_PRIVILEGED, /* connection can override proxyauthz control */
306
};
307
308
309
/*
 * represents a connection from an ldap client/to ldap server
 */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
310
struct Connection {
311
    enum sc_state c_state; /* connection state */
312
    enum sc_type c_type;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
313
    ber_socket_t c_fd;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
314

315
316
317
318
319
320
321
322
323
324
/*
 * Connection reference counting:
 * - connection has a reference counter in c_refcnt
 * - also a liveness/validity token is added to c_refcnt during
 *   connection_init, its existence is tracked in c_live and is usually the
 *   only one that prevents it from being destroyed
 * - anyone who needs to be able to lock the connection after unlocking it has
 *   to use CONNECTION_UNLOCK_INCREF, they are then responsible that
 *   CONNECTION_LOCK_DECREF+CONNECTION_UNLOCK_OR_DESTROY is used when they are
 *   done with it
325
326
327
328
329
330
 * - when a connection is considered dead, use CONNECTION_DESTROY on a locked
 *   connection, it might get disposed of or if anyone still holds a token, it
 *   just gets unlocked and it's the last token holder's responsibility to run
 *   CONNECTION_UNLOCK_OR_DESTROY
 * - CONNECTION_LOCK_DESTROY is a shorthand for locking, decreasing refcount
 *   and CONNECTION_DESTROY
331
 */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
332
    ldap_pvt_thread_mutex_t c_mutex; /* protect the connection */
333
    int c_refcnt, c_live;
334
335
    CONNECTION_DESTROY_CB c_destroy;
    CONNECTION_PDU_CB c_pdu_cb;
336
337
338
339
340
341
342
343
344
345
346
347
#define CONNECTION_LOCK(c) ldap_pvt_thread_mutex_lock( &(c)->c_mutex )
#define CONNECTION_UNLOCK(c) ldap_pvt_thread_mutex_unlock( &(c)->c_mutex )
#define CONNECTION_LOCK_DECREF(c) \
    do { \
        CONNECTION_LOCK(c); \
        (c)->c_refcnt--; \
    } while (0)
#define CONNECTION_UNLOCK_INCREF(c) \
    do { \
        (c)->c_refcnt++; \
        CONNECTION_UNLOCK(c); \
    } while (0)
348
#define CONNECTION_UNLOCK_OR_DESTROY(c) \
349
350
351
    do { \
        assert( (c)->c_refcnt >= 0 ); \
        if ( !( c )->c_refcnt ) { \
352
            Debug( LDAP_DEBUG_TRACE, "%s: destroying connection connid=%lu\n", \
353
                    __func__, (c)->c_connid ); \
354
            (c)->c_destroy( (c) ); \
355
356
357
358
359
            (c) = NULL; \
        } else { \
            CONNECTION_UNLOCK(c); \
        } \
    } while (0)
360
#define CONNECTION_DESTROY(c) \
361
362
363
    do { \
        (c)->c_refcnt -= (c)->c_live; \
        (c)->c_live = 0; \
364
        CONNECTION_UNLOCK_OR_DESTROY(c); \
365
    } while (0)
366
#define CONNECTION_LOCK_DESTROY(c) \
367
368
    do { \
        CONNECTION_LOCK_DECREF(c); \
369
        CONNECTION_DESTROY(c); \
370
371
372
    } while (0);

    Sockbuf *c_sb; /* ber connection stuff */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
373
374
375
376
377
378

    /* set by connection_init */
    unsigned long c_connid;    /* unique id of this connection */
    struct berval c_peer_name; /* peer name (trans=addr:port) */
    time_t c_starttime;        /* when the connection was opened */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
379
380
    time_t c_activitytime;  /* when the connection was last used */
    ber_int_t c_next_msgid; /* msgid of the next message */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
381

382
    /* must not be used while holding either mutex */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
383
384
385
386
    struct event *c_read_event, *c_write_event;

    /* can only be changed by binding thread */
    struct berval c_sasl_bind_mech; /* mech in progress */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
387
388
    struct berval c_auth;           /* authcDN (possibly in progress) */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
389
#ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
Ondřej Kuzník's avatar
Ondřej Kuzník committed
390
    struct berval c_vc_cookie;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
391
#endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
392

Ondřej Kuzník's avatar
Ondřej Kuzník committed
393
394
    /* Can be held while acquiring c_mutex to inject things into c_ops or
     * destroy the connection */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
395
396
    ldap_pvt_thread_mutex_t c_io_mutex; /* only one pdu written at a time */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
397
398
    BerElement *c_currentber; /* ber we're attempting to read */
    BerElement *c_pendingber; /* ber we're attempting to write */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
399

Ondřej Kuzník's avatar
Ondřej Kuzník committed
400
401
    TAvlnode *c_ops; /* Operations pending on the connection */

Ondřej Kuzník's avatar
Ondřej Kuzník committed
402
#define CONN_IS_TLS 1
403
#define CONN_IS_BIND 4
Ondřej Kuzník's avatar
Ondřej Kuzník committed
404
405
406
#define CONN_IS_IPC 8

#ifdef HAVE_TLS
Ondřej Kuzník's avatar
Ondřej Kuzník committed
407
408
    enum lload_tls_type c_is_tls; /* true if this LDAP over raw TLS */
    char c_needs_tls_accept;      /* true if SSL_accept should be called */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
409
410
411
412
413
#endif

    long c_n_ops_executing; /* num of ops currently executing */
    long c_n_ops_completed; /* num of ops completed */

414
415
416
417
418
419
    /*
     * Protected by the CIRCLEQ mutex:
     * - Client: clients_mutex
     * - Upstream: b->b_mutex
     */
    LDAP_CIRCLEQ_ENTRY(Connection) c_next;
420

Ondřej Kuzník's avatar
Ondřej Kuzník committed
421
422
423
    void *c_private;
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
424
425
426
427
enum op_state {
    SLAP_OP_NOT_FREEING = 0,
    SLAP_OP_FREEING_UPSTREAM = 1 << 0,
    SLAP_OP_FREEING_CLIENT = 1 << 1,
428
429
    SLAP_OP_DETACHING_UPSTREAM = 1 << 2,
    SLAP_OP_DETACHING_CLIENT = 1 << 3,
Ondřej Kuzník's avatar
Ondřej Kuzník committed
430
};
431
432
433
434
#define SLAP_OP_FREEING_MASK \
    ( SLAP_OP_FREEING_UPSTREAM | SLAP_OP_FREEING_CLIENT )
#define SLAP_OP_DETACHING_MASK \
    ( SLAP_OP_DETACHING_UPSTREAM | SLAP_OP_DETACHING_CLIENT )
Ondřej Kuzník's avatar
Ondřej Kuzník committed
435

Ondřej Kuzník's avatar
Ondřej Kuzník committed
436
struct Operation {
Ondřej Kuzník's avatar
Ondřej Kuzník committed
437
438
439
440
441
442
443
444
445
    Connection *o_client;
    unsigned long o_client_connid;
    int o_client_live, o_client_refcnt;
    ber_int_t o_client_msgid;

    Connection *o_upstream;
    unsigned long o_upstream_connid;
    int o_upstream_live, o_upstream_refcnt;
    ber_int_t o_upstream_msgid;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
446

Ondřej Kuzník's avatar
Ondřej Kuzník committed
447
448
449
450
    /* Protects o_client, o_upstream pointers before we lock their c_mutex if
     * we don't know they are still alive */
    ldap_pvt_thread_mutex_t o_link_mutex;
    /* Protects o_freeing, can be locked while holding c_mutex */
451
    ldap_pvt_thread_mutex_t o_mutex;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
452
453
    /* Consistent w.r.t. o_mutex, only written to while holding
     * op->o_{client,upstream}->c_mutex */
Ondřej Kuzník's avatar
Ondřej Kuzník committed
454
    enum op_state o_freeing;
Ondřej Kuzník's avatar
Ondřej Kuzník committed
455
456
457
458
459
460
    ber_tag_t o_tag;

    BerElement *o_ber;
    BerValue o_request, o_ctrls;
};

Ondřej Kuzník's avatar
Ondřej Kuzník committed
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
#ifdef LDAP_DEBUG
#ifdef LDAP_SYSLOG
#ifdef LOG_LOCAL4
#define SLAP_DEFAULT_SYSLOG_USER LOG_LOCAL4
#endif /* LOG_LOCAL4 */

#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
    Log( (level), ldap_syslog_level, (fmt), (connid), (opid), \
            ( arg1 ), ( arg2 ), ( arg3 ) )
#define StatslogTest( level ) ( ( ldap_debug | ldap_syslog ) & ( level ) )
#else /* !LDAP_SYSLOG */
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
    do { \
        if ( ldap_debug & (level) ) \
            lutil_debug( ldap_debug, (level), (fmt), (connid), (opid), \
                    ( arg1 ), ( arg2 ), ( arg3 ) ); \
    } while (0)
#define StatslogTest( level ) ( ldap_debug & ( level ) )
#endif /* !LDAP_SYSLOG */
#else /* !LDAP_DEBUG */
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) ( (void)0 )
#define StatslogTest( level ) ( 0 )
#endif /* !LDAP_DEBUG */

/*
 * listener; need to access it from monitor backend
 */
struct Listener {
    struct berval sl_url;
    struct berval sl_name;
    mode_t sl_perms;
#ifdef HAVE_TLS
    int sl_is_tls;
#endif
    struct event_base *base;
    struct evconnlistener *listener;
    int sl_mute; /* Listener is temporarily disabled due to emfile */
    int sl_busy; /* Listener is busy (accept thread activated) */
    ber_socket_t sl_sd;
    Sockaddr sl_sa;
#define sl_addr sl_sa.sa_in_addr
#define LDAP_TCP_BUFFER
#ifdef LDAP_TCP_BUFFER
    int sl_tcp_rmem; /* custom TCP read buffer size */
    int sl_tcp_wmem; /* custom TCP write buffer size */
#endif
};

LDAP_END_DECL

#include "proto-slap.h"

#endif /* _SLAP_H_ */