xref: /netbsd-src/external/bsd/openldap/dist/servers/lloadd/lload.h (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1*e670fd5cSchristos /*	$NetBSD: lload.h,v 1.1.1.1 2021/08/14 16:05:25 christos Exp $	*/
2*e670fd5cSchristos 
3*e670fd5cSchristos /* lload.h - load balancer include file */
4*e670fd5cSchristos /* $OpenLDAP$ */
5*e670fd5cSchristos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6*e670fd5cSchristos  *
7*e670fd5cSchristos  * Copyright 1998-2021 The OpenLDAP Foundation.
8*e670fd5cSchristos  * All rights reserved.
9*e670fd5cSchristos  *
10*e670fd5cSchristos  * Redistribution and use in source and binary forms, with or without
11*e670fd5cSchristos  * modification, are permitted only as authorized by the OpenLDAP
12*e670fd5cSchristos  * Public License.
13*e670fd5cSchristos  *
14*e670fd5cSchristos  * A copy of this license is available in the file LICENSE in the
15*e670fd5cSchristos  * top-level directory of the distribution or, alternatively, at
16*e670fd5cSchristos  * <http://www.OpenLDAP.org/license.html>.
17*e670fd5cSchristos  */
18*e670fd5cSchristos /* Portions Copyright (c) 1995 Regents of the University of Michigan.
19*e670fd5cSchristos  * All rights reserved.
20*e670fd5cSchristos  *
21*e670fd5cSchristos  * Redistribution and use in source and binary forms are permitted
22*e670fd5cSchristos  * provided that this notice is preserved and that due credit is given
23*e670fd5cSchristos  * to the University of Michigan at Ann Arbor. The name of the University
24*e670fd5cSchristos  * may not be used to endorse or promote products derived from this
25*e670fd5cSchristos  * software without specific prior written permission. This software
26*e670fd5cSchristos  * is provided ``as is'' without express or implied warranty.
27*e670fd5cSchristos  */
28*e670fd5cSchristos 
29*e670fd5cSchristos #ifndef _LLOAD_H_
30*e670fd5cSchristos #define _LLOAD_H_
31*e670fd5cSchristos 
32*e670fd5cSchristos #include "ldap_defaults.h"
33*e670fd5cSchristos 
34*e670fd5cSchristos #include <stdio.h>
35*e670fd5cSchristos #include <ac/stdlib.h>
36*e670fd5cSchristos 
37*e670fd5cSchristos #include <sys/types.h>
38*e670fd5cSchristos #include <ac/syslog.h>
39*e670fd5cSchristos #include <ac/regex.h>
40*e670fd5cSchristos #include <ac/signal.h>
41*e670fd5cSchristos #include <ac/socket.h>
42*e670fd5cSchristos #include <ac/time.h>
43*e670fd5cSchristos #include <ac/param.h>
44*e670fd5cSchristos 
45*e670fd5cSchristos #include "ldap_avl.h"
46*e670fd5cSchristos 
47*e670fd5cSchristos #include "../servers/slapd/slap.h"
48*e670fd5cSchristos #include "../slapd/back-monitor/back-monitor.h"
49*e670fd5cSchristos 
50*e670fd5cSchristos #ifndef ldap_debug
51*e670fd5cSchristos #define ldap_debug slap_debug
52*e670fd5cSchristos #endif
53*e670fd5cSchristos 
54*e670fd5cSchristos #include "ldap_log.h"
55*e670fd5cSchristos 
56*e670fd5cSchristos #include <ldap.h>
57*e670fd5cSchristos #include <ldap_schema.h>
58*e670fd5cSchristos 
59*e670fd5cSchristos #include "lber_pvt.h"
60*e670fd5cSchristos #include "ldap_pvt.h"
61*e670fd5cSchristos #include "ldap_pvt_thread.h"
62*e670fd5cSchristos #include "ldap_queue.h"
63*e670fd5cSchristos 
64*e670fd5cSchristos #include <event2/event.h>
65*e670fd5cSchristos 
66*e670fd5cSchristos #ifdef HAVE_CYRUS_SASL
67*e670fd5cSchristos #ifdef HAVE_SASL_SASL_H
68*e670fd5cSchristos #include <sasl/sasl.h>
69*e670fd5cSchristos #else
70*e670fd5cSchristos #include <sasl.h>
71*e670fd5cSchristos #endif
72*e670fd5cSchristos #endif /* HAVE_CYRUS_SASL */
73*e670fd5cSchristos 
74*e670fd5cSchristos LDAP_BEGIN_DECL
75*e670fd5cSchristos 
76*e670fd5cSchristos #ifdef SERVICE_NAME
77*e670fd5cSchristos #undef SERVICE_NAME
78*e670fd5cSchristos #endif
79*e670fd5cSchristos 
80*e670fd5cSchristos #define SERVICE_NAME OPENLDAP_PACKAGE "-lloadd"
81*e670fd5cSchristos 
82*e670fd5cSchristos #define LLOAD_SB_MAX_INCOMING_CLIENT ( ( 1 << 24 ) - 1 )
83*e670fd5cSchristos #define LLOAD_SB_MAX_INCOMING_UPSTREAM ( ( 1 << 24 ) - 1 )
84*e670fd5cSchristos 
85*e670fd5cSchristos #define LLOAD_CONN_MAX_PDUS_PER_CYCLE_DEFAULT 10
86*e670fd5cSchristos 
87*e670fd5cSchristos #define BER_BV_OPTIONAL( bv ) ( BER_BVISNULL( bv ) ? NULL : ( bv ) )
88*e670fd5cSchristos 
89*e670fd5cSchristos #include <epoch.h>
90*e670fd5cSchristos 
91*e670fd5cSchristos #define checked_lock( mutex ) \
92*e670fd5cSchristos     if ( ldap_pvt_thread_mutex_lock( mutex ) != 0 ) assert(0)
93*e670fd5cSchristos #define checked_unlock( mutex ) \
94*e670fd5cSchristos     if ( ldap_pvt_thread_mutex_unlock( mutex ) != 0 ) assert(0)
95*e670fd5cSchristos 
96*e670fd5cSchristos #ifdef LDAP_THREAD_DEBUG
97*e670fd5cSchristos #define assert_locked( mutex ) \
98*e670fd5cSchristos     if ( ldap_pvt_thread_mutex_trylock( mutex ) == 0 ) assert(0)
99*e670fd5cSchristos #else
100*e670fd5cSchristos #define assert_locked( mutex ) ( (void)0 )
101*e670fd5cSchristos #endif
102*e670fd5cSchristos 
103*e670fd5cSchristos typedef struct LloadBackend LloadBackend;
104*e670fd5cSchristos typedef struct LloadPendingConnection LloadPendingConnection;
105*e670fd5cSchristos typedef struct LloadConnection LloadConnection;
106*e670fd5cSchristos typedef struct LloadOperation LloadOperation;
107*e670fd5cSchristos typedef struct LloadChange LloadChange;
108*e670fd5cSchristos /* end of forward declarations */
109*e670fd5cSchristos 
110*e670fd5cSchristos typedef LDAP_CIRCLEQ_HEAD(BeSt, LloadBackend) lload_b_head;
111*e670fd5cSchristos typedef LDAP_CIRCLEQ_HEAD(ConnSt, LloadConnection) lload_c_head;
112*e670fd5cSchristos 
113*e670fd5cSchristos LDAP_SLAPD_V (lload_b_head) backend;
114*e670fd5cSchristos LDAP_SLAPD_V (lload_c_head) clients;
115*e670fd5cSchristos LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) backend_mutex;
116*e670fd5cSchristos LDAP_SLAPD_V (LloadBackend *) current_backend;
117*e670fd5cSchristos LDAP_SLAPD_V (struct slap_bindconf) bindconf;
118*e670fd5cSchristos LDAP_SLAPD_V (struct berval) lloadd_identity;
119*e670fd5cSchristos 
120*e670fd5cSchristos /* Used to coordinate server (un)pause, shutdown */
121*e670fd5cSchristos LDAP_SLAPD_V (ldap_pvt_thread_mutex_t) lload_wait_mutex;
122*e670fd5cSchristos LDAP_SLAPD_V (ldap_pvt_thread_cond_t) lload_pause_cond;
123*e670fd5cSchristos LDAP_SLAPD_V (ldap_pvt_thread_cond_t) lload_wait_cond;
124*e670fd5cSchristos 
125*e670fd5cSchristos typedef int lload_cf_aux_table_parse_x( struct berval *val,
126*e670fd5cSchristos         void *bc,
127*e670fd5cSchristos         slap_cf_aux_table *tab0,
128*e670fd5cSchristos         const char *tabmsg,
129*e670fd5cSchristos         int unparse );
130*e670fd5cSchristos 
131*e670fd5cSchristos typedef struct LloadListener LloadListener;
132*e670fd5cSchristos 
133*e670fd5cSchristos enum lc_type {
134*e670fd5cSchristos     LLOAD_CHANGE_UNDEFINED = 0,
135*e670fd5cSchristos     LLOAD_CHANGE_MODIFY,
136*e670fd5cSchristos     LLOAD_CHANGE_ADD,
137*e670fd5cSchristos     LLOAD_CHANGE_DEL,
138*e670fd5cSchristos };
139*e670fd5cSchristos 
140*e670fd5cSchristos enum lc_object {
141*e670fd5cSchristos     LLOAD_UNDEFINED = 0,
142*e670fd5cSchristos     LLOAD_DAEMON,
143*e670fd5cSchristos     /*
144*e670fd5cSchristos     LLOAD_BINDCONF,
145*e670fd5cSchristos     */
146*e670fd5cSchristos     LLOAD_BACKEND,
147*e670fd5cSchristos };
148*e670fd5cSchristos 
149*e670fd5cSchristos enum lcf_daemon {
150*e670fd5cSchristos     LLOAD_DAEMON_MOD_THREADS = 1 << 0,
151*e670fd5cSchristos     LLOAD_DAEMON_MOD_FEATURES = 1 << 1,
152*e670fd5cSchristos     LLOAD_DAEMON_MOD_TLS = 1 << 2,
153*e670fd5cSchristos     LLOAD_DAEMON_MOD_LISTENER_ADD = 1 << 3,
154*e670fd5cSchristos     LLOAD_DAEMON_MOD_LISTENER_REPLACE = 1 << 4,
155*e670fd5cSchristos     LLOAD_DAEMON_MOD_BINDCONF = 1 << 5,
156*e670fd5cSchristos };
157*e670fd5cSchristos 
158*e670fd5cSchristos enum lcf_backend {
159*e670fd5cSchristos     LLOAD_BACKEND_MOD_OTHER = 1 << 0,
160*e670fd5cSchristos     LLOAD_BACKEND_MOD_CONNS = 1 << 1,
161*e670fd5cSchristos };
162*e670fd5cSchristos 
163*e670fd5cSchristos struct LloadChange {
164*e670fd5cSchristos     enum lc_type type;
165*e670fd5cSchristos     enum lc_object object;
166*e670fd5cSchristos     union {
167*e670fd5cSchristos         int generic;
168*e670fd5cSchristos         enum lcf_daemon daemon;
169*e670fd5cSchristos         enum lcf_backend backend;
170*e670fd5cSchristos     } flags;
171*e670fd5cSchristos     void *target;
172*e670fd5cSchristos };
173*e670fd5cSchristos 
174*e670fd5cSchristos typedef enum {
175*e670fd5cSchristos #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
176*e670fd5cSchristos     LLOAD_FEATURE_VC = 1 << 0,
177*e670fd5cSchristos #endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
178*e670fd5cSchristos     LLOAD_FEATURE_PROXYAUTHZ = 1 << 1,
179*e670fd5cSchristos     LLOAD_FEATURE_PAUSE = 1 << 2,
180*e670fd5cSchristos } lload_features_t;
181*e670fd5cSchristos 
182*e670fd5cSchristos #define LLOAD_FEATURE_SUPPORTED_MASK ( \
183*e670fd5cSchristos     LLOAD_FEATURE_PROXYAUTHZ | \
184*e670fd5cSchristos     0 )
185*e670fd5cSchristos 
186*e670fd5cSchristos #ifdef BALANCER_MODULE
187*e670fd5cSchristos #define LLOAD_TLS_CTX ( lload_use_slap_tls_ctx ? slap_tls_ctx : lload_tls_ctx )
188*e670fd5cSchristos #else
189*e670fd5cSchristos #define LLOAD_TLS_CTX ( lload_tls_ctx )
190*e670fd5cSchristos #endif
191*e670fd5cSchristos 
192*e670fd5cSchristos enum lload_tls_type {
193*e670fd5cSchristos     LLOAD_CLEARTEXT = 0,
194*e670fd5cSchristos     LLOAD_LDAPS,
195*e670fd5cSchristos     LLOAD_STARTTLS_OPTIONAL,
196*e670fd5cSchristos     LLOAD_STARTTLS,
197*e670fd5cSchristos     LLOAD_TLS_ESTABLISHED,
198*e670fd5cSchristos };
199*e670fd5cSchristos 
200*e670fd5cSchristos struct LloadPendingConnection {
201*e670fd5cSchristos     LloadBackend *backend;
202*e670fd5cSchristos 
203*e670fd5cSchristos     struct event *event;
204*e670fd5cSchristos     ber_socket_t fd;
205*e670fd5cSchristos 
206*e670fd5cSchristos     LDAP_LIST_ENTRY(LloadPendingConnection) next;
207*e670fd5cSchristos };
208*e670fd5cSchristos 
209*e670fd5cSchristos typedef struct lload_counters_t {
210*e670fd5cSchristos     ldap_pvt_mp_t lc_ops_completed;
211*e670fd5cSchristos     ldap_pvt_mp_t lc_ops_received;
212*e670fd5cSchristos     ldap_pvt_mp_t lc_ops_forwarded;
213*e670fd5cSchristos     ldap_pvt_mp_t lc_ops_rejected;
214*e670fd5cSchristos     ldap_pvt_mp_t lc_ops_failed;
215*e670fd5cSchristos } lload_counters_t;
216*e670fd5cSchristos 
217*e670fd5cSchristos enum {
218*e670fd5cSchristos     LLOAD_STATS_OPS_BIND = 0,
219*e670fd5cSchristos     LLOAD_STATS_OPS_OTHER,
220*e670fd5cSchristos     LLOAD_STATS_OPS_LAST
221*e670fd5cSchristos };
222*e670fd5cSchristos 
223*e670fd5cSchristos typedef struct lload_global_stats_t {
224*e670fd5cSchristos     ldap_pvt_mp_t global_incoming;
225*e670fd5cSchristos     ldap_pvt_mp_t global_outgoing;
226*e670fd5cSchristos     lload_counters_t counters[LLOAD_STATS_OPS_LAST];
227*e670fd5cSchristos } lload_global_stats_t;
228*e670fd5cSchristos 
229*e670fd5cSchristos /* Can hold mutex when locking a linked connection */
230*e670fd5cSchristos struct LloadBackend {
231*e670fd5cSchristos     ldap_pvt_thread_mutex_t b_mutex;
232*e670fd5cSchristos 
233*e670fd5cSchristos     struct berval b_name, b_uri;
234*e670fd5cSchristos     int b_proto, b_port;
235*e670fd5cSchristos     enum lload_tls_type b_tls, b_tls_conf;
236*e670fd5cSchristos     char *b_host;
237*e670fd5cSchristos 
238*e670fd5cSchristos     int b_retry_timeout, b_failed;
239*e670fd5cSchristos     struct event *b_retry_event;
240*e670fd5cSchristos     struct timeval b_retry_tv;
241*e670fd5cSchristos 
242*e670fd5cSchristos     int b_numconns, b_numbindconns;
243*e670fd5cSchristos     int b_bindavail, b_active, b_opening;
244*e670fd5cSchristos     lload_c_head b_conns, b_bindconns, b_preparing;
245*e670fd5cSchristos     LDAP_LIST_HEAD(ConnectingSt, LloadPendingConnection) b_connecting;
246*e670fd5cSchristos     LloadConnection *b_last_conn, *b_last_bindconn;
247*e670fd5cSchristos 
248*e670fd5cSchristos     long b_max_pending, b_max_conn_pending;
249*e670fd5cSchristos     long b_n_ops_executing;
250*e670fd5cSchristos 
251*e670fd5cSchristos     lload_counters_t b_counters[LLOAD_STATS_OPS_LAST];
252*e670fd5cSchristos 
253*e670fd5cSchristos #ifdef BALANCER_MODULE
254*e670fd5cSchristos     monitor_subsys_t *b_monitor;
255*e670fd5cSchristos #endif /* BALANCER_MODULE */
256*e670fd5cSchristos 
257*e670fd5cSchristos     struct evdns_getaddrinfo_request *b_dns_req;
258*e670fd5cSchristos     void *b_cookie;
259*e670fd5cSchristos 
260*e670fd5cSchristos     LDAP_CIRCLEQ_ENTRY(LloadBackend) b_next;
261*e670fd5cSchristos };
262*e670fd5cSchristos 
263*e670fd5cSchristos typedef int (*LloadOperationHandler)( LloadConnection *client,
264*e670fd5cSchristos         LloadOperation *op,
265*e670fd5cSchristos         BerElement *ber );
266*e670fd5cSchristos typedef int (*RequestHandler)( LloadConnection *c, LloadOperation *op );
267*e670fd5cSchristos typedef struct lload_exop_handlers_t {
268*e670fd5cSchristos     struct berval oid;
269*e670fd5cSchristos     RequestHandler func;
270*e670fd5cSchristos } ExopHandler;
271*e670fd5cSchristos 
272*e670fd5cSchristos typedef int (*CONNECTION_PDU_CB)( LloadConnection *c );
273*e670fd5cSchristos typedef void (*CONNECTION_DESTROY_CB)( LloadConnection *c );
274*e670fd5cSchristos 
275*e670fd5cSchristos /* connection state (protected by c_mutex) */
276*e670fd5cSchristos enum sc_state {
277*e670fd5cSchristos     LLOAD_C_INVALID = 0, /* MUST BE ZERO (0) */
278*e670fd5cSchristos     LLOAD_C_READY,       /* ready */
279*e670fd5cSchristos     LLOAD_C_CLOSING,     /* closing */
280*e670fd5cSchristos     LLOAD_C_ACTIVE,      /* exclusive operation (tls setup, ...) in progress */
281*e670fd5cSchristos     LLOAD_C_BINDING,     /* binding */
282*e670fd5cSchristos     LLOAD_C_DYING,       /* part-processed dead waiting to be freed, someone
283*e670fd5cSchristos                           * might still be observing it */
284*e670fd5cSchristos };
285*e670fd5cSchristos enum sc_type {
286*e670fd5cSchristos     LLOAD_C_OPEN = 0,  /* regular connection */
287*e670fd5cSchristos     LLOAD_C_PREPARING, /* upstream connection not assigned yet */
288*e670fd5cSchristos     LLOAD_C_BIND, /* connection used to handle bind client requests if VC not enabled */
289*e670fd5cSchristos     LLOAD_C_PRIVILEGED, /* connection can override proxyauthz control */
290*e670fd5cSchristos };
291*e670fd5cSchristos enum sc_io_state {
292*e670fd5cSchristos     LLOAD_C_OPERATIONAL = 0,        /* all is good */
293*e670fd5cSchristos     LLOAD_C_READ_HANDOVER = 1 << 0, /* A task to process PDUs is scheduled or
294*e670fd5cSchristos                                      * running, do not re-enable c_read_event */
295*e670fd5cSchristos     LLOAD_C_READ_PAUSE = 1 << 1,    /* We want to pause reading until the client
296*e670fd5cSchristos                                      * has sufficiently caught up with what we
297*e670fd5cSchristos                                      * sent */
298*e670fd5cSchristos };
299*e670fd5cSchristos 
300*e670fd5cSchristos /*
301*e670fd5cSchristos  * represents a connection from an ldap client/to ldap server
302*e670fd5cSchristos  */
303*e670fd5cSchristos struct LloadConnection {
304*e670fd5cSchristos     enum sc_state c_state; /* connection state */
305*e670fd5cSchristos     enum sc_type c_type;
306*e670fd5cSchristos     enum sc_io_state c_io_state;
307*e670fd5cSchristos     ber_socket_t c_fd;
308*e670fd5cSchristos 
309*e670fd5cSchristos /*
310*e670fd5cSchristos  * LloadConnection reference counting:
311*e670fd5cSchristos  * - connection has a reference counter in c_refcnt
312*e670fd5cSchristos  * - also a liveness/validity token is added to c_refcnt during
313*e670fd5cSchristos  *   lload_connection_init, its existence is tracked in c_live and is usually the
314*e670fd5cSchristos  *   only one that prevents it from being destroyed
315*e670fd5cSchristos  * - anyone who needs to be able to relock the connection after unlocking it has
316*e670fd5cSchristos  *   to use acquire_ref(), they need to make sure a matching
317*e670fd5cSchristos  *   RELEASE_REF( c, c_refcnt, c->c_destroy ); is run eventually
318*e670fd5cSchristos  * - when a connection is considered dead, use CONNECTION_DESTROY on a locked
319*e670fd5cSchristos  *   connection, it will be made unreachable from normal places and either
320*e670fd5cSchristos  *   scheduled for reclamation when safe to do so or if anyone still holds a
321*e670fd5cSchristos  *   reference, it just gets unlocked and reclaimed after the last ref is
322*e670fd5cSchristos  *   released
323*e670fd5cSchristos  * - CONNECTION_LOCK_DESTROY is a shorthand for locking and CONNECTION_DESTROY
324*e670fd5cSchristos  */
325*e670fd5cSchristos     ldap_pvt_thread_mutex_t c_mutex; /* protect the connection */
326*e670fd5cSchristos     uintptr_t c_refcnt, c_live;
327*e670fd5cSchristos     CONNECTION_DESTROY_CB c_unlink;
328*e670fd5cSchristos     CONNECTION_DESTROY_CB c_destroy;
329*e670fd5cSchristos     CONNECTION_PDU_CB c_pdu_cb;
330*e670fd5cSchristos #define CONNECTION_ASSERT_LOCKED(c) assert_locked( &(c)->c_mutex )
331*e670fd5cSchristos #define CONNECTION_LOCK(c) \
332*e670fd5cSchristos     do { \
333*e670fd5cSchristos         checked_lock( &(c)->c_mutex ); \
334*e670fd5cSchristos     } while (0)
335*e670fd5cSchristos #define CONNECTION_UNLOCK(c) \
336*e670fd5cSchristos     do { \
337*e670fd5cSchristos         checked_unlock( &(c)->c_mutex ); \
338*e670fd5cSchristos     } while (0)
339*e670fd5cSchristos #define CONNECTION_UNLINK_(c) \
340*e670fd5cSchristos     do { \
341*e670fd5cSchristos         if ( __atomic_exchange_n( &(c)->c_live, 0, __ATOMIC_ACQ_REL ) ) { \
342*e670fd5cSchristos             RELEASE_REF( (c), c_refcnt, c->c_destroy ); \
343*e670fd5cSchristos             (c)->c_unlink( (c) ); \
344*e670fd5cSchristos         } \
345*e670fd5cSchristos     } while (0)
346*e670fd5cSchristos #define CONNECTION_DESTROY(c) \
347*e670fd5cSchristos     do { \
348*e670fd5cSchristos         CONNECTION_UNLINK_(c); \
349*e670fd5cSchristos         CONNECTION_UNLOCK(c); \
350*e670fd5cSchristos     } while (0)
351*e670fd5cSchristos #define CONNECTION_LOCK_DESTROY(c) \
352*e670fd5cSchristos     do { \
353*e670fd5cSchristos         CONNECTION_LOCK(c); \
354*e670fd5cSchristos         CONNECTION_DESTROY(c); \
355*e670fd5cSchristos     } while (0);
356*e670fd5cSchristos 
357*e670fd5cSchristos     Sockbuf *c_sb; /* ber connection stuff */
358*e670fd5cSchristos 
359*e670fd5cSchristos     /* set by connection_init */
360*e670fd5cSchristos     unsigned long c_connid;    /* unique id of this connection */
361*e670fd5cSchristos     struct berval c_peer_name; /* peer name (trans=addr:port) */
362*e670fd5cSchristos     time_t c_starttime;        /* when the connection was opened */
363*e670fd5cSchristos 
364*e670fd5cSchristos     time_t c_activitytime;  /* when the connection was last used */
365*e670fd5cSchristos     ber_int_t c_next_msgid; /* msgid of the next message */
366*e670fd5cSchristos 
367*e670fd5cSchristos     /* must not be used while holding either mutex */
368*e670fd5cSchristos     struct event *c_read_event, *c_write_event;
369*e670fd5cSchristos     struct timeval *c_read_timeout;
370*e670fd5cSchristos 
371*e670fd5cSchristos     /* can only be changed by binding thread */
372*e670fd5cSchristos     struct berval c_sasl_bind_mech; /* mech in progress */
373*e670fd5cSchristos     struct berval c_auth;           /* authcDN (possibly in progress) */
374*e670fd5cSchristos 
375*e670fd5cSchristos     unsigned long c_pin_id;
376*e670fd5cSchristos 
377*e670fd5cSchristos #ifdef HAVE_CYRUS_SASL
378*e670fd5cSchristos     sasl_conn_t *c_sasl_authctx;
379*e670fd5cSchristos     void *c_sasl_defaults;
380*e670fd5cSchristos #ifdef SASL_CHANNEL_BINDING /* 2.1.25+ */
381*e670fd5cSchristos     sasl_channel_binding_t *c_sasl_cbinding; /* Else cyrus-sasl would happily
382*e670fd5cSchristos                                               * leak it on sasl_dispose */
383*e670fd5cSchristos #endif /* SASL_CHANNEL_BINDING */
384*e670fd5cSchristos #endif /* HAVE_CYRUS_SASL */
385*e670fd5cSchristos 
386*e670fd5cSchristos #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
387*e670fd5cSchristos     struct berval c_vc_cookie;
388*e670fd5cSchristos #endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
389*e670fd5cSchristos 
390*e670fd5cSchristos     /* Can be held while acquiring c_mutex to inject things into c_ops or
391*e670fd5cSchristos      * destroy the connection */
392*e670fd5cSchristos     ldap_pvt_thread_mutex_t c_io_mutex; /* only one pdu written at a time */
393*e670fd5cSchristos 
394*e670fd5cSchristos     BerElement *c_currentber; /* ber we're attempting to read */
395*e670fd5cSchristos     BerElement *c_pendingber; /* ber we're attempting to write */
396*e670fd5cSchristos 
397*e670fd5cSchristos     TAvlnode *c_ops; /* Operations pending on the connection */
398*e670fd5cSchristos 
399*e670fd5cSchristos #ifdef HAVE_TLS
400*e670fd5cSchristos     enum lload_tls_type c_is_tls; /* true if this LDAP over raw TLS */
401*e670fd5cSchristos #endif
402*e670fd5cSchristos 
403*e670fd5cSchristos     long c_n_ops_executing;      /* num of ops currently executing */
404*e670fd5cSchristos     long c_n_ops_completed;      /* num of ops completed */
405*e670fd5cSchristos     lload_counters_t c_counters; /* per connection operation counters */
406*e670fd5cSchristos 
407*e670fd5cSchristos     LloadBackend *c_backend;
408*e670fd5cSchristos 
409*e670fd5cSchristos     /*
410*e670fd5cSchristos      * Protected by the CIRCLEQ mutex:
411*e670fd5cSchristos      * - Client: clients_mutex
412*e670fd5cSchristos      * - Upstream: b->b_mutex
413*e670fd5cSchristos      */
414*e670fd5cSchristos     LDAP_CIRCLEQ_ENTRY(LloadConnection) c_next;
415*e670fd5cSchristos };
416*e670fd5cSchristos 
417*e670fd5cSchristos enum op_state {
418*e670fd5cSchristos     LLOAD_OP_NOT_FREEING = 0,
419*e670fd5cSchristos     LLOAD_OP_DETACHING_CLIENT = 1 << 1,
420*e670fd5cSchristos     LLOAD_OP_DETACHING_UPSTREAM = 1 << 0,
421*e670fd5cSchristos };
422*e670fd5cSchristos 
423*e670fd5cSchristos #define LLOAD_OP_DETACHING_MASK \
424*e670fd5cSchristos     ( LLOAD_OP_DETACHING_UPSTREAM | LLOAD_OP_DETACHING_CLIENT )
425*e670fd5cSchristos 
426*e670fd5cSchristos /* operation result for monitoring purposes */
427*e670fd5cSchristos enum op_result {
428*e670fd5cSchristos     LLOAD_OP_REJECTED,  /* operation was not forwarded */
429*e670fd5cSchristos     LLOAD_OP_COMPLETED, /* operation sent and response received */
430*e670fd5cSchristos     LLOAD_OP_FAILED, /* operation was forwarded, but no response was received */
431*e670fd5cSchristos };
432*e670fd5cSchristos 
433*e670fd5cSchristos /*
434*e670fd5cSchristos  * Operation reference tracking:
435*e670fd5cSchristos  * - o_refcnt is set to 1, never incremented
436*e670fd5cSchristos  * - operation_unlink sets it to 0 and on transition from 1 clears both
437*e670fd5cSchristos  *   connection links (o_client, o_upstream)
438*e670fd5cSchristos  */
439*e670fd5cSchristos struct LloadOperation {
440*e670fd5cSchristos     uintptr_t o_refcnt;
441*e670fd5cSchristos 
442*e670fd5cSchristos     LloadConnection *o_client;
443*e670fd5cSchristos     unsigned long o_client_connid;
444*e670fd5cSchristos     ber_int_t o_client_msgid;
445*e670fd5cSchristos     ber_int_t o_saved_msgid;
446*e670fd5cSchristos 
447*e670fd5cSchristos     LloadConnection *o_upstream;
448*e670fd5cSchristos     unsigned long o_upstream_connid;
449*e670fd5cSchristos     ber_int_t o_upstream_msgid;
450*e670fd5cSchristos     time_t o_last_response;
451*e670fd5cSchristos 
452*e670fd5cSchristos     /* Protects o_client, o_upstream links */
453*e670fd5cSchristos     ldap_pvt_thread_mutex_t o_link_mutex;
454*e670fd5cSchristos 
455*e670fd5cSchristos     ber_tag_t o_tag;
456*e670fd5cSchristos     time_t o_start;
457*e670fd5cSchristos     unsigned long o_pin_id;
458*e670fd5cSchristos 
459*e670fd5cSchristos     enum op_result o_res;
460*e670fd5cSchristos     BerElement *o_ber;
461*e670fd5cSchristos     BerValue o_request, o_ctrls;
462*e670fd5cSchristos };
463*e670fd5cSchristos 
464*e670fd5cSchristos /*
465*e670fd5cSchristos  * listener; need to access it from monitor backend
466*e670fd5cSchristos  */
467*e670fd5cSchristos struct LloadListener {
468*e670fd5cSchristos     struct berval sl_url;
469*e670fd5cSchristos     struct berval sl_name;
470*e670fd5cSchristos     mode_t sl_perms;
471*e670fd5cSchristos #ifdef HAVE_TLS
472*e670fd5cSchristos     int sl_is_tls;
473*e670fd5cSchristos #endif
474*e670fd5cSchristos     int sl_is_proxied;
475*e670fd5cSchristos     struct event_base *base;
476*e670fd5cSchristos     struct evconnlistener *listener;
477*e670fd5cSchristos     int sl_mute; /* Listener is temporarily disabled due to emfile */
478*e670fd5cSchristos     int sl_busy; /* Listener is busy (accept thread activated) */
479*e670fd5cSchristos     ber_socket_t sl_sd;
480*e670fd5cSchristos     Sockaddr sl_sa;
481*e670fd5cSchristos #define sl_addr sl_sa.sa_in_addr
482*e670fd5cSchristos #define LDAP_TCP_BUFFER
483*e670fd5cSchristos #ifdef LDAP_TCP_BUFFER
484*e670fd5cSchristos     int sl_tcp_rmem; /* custom TCP read buffer size */
485*e670fd5cSchristos     int sl_tcp_wmem; /* custom TCP write buffer size */
486*e670fd5cSchristos #endif
487*e670fd5cSchristos };
488*e670fd5cSchristos 
489*e670fd5cSchristos typedef int (*CONNCB)( LloadConnection *c, void *arg );
490*e670fd5cSchristos 
491*e670fd5cSchristos struct lload_monitor_conn_arg {
492*e670fd5cSchristos     Operation *op;
493*e670fd5cSchristos     monitor_subsys_t *ms;
494*e670fd5cSchristos     Entry **ep;
495*e670fd5cSchristos };
496*e670fd5cSchristos 
497*e670fd5cSchristos /* config requires a bi_private with configuration data - dummy for now */
498*e670fd5cSchristos struct lload_conf_info {
499*e670fd5cSchristos     int dummy;
500*e670fd5cSchristos };
501*e670fd5cSchristos LDAP_END_DECL
502*e670fd5cSchristos 
503*e670fd5cSchristos #include "proto-lload.h"
504*e670fd5cSchristos #endif /* _LLOAD_H_ */
505