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