24 RCSID(
"$Id: 0e481afde1a5c9d991a0adc44bf02d5e9139e083 $")
28 #include <freeradius-devel/ldap/base.h>
29 #include <freeradius-devel/util/debug.h>
35 [LDAP_RES_BIND] =
"bind response",
36 [LDAP_RES_SEARCH_ENTRY] =
"search entry",
37 [LDAP_RES_SEARCH_REFERENCE] =
"search reference",
38 [LDAP_RES_SEARCH_RESULT] =
"search result",
39 [LDAP_RES_MODIFY] =
"modify response",
40 [LDAP_RES_ADD] =
"add response",
41 [LDAP_RES_DELETE] =
"delete response",
42 [LDAP_RES_MODDN] =
"modify dn response",
43 [LDAP_RES_COMPARE] =
"compare response",
44 [LDAP_RES_EXTENDED] =
"extended response",
45 [LDAP_RES_INTERMEDIATE] =
"intermediate response"
70 int ldap_errno, ldap_version, keepalive, probes, is_server;
74 ldap_errno = ldap_initialize(&handle,
config->server);
75 if (ldap_errno != LDAP_SUCCESS) {
76 ERROR(
"ldap_initialize failed: %s", ldap_err2string(ldap_errno));
81 DEBUG3(
"New connection %p libldap handle %p", c, handle);
91 #define do_ldap_option(_option, _name, _value) \
92 if (ldap_set_option(c->handle, _option, _value) != LDAP_OPT_SUCCESS) do { \
93 ldap_get_option(c->handle, LDAP_OPT_ERROR_NUMBER, &ldap_errno); \
94 ERROR("Failed setting connection option %s: %s", _name, \
95 (ldap_errno != LDAP_SUCCESS) ? ldap_err2string(ldap_errno) : "Unknown error"); \
100 #define maybe_ldap_option(_option, _name, _value) \
101 if (_value) do_ldap_option(_option, _name, _value)
113 do_ldap_option(LDAP_OPT_REFERRALS,
"chase_referrals", LDAP_OPT_OFF);
125 &(
struct timeval) { .tv_sec = -1, .tv_usec = 0 }));
129 ldap_version = LDAP_VERSION3;
130 do_ldap_option(LDAP_OPT_PROTOCOL_VERSION,
"ldap_version", &ldap_version);
133 do_ldap_option(LDAP_OPT_X_KEEPALIVE_IDLE,
"keepalive_idle", &keepalive);
135 probes =
config->keepalive_probes;
136 do_ldap_option(LDAP_OPT_X_KEEPALIVE_PROBES,
"keepalive_probes", &probes);
139 do_ldap_option(LDAP_OPT_X_KEEPALIVE_INTERVAL,
"keepalive_interval", &keepalive);
162 if (
config->tls_require_cert_str) {
166 if (
config->tls_min_version_str) {
177 do_ldap_option(LDAP_OPT_X_TLS_NEWCTX,
"new TLS context", &is_server);
180 if (
config->port == LDAPS_PORT) {
181 WARN(
"Told to Start TLS on LDAPS port this will probably fail, please correct the "
228 talloc_free_children(c);
239 DEBUG3(
"Closing connection %p libldap handle %p", c->
handle, c);
240 ldap_unbind_ext(c->
handle, our_serverctrls, our_clientctrls);
293 talloc_reparent(conn, NULL, ldap_conn);
294 ldap_conn->
conn = NULL;
366 if (ldap_set_option(c->
handle, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON) != LDAP_OPT_SUCCESS)
goto error;
393 .init = _ldap_connection_init,
397 .connection_timeout =
config->net_timeout,
398 .reconnection_delay =
config->reconnection_delay
402 PERROR(
"Failed allocating state handler for new LDAP connection");
423 &(
struct timeval) { .tv_sec = -1, .tv_usec = 0 }));
445 &(
struct timeval) { .tv_sec = -1, .tv_usec = 0 }));
460 if (ttrunk->
trunk->req_alloc == 0) {
461 DEBUG2(
"Removing idle LDAP trunk to \"%s\"", ttrunk->
uri);
506 ldap_abandon_ext(ldap_conn->
handle, query->
msgid, NULL, NULL);
545 char const *log_prefix,
void *
uctx)
552 #define POPULATE_LDAP_CONTROLS(_dest, _src) do { \
554 for (i = 0; (i < LDAP_MAX_CONTROLS) && (_src[i].control); i++) { \
555 _dest[i] = _src[i].control; \
574 LDAPURLDesc *referral_url = NULL;
587 switch (query->
type) {
602 (referral_url && referral_url->lud_dn) ?
603 referral_url->lud_dn : query->
dn,
604 (referral_url && referral_url->lud_scope) ?
605 referral_url->lud_scope : query->search.scope,
606 query->search.filter, query->search.attrs,
607 our_serverctrls, our_clientctrls);
618 ldap_conn, query->
dn, query->mods,
619 our_serverctrls, our_clientctrls);
630 ldap_conn, query->
dn,
631 our_serverctrls, our_clientctrls);
639 query->extended.reqoid, query->extended.reqdata);
644 ERROR(
"Invalid LDAP query for trunk connection");
694 int ret = 0, msgtype;
695 struct timeval poll = { 0, 10 };
696 LDAPMessage *result = NULL;
700 bool really_no_result =
false;
721 ret = ldap_result(ldap_conn->
handle, LDAP_RES_ANY, LDAP_MSG_ALL, &poll, &result);
724 if (really_no_result)
return;
725 really_no_result =
true;
731 ERROR(
"Bad LDAP connection");
740 really_no_result =
true;
744 find.
msgid = ldap_msgid(result);
748 WARN(
"Ignoring msgid %i - doesn't match any outstanding queries (it may have been cancelled)",
750 ldap_msgfree(result);
771 WARN(
"Received results for msgid %i which has already been handled - ignoring", find.
msgid);
772 ldap_msgfree(result);
776 msgtype = ldap_msgtype(result);
781 request = query->
treq->request;
789 switch (query->
type) {
791 query->
ret = (ldap_count_entries(ldap_conn->
handle, result) == 0) ?
804 "LDAP referral received but 'chase_referrals' is set to 'no'");
833 ldap_msgfree(result);
875 result, query->
treq->rctx);
885 if (!query->
treq)
continue;
919 char const *bind_dn,
char const *bind_password,
925 bind_dn ? bind_dn :
"(anonymous)");
928 if (found)
return found;
951 .connection_alloc = ldap_trunk_connection_alloc,
952 .connection_notify = ldap_trunk_connection_notify,
953 .request_mux = ldap_trunk_request_mux,
954 .request_demux = ldap_trunk_request_demux,
955 .request_cancel = ldap_request_cancel,
956 .request_cancel_mux = ldap_request_cancel_mux,
957 .request_fail = ldap_request_fail,
960 "rlm_ldap", found,
false);
1034 switch (bind->
type) {
1039 RDEBUG2(
"Starting bind auth operation as %s", bind_ctx->
bind_dn);
1042 memcpy(&cred.bv_val, &bind_ctx->
password,
sizeof(cred.bv_val));
1043 cred.bv_len = talloc_array_length(bind_ctx->
password) - 1;
1049 ret = ldap_sasl_bind(ldap_conn->
handle, bind_ctx->
bind_dn, LDAP_SASL_SIMPLE,
1050 &cred, NULL, NULL, &bind->
msgid);
1055 RDEBUG3(
"Bind auth sent as LDAP msgid %d", bind->
msgid);
1061 RERROR(
"Failed to send bind auth");
1068 case LDAP_BIND_SASL:
1072 RDEBUG2(
"%s SASL bind auth operation as %s", sasl_ctx->
rmech ?
"Continuing" :
"Starting",
1078 case LDAP_SASL_BIND_IN_PROGRESS:
1083 RDEBUG3(
"SASL bind auth sent as LDAP msgid %d", bind->
msgid);
1094 RERROR(
"Failed to send SASL bind auth");
1127 LDAPMessage *result = NULL;
1129 bool really_no_result =
false;
1142 if (really_no_result)
return;
1143 really_no_result =
true;
1147 if (!result)
return;
1149 really_no_result =
true;
1150 find.
msgid = ldap_msgid(result);
1154 WARN(
"Ignoring bind result msgid %i - doesn't match any outstanding binds", find.
msgid);
1155 ldap_msgfree(result);
1194 struct berval *srv_cred;
1200 sasl_ctx->
result = result;
1203 ret = ldap_parse_sasl_bind_result(ldap_conn->
handle, sasl_ctx->
result, &srv_cred, 0);
1204 if (ret != LDAP_SUCCESS) {
1205 RERROR(
"SASL decode failed (bind failed): %s", ldap_err2string(ret));
1210 RDEBUG3(
"SASL response : %pV",
1212 ber_bvfree(srv_cred);
1223 ldap_msgfree(result);
1247 if (bind->
type == LDAP_BIND_SASL) {
1256 ldap_abandon_ext(ldap_conn->
handle, bind->
msgid, NULL, NULL);
1278 talloc_steal(NULL, bind);
1309 .connection_alloc = ldap_trunk_connection_alloc,
1310 .connection_notify = ldap_trunk_connection_notify,
1311 .request_mux = ldap_trunk_bind_auth_mux,
1312 .request_demux = ldap_trunk_bind_auth_demux,
1313 .request_cancel_mux = ldap_bind_auth_cancel_mux,
1314 .request_fail = ldap_trunk_bind_auth_fail,
1317 "rlm_ldap bind auth", ttrunk,
false);
1319 if (!ttrunk->
trunk) {
1320 ERROR(
"Unable to create LDAP connection");
#define USES_APPLE_DEPRECATED_API
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
@ CONNECTION_STATE_FAILED
Connection has failed.
@ CONNECTION_STATE_CLOSED
Connection has been closed.
@ CONNECTION_STATE_CONNECTING
Waiting for connection to establish.
@ CONNECTION_FAILED
Connection is being reconnected because it failed.
Holds a complete set of functions for a connection.
fr_dcursor_eval_t void const * uctx
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
static fr_time_delta_t timeout
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_talloc_free_item(fr_dlist_head_t *list_head, void *ptr)
Free the item specified.
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
#define fr_event_timer_in(...)
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
fr_ldap_control_t serverctrls[LDAP_MAX_CONTROLS]
Server controls specific to this query.
LDAPURLDesc * referral_url
URL for the referral.
fr_ldap_thread_t * t
Thread this connection is associated with.
fr_ldap_rcode_t ret
Return code of bind operation.
char const * admin_password
Password used in administrative bind.
fr_ldap_config_t * config
Module instance config.
void fr_ldap_control_clear(fr_ldap_connection_t *conn)
Clear and free any controls associated with a connection.
fr_event_timer_t const * ev
Event for timing out the query.
bool chase_referrals
If the LDAP server returns a referral to another server or point in the tree, follow it,...
char ** referral_urls
Referral results to follow.
int msgid
libldap msgid for this bind.
char * server
Initial server to bind to.
uint16_t referral_depth
How many referrals we have followed.
LDAP * handle
libldap handle.
int msgid
The unique identifier for this query.
char const * dn
Base DN for searches, DN for modifications.
char const * bind_dn
DN connection is bound as.
void fr_ldap_control_merge(LDAPControl *serverctrls_out[], LDAPControl *clientctrls_out[], size_t serverctrls_len, size_t clientctrls_len, fr_ldap_connection_t *conn, LDAPControl *serverctrls_in[], LDAPControl *clientctrls_in[])
Merge connection and call specific client and server controls.
fr_rb_node_t node
Entry in the tree of connections.
fr_dlist_head_t referrals
List of parsed referrals.
char const * admin_identity
Identity we bind as when we need to query the LDAP directory.
fr_ldap_result_code_t ret
Result code.
fr_ldap_result_parser_t parser
Custom results parser.
fr_rb_tree_t * trunks
Tree of LDAP trunks used by this thread.
int fr_ldap_referral_follow(fr_ldap_thread_t *thread, request_t *request, fr_ldap_query_t *query)
Follow an LDAP referral.
trunk_conf_t * trunk_conf
Module trunk config.
fr_rb_tree_t * queries
Outstanding queries on this connection.
fr_ldap_state_t
LDAP connection handle states.
@ FR_LDAP_STATE_ERROR
Connection is in an error state.
char const * identity
of the user.
trunk_request_t * treq
Trunk request this query is associated with.
fr_event_timer_t const * ev
Event to close the thread when it has been idle.
fr_dlist_head_t refs
Replied to queries still referencing this connection.
int fd
File descriptor for this connection.
int fr_ldap_trunk_directory_alloc_async(TALLOC_CTX *ctx, fr_ldap_thread_trunk_t *ttrunk)
Async extract useful information from the rootDSE of the LDAP server.
char const * uri
Server URI for this connection.
LDAPMessage * result
Previous result.
fr_time_delta_t net_timeout
How long we wait in blocking network calls.
fr_ldap_config_t const * config
rlm_ldap connection configuration.
request_t * request
this bind relates to.
fr_ldap_control_t clientctrls[LDAP_MAX_CONTROLS]
Client controls specific to this query.
trunk_request_t * treq
Trunk request this bind is associated with.
static int8_t fr_ldap_query_cmp(void const *one, void const *two)
Compare two ldap query structures on msgid.
fr_ldap_config_t config
Config used for this connection.
fr_ldap_state_t fr_ldap_state_next(fr_ldap_connection_t *c)
Move between LDAP connection states.
@ LDAP_REQUEST_MODIFY
A modification to an LDAP entity.
@ LDAP_REQUEST_SEARCH
A lookup in an LDAP directory.
@ LDAP_REQUEST_DELETE
A deletion of an LDAP entity.
@ LDAP_REQUEST_EXTENDED
An extended LDAP operation.
fr_ldap_connection_t * ldap_conn
LDAP connection this query is running on.
@ LDAP_RESULT_EXCESS_REFERRALS
The referral chain took too many hops.
@ LDAP_RESULT_REFERRAL_FAIL
Initial results indicated a referral was needed but the referral could not be followed.
@ LDAP_RESULT_ERROR
A general error occurred.
@ LDAP_RESULT_SUCCESS
Successfully got LDAP results.
@ LDAP_RESULT_PENDING
Result not yet returned.
@ LDAP_RESULT_NO_RESULT
No results returned.
@ LDAP_RESULT_BAD_DN
The requested DN does not exist.
@ LDAP_RESULT_MISSING_REFERRAL
A referral was indicated but no URL was provided.
#define LDAP_MAX_CONTROLS
Maximum number of client/server controls.
trunk_conf_t * bind_trunk_conf
Trunk config for bind auth trunk.
uint16_t referral_depth
How many referrals to chase.
LDAPMessage * result
Head of LDAP results list.
fr_event_list_t * el
Thread event list for callbacks / timeouts.
char const * rmech
Mech we're continuing with.
fr_ldap_thread_trunk_t * bind_trunk
LDAP trunk used for bind auths.
char const * bind_dn
of the user, may be NULL to bind anonymously.
trunk_t * trunk
Connection trunk.
connection_t * conn
Connection state handle.
fr_ldap_referral_t * referral
Referral actually being followed.
fr_rb_tree_t * binds
Tree of outstanding bind auths.
fr_ldap_bind_type_t type
type of bind.
int fr_ldap_referral_next(fr_ldap_thread_t *thread, request_t *request, fr_ldap_query_t *query)
Follow an alternative LDAP referral.
char const * password
of the user, may be NULL if no password is specified.
fr_time_delta_t idle_timeout
How long to wait before closing unused connections.
fr_ldap_request_type_t type
What type of query this is.
fr_ldap_rcode_t
Codes returned by fr_ldap internal functions.
@ LDAP_PROC_CONTINUE
Operation is in progress.
@ LDAP_PROC_SUCCESS
Operation was successful.
@ LDAP_PROC_REFERRAL
LDAP server returned referral URLs.
@ LDAP_PROC_TIMEOUT
Operation timed out.
@ LDAP_PROC_ERROR
Unrecoverable library/server error.
@ LDAP_PROC_BAD_CONN
Transitory error, caller should retry the operation with a new connection.
@ LDAP_PROC_NOT_PERMITTED
Operation was not permitted, either current user was locked out in the case of binds,...
@ LDAP_PROC_REJECT
Bind failed, user was rejected.
@ LDAP_PROC_BAD_DN
Specified an invalid object in a bind or search DN.
@ LDAP_PROC_NO_RESULT
Got no results.
Holds arguments for async bind auth requests.
Holds arguments for the async bind operation.
Connection configuration.
Tracks the state of a libldap connection handle.
Holds arguments for the async SASL bind operation.
Thread specific structure to manage LDAP trunk connections.
Thread LDAP trunk structure.
connection_t * fr_ldap_connection_state_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, fr_ldap_config_t const *config, char const *log_prefix)
Alloc a self re-establishing connection to an LDAP server.
static void _ldap_connection_close(fr_event_list_t *el, void *h, UNUSED void *uctx)
Free the handle, closing the connection to ldap.
fr_ldap_thread_trunk_t * fr_thread_ldap_trunk_get(fr_ldap_thread_t *thread, char const *uri, char const *bind_dn, char const *bind_password, request_t *request, fr_ldap_config_t const *config)
Find a thread specific LDAP connection for a specific URI / bind DN.
fr_ldap_connection_t * fr_ldap_connection_alloc(TALLOC_CTX *ctx)
Allocate our ldap connection handle layer.
#define do_ldap_option(_option, _name, _value)
static int _ldap_connection_free(fr_ldap_connection_t *c)
Close and delete a connection.
static void _ldap_trunk_idle_timeout(fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Callback for closing idle LDAP trunk.
static void ldap_request_fail(request_t *request, void *preq, UNUSED void *rctx, UNUSED trunk_request_state_t state, UNUSED void *uctx)
Callback to tidy up when a trunk request fails.
static USES_APPLE_DEPRECATED_API char const * ldap_msg_types[UINT8_MAX]
static void ldap_trunk_bind_auth_fail(request_t *request, void *preq, UNUSED void *rctx, UNUSED trunk_request_state_t state, UNUSED void *uctx)
Callback to tidy up when a bind auth trunk request fails.
fr_ldap_thread_trunk_t * fr_thread_ldap_bind_trunk_get(fr_ldap_thread_t *thread)
Find the thread specific trunk to use for LDAP bind auths.
trunk_state_t fr_thread_ldap_trunk_state(fr_ldap_thread_t *thread, char const *uri, char const *bind_dn)
Lookup the state of a thread specific LDAP connection trunk for a specific URI / bind DN.
static void _ldap_connection_close_watch(connection_t *conn, UNUSED connection_state_t prev, UNUSED connection_state_t state, void *uctx)
Watcher for LDAP connections being closed.
#define maybe_ldap_option(_option, _name, _value)
static int _thread_ldap_trunk_free(fr_ldap_thread_trunk_t *ttrunk)
CC_NO_UBSAN(function)
(Re-)Initialises the libldap side of the connection handle
#define POPULATE_LDAP_CONTROLS(_dest, _src)
int fr_ldap_connection_timeout_set(fr_ldap_connection_t const *c, fr_time_delta_t timeout)
int fr_ldap_connection_configure(fr_ldap_connection_t *c, fr_ldap_config_t const *config)
Allocate and configure a new connection.
int fr_ldap_connection_timeout_reset(fr_ldap_connection_t const *c)
static void ldap_request_cancel(UNUSED connection_t *conn, void *preq, UNUSED trunk_cancel_reason_t reason, UNUSED void *uctx)
Callback when an LDAP trunk request is cancelled.
fr_ldap_rcode_t fr_ldap_error_check(LDAPControl ***ctrls, fr_ldap_connection_t const *conn, LDAPMessage *msg, char const *dn)
Perform basic parsing of multiple types of messages, checking for error conditions.
fr_ldap_rcode_t fr_ldap_search_async(int *msgid, request_t *request, fr_ldap_connection_t *pconn, char const *dn, int scope, char const *filter, char const *const *attrs, LDAPControl **serverctrls, LDAPControl **clientctrls)
Search for something in the LDAP directory.
fr_ldap_rcode_t fr_ldap_result(LDAPMessage **result, LDAPControl ***ctrls, fr_ldap_connection_t const *conn, int msgid, int all, char const *dn, fr_time_delta_t timeout)
Parse response from LDAP server dealing with any errors.
fr_ldap_rcode_t fr_ldap_modify_async(int *msgid, request_t *request, fr_ldap_connection_t *pconn, char const *dn, LDAPMod *mods[], LDAPControl **serverctrls, LDAPControl **clientctrls)
Modify something in the LDAP directory.
fr_ldap_rcode_t fr_ldap_extended_async(int *msgid, request_t *request, fr_ldap_connection_t *pconn, char const *reqoid, struct berval *reqdata)
Initiate an LDAP extended operation.
fr_ldap_rcode_t fr_ldap_delete_async(int *msgid, request_t *request, fr_ldap_connection_t *pconn, char const *dn, LDAPControl **serverctrls, LDAPControl **clientctrls)
Modify something in the LDAP directory.
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
int fr_event_timer_delete(fr_event_timer_t const **ev_p)
Delete a timer event from the event list.
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Stores all information relating to an event list.
static const conf_parser_t config[]
uint32_t fr_rb_num_elements(fr_rb_tree_t *tree)
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
static bool fr_rb_node_inline_in_tree(fr_rb_node_t const *node)
Check to see if an item is in a tree by examining its inline fr_rb_node_t.
void * fr_rb_remove(fr_rb_tree_t *tree, void const *data)
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
int fr_ldap_sasl_bind_auth_send(fr_ldap_sasl_ctx_t *sasl_ctx, int *msgid, fr_ldap_connection_t *ldap_conn)
Send a SASL LDAP auth bind.
void connection_signal_reconnect(connection_t *conn, connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
connection_watch_entry_t * connection_add_watch_pre(connection_t *conn, connection_state_t state, connection_watch_t watch, bool oneshot, void const *uctx)
Add a callback to be executed before a state function has been called.
connection_t * connection_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, connection_funcs_t const *funcs, connection_conf_t const *conf, char const *log_prefix, void const *uctx)
Allocate a new connection.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time_delta_wrap(_time)
#define fr_time_delta_ispos(_a)
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
A time delta, a difference in time measured in nanoseconds.
int trunk_connection_pop_cancellation(trunk_request_t **treq_out, trunk_connection_t *tconn)
Pop a cancellation request off a connection's cancellation queue.
void trunk_request_signal_fail(trunk_request_t *treq)
Signal that a trunk request failed.
void trunk_request_signal_cancel_complete(trunk_request_t *treq)
Signal that a remote server acked our cancellation.
int trunk_connection_pop_request(trunk_request_t **treq_out, trunk_connection_t *tconn)
Pop a request off a connection's pending queue.
void trunk_request_signal_sent(trunk_request_t *treq)
Signal that the request was written to a connection successfully.
void trunk_request_signal_complete(trunk_request_t *treq)
Signal that a trunk request is complete.
void trunk_connection_signal_reconnect(trunk_connection_t *tconn, connection_reason_t reason)
Signal a trunk connection is no longer viable.
trunk_t * trunk_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, trunk_io_funcs_t const *funcs, trunk_conf_t const *conf, char const *log_prefix, void const *uctx, bool delay_start)
Allocate a new collection of connections.
Associates request queues with a connection.
#define TRUNK_NOTIFY_FUNC(_name, _type)
Helper macro for building generic trunk notify callback.
trunk_cancel_reason_t
Reasons for a request being cancelled.
trunk_request_state_t
Used for sanity checks and to simplify freeing.
I/O functions to pass to trunk_alloc.
static fr_event_list_t * el
#define fr_box_strvalue_len(_val, _len)