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