24 RCSID(
"$Id: 2bb33c83017b72c2a2f7823a566bc93a277013e3 $")
26 #include <freeradius-devel/io/application.h>
27 #include <freeradius-devel/io/listen.h>
28 #include <freeradius-devel/io/pair.h>
29 #include <freeradius-devel/missing.h>
30 #include <freeradius-devel/server/connection.h>
31 #include <freeradius-devel/util/debug.h>
32 #include <freeradius-devel/util/heap.h>
33 #include <freeradius-devel/util/udp.h>
35 #include <sys/socket.h>
94 char const *module_name;
100 size_t send_buff_actual;
221 if ((h->
active == 0) && (h->
id > 255)) {
236 if (shutdown(h->
fd, SHUT_RDWR) < 0) {
237 DEBUG3(
"%s - Failed shutting down connection %s: %s",
242 DEBUG3(
"%s - Failed closing connection %s: %s",
295 h->
name =
fr_asprintf(h,
"proto tcp local %pV port %u remote %pV port %u",
306 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt,
sizeof(
int)) < 0) {
315 socklen_t socklen =
sizeof(int);
319 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt,
sizeof(
int)) < 0) {
320 WARN(
"%s - Failed setting 'SO_SNDBUF', write performance may be sub-optimal: %s",
325 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, &socklen) < 0) {
326 WARN(
"%s - Failed getting 'SO_SNDBUF', write performance may be sub-optimal: %s",
346 WARN(
"%s - Max coalesced outbound data will be %zu bytes", h->
module_name,
364 WARN(
"%s - Modifying 'SO_SNDBUF' value is not supported on this system, "
365 "write performance may be sub-optimal", h->
module_name);
366 WARN(
"%s - Max coalesced outbound data will be %zu bytes", h->
module_name, h->
inst->send_buff_actual);
415 DEBUG4(
"Freeing rlm_tacacs_tcp handle %p", handle);
423 char const *log_prefix,
void *uctx)
523 if (ret != 0)
return ret;
559 REDEBUG(
"Session ID %08x does not match expected number %08x",
569 if (packet_len < 0) {
570 RPEDEBUG(
"Failed decoding TACACS+ reply packet");
575 RDEBUG(
"Received %s ID %d length %ld reply packet on connection %s",
579 *response_code = code;
608 if (!hdr) hdr = request->request_ctx;
623 inst->secret,
inst->secretlen, request->reply->code, &request->request_pairs);
624 if (packet_len < 0) {
625 RPERROR(
"Failed encoding packet");
662 INFO(
"%s - No replies during 'zombie_period', marking connection %s as dead", h->
module_name, h->
name);
676 ERROR(
"Failed inserting revive timeout for connection");
737 ERROR(
"Failed inserting zombie timeout for connection");
775 REDEBUG(
"Reached maximum_retransmit_duration (%pVs > %pVs), failing request",
780 REDEBUG(
"Reached maximum_retransmit_count (%u > %u), failing request",
804 for (i = 0, queued = 0; (i <
inst->max_send_coalesce); i++) {
838 request = treq->request;
873 RDEBUG(
"Sending %s ID %d length %ld over connection %s",
876 if (
encode(h, request, u) < 0) {
918 if (queued == 0)
return;
934 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
941 WARN(
"%s - Failed sending data over connection %s: %s",
951 ERROR(
"%s - Failed sending data over connection %s: %s",
965 for (i = 0; i < queued; i++) {
975 request = treq->request;
987 RERROR(
"Failed inserting retransmit timeout for connection");
1009 if (u->
packet < written) {
1010 size_t skip = written - u->
packet;
1048 bool do_read =
true;
1054 size_t available,
used, packet_len;
1071 if (available < h->
inst->max_packet_size) {
1094 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
return;
1096 ERROR(
"%s - Failed reading response from socket: %s",
1112 if (do_read)
continue;
1127 ERROR(
"%s - Packet is larger than max_packet_size",
1136 if (
used < packet_len) {
1137 if (do_read)
continue;
1149 WARN(
"%s - Ignoring reply with ID %i that arrived too late",
1157 request = treq->request;
1167 slen =
decode(request->reply_ctx, &reply, &code, h, request, u, h->
recv.
read, packet_len);
1180 treq->request->reply->code = code;
1323 case FR_SIGNAL_CANCEL:
1360 if (!r->
treq)
return 0;
1393 u->
code = request->packet->code;
1394 u->
priority = request->async->priority;
1395 u->
recv_time = request->async->recv_time;
1412 RDEBUG(
"All destinations are down - cannot send packet");
1444 inst->trunk_conf = &
inst->parent->trunk_conf;
1446 inst->trunk_conf->req_pool_headers = 2;
1449 thread->
el = mctx->
el;
1452 inst->trunk_conf,
inst->parent->name, thread,
false);
1453 if (!thread->
trunk)
return -1;
1458 if (
inst->secret && !*
inst->secret) {
1460 inst->secret = NULL;
1463 if (
inst->secret)
inst->secretlen = talloc_array_length(
inst->secret) - 1;
1475 ERROR(
"IO module cannot be instantiated directly");
1484 if (
inst->max_send_coalesce == 0)
inst->max_send_coalesce = 1;
1489 if (
inst->dst_ipaddr.af == AF_UNSPEC) {
1498 if (
inst->src_ipaddr.af == AF_UNSPEC) {
1499 memset(&
inst->src_ipaddr, 0,
sizeof(
inst->src_ipaddr));
1501 inst->src_ipaddr.af =
inst->dst_ipaddr.af;
1503 if (
inst->src_ipaddr.af == AF_INET) {
1504 inst->src_ipaddr.prefix = 32;
1506 inst->src_ipaddr.prefix = 128;
1510 else if (
inst->src_ipaddr.af !=
inst->dst_ipaddr.af) {
1511 cf_log_err(
conf,
"The 'ipaddr' and 'src_ipaddr' configuration items must "
1512 "be both of the same address family");
1516 if (!
inst->dst_port) {
1528 if (
inst->recv_buff_is_set) {
1533 if (
inst->send_buff_is_set) {
1546 .name =
"tacacs_tcp",
1550 .thread_inst_type =
"udp_thread_t",
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
#define CMP_PREFER_SMALLER(_a, _b)
Evaluates to +1 for a > b, and -1 for a < b.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#define CONF_PARSER_TERMINATOR
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
@ FR_CONNECTION_STATE_CONNECTING
Waiting for connection to establish.
@ FR_CONNECTION_STATE_FAILED
Connection has failed.
@ FR_CONNECTION_EXPIRED
Connection is being reconnected because it's at the end of its life.
@ FR_CONNECTION_FAILED
Connection is being reconnected because it failed.
Holds a complete set of functions for a connection.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
CONF_SECTION *_CONST conf
Module's instance configuration.
dl_module_inst_t const *_CONST parent
Parent module's instance (if any).
#define fr_event_fd_insert(...)
void(* fr_event_fd_cb_t)(fr_event_list_t *el, int fd, int flags, void *uctx)
Called when an IO event occurs on a file descriptor.
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
#define fr_event_timer_at(...)
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
#define RPEDEBUG(fmt,...)
#define RHEXDUMP3(_data, _len, _fmt,...)
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.
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_STRUCT
like TLV, but without T or L, and fixed-width children
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
void * rctx
Resume ctx that a module previously set.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
void * thread
Thread instance data.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
static uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
Read an unsigned 32bit integer from wire format (big endian)
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
int8_t fr_pair_cmp_by_parent_num(void const *a, void const *b)
Order attributes by their parent(s), attribute number, and tag.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
char const * fr_tacacs_packet_names[FR_TACACS_CODE_MAX]
ssize_t fr_tacacs_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *vendor, uint8_t const *buffer, size_t buffer_len, const uint8_t *original, char const *const secret, size_t secret_len, int *code)
Decode a TACACS+ packet.
ssize_t fr_tacacs_encode(fr_dbuff_t *dbuff, uint8_t const *original_packet, char const *secret, size_t secret_len, unsigned int code, fr_pair_list_t *vps)
Encode VPS into a raw TACACS packet.
uint32_t fr_rand(void)
Return a 32-bit random number.
#define RETURN_MODULE_RCODE(_rcode)
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
fr_time_delta_t revive_interval
fr_retry_config_t retry[FR_RADIUS_CODE_MAX]
fr_time_delta_t response_window
fr_time_delta_t zombie_period
uint32_t recv_buff
How big the kernel's receive buffer should be.
uint16_t dst_port
Port of the home server.
fr_ipaddr_t dst_ipaddr
IP of the home server.
uint32_t send_buff
How big the kernel's send buffer should be.
bool send_buff_is_set
Whether we were provided with a send_buf.
fr_ipaddr_t src_ipaddr
IP we open our socket on.
rlm_radius_t * parent
rlm_radius instance.
uint32_t max_packet_size
Maximum packet size.
uint16_t max_send_coalesce
Maximum number of packets to coalesce into one mmsg call.
bool recv_buff_is_set
Whether we were provided with a recv_buf.
module_t common
Common fields to all loadable modules.
Public structure describing an I/O path for an outgoing socket.
static void request_conn_release(fr_connection_t *conn, void *preq_to_reset, UNUSED void *uctx)
Clear out anything associated with the handle from the request.
fr_time_t last_reply
When we last received a reply.
static int8_t request_prioritise(void const *one, void const *two)
uint16_t src_port
Source port specific to this connection.
rlm_rcode_t rcode
from the transport
uint8_t * write
where we write data to
static fr_dict_attr_t const * attr_packet_type
fr_time_t first_sent
first time we sent a packet since going idle
fr_event_list_t * el
Event list.
bool send_buff_is_set
Whether we were provided with a send_buf.
static int _udp_result_free(udp_result_t *r)
Free a udp_result_t.
size_t secretlen
length of secret
static fr_dict_attr_t const * attr_session_id
fr_trunk_t * trunk
trunk handler
char const * interface
Interface to bind to.
uint8_t * data
actual data
fr_time_t last_idle
last time we had nothing to do
size_t packet_len
Length of the packet.
static fr_dict_attr_t const * attr_packet_hdr
static void request_mux(fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_connection_t *conn, UNUSED void *uctx)
static void udp_request_reset(udp_handle_t *h, udp_request_t *u)
Clear out any connection specific resources from a udp request.
fr_trunk_conf_t * trunk_conf
trunk configuration
rlm_tacacs_tcp_t const * inst
our instance
fr_dict_autoload_t rlm_tacacs_tcp_dict[]
fr_trunk_connection_t * tconn
trunk connection
uint8_t id
Last ID assigned to this packet.
fr_ipaddr_t src_ipaddr
Source IP address.
static void conn_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
Connection errored.
static ssize_t decode(TALLOC_CTX *ctx, fr_pair_list_t *reply, uint8_t *response_code, udp_handle_t *h, request_t *request, udp_request_t *u, uint8_t *data, size_t data_len)
Decode response packet data, extracting relevant information and validating the packet.
static void mod_signal(module_ctx_t const *mctx, UNUSED request_t *request, fr_signal_t action)
static void conn_close(UNUSED fr_event_list_t *el, void *handle, UNUSED void *uctx)
Shutdown/close a file descriptor.
char const * secret
Shared secret.
uint32_t session_id
for TACACS+ "security".
uint16_t dst_port
Port of the home server.
fr_time_t recv_time
copied from request->async->recv_time
static fr_dict_t const * dict_tacacs
fr_event_timer_t const * ev
timer for retransmissions
uint32_t send_buff
How big the kernel's send buffer should be.
static fr_connection_state_t conn_init(void **h_out, fr_connection_t *conn, void *uctx)
Initialise a new outbound connection.
uint8_t * end
end of the buffer
fr_time_t last_sent
last time we sent a packet.
static void request_free(UNUSED request_t *request, void *preq_to_free, UNUSED void *uctx)
Explicitly free resources associated with the protocol request.
rlm_radius_udp_t const * inst
our instance
static void zombie_timeout(fr_event_list_t *el, fr_time_t now, void *uctx)
Mark a connection dead after "zombie_interval".
uint32_t recv_buff
How big the kernel's receive buffer should be.
size_t send_buff_actual
What we believe the maximum SO_SNDBUF size to be.
struct udp_request_s udp_request_t
rlm_tacacs_io_t rlm_tacacs_tcp
fr_trunk_request_t ** coalesced
Outbound coalesced requests.
tcp_buffer_t recv
receive buffer
fr_ipaddr_t src_ipaddr
IP we open our socket on.
uint8_t * packet
Packet we write to the network.
static void revive_timeout(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Revive a connection after "revive_interval".
char const * name
From IP PORT to IP PORT.
uint32_t max_packet_size
Our max packet size. may be different from the parent.
static void request_cancel(fr_connection_t *conn, void *preq_to_reset, fr_trunk_cancel_reason_t reason, UNUSED void *uctx)
Remove the request from any tracking structures.
udp_coalesced_t * coalesced
Outbound coalesced requests.
static unlang_action_t mod_enqueue(rlm_rcode_t *p_result, void **rctx_out, UNUSED void *instance, void *thread, request_t *request)
bool recv_buff_is_set
Whether we were provided with a recv_buf.
static void thread_conn_notify(fr_trunk_connection_t *tconn, fr_connection_t *conn, fr_event_list_t *el, fr_trunk_connection_event_t notify_on, UNUSED void *uctx)
uint32_t max_packet_size
Maximum packet size.
fr_time_t mrs_time
Most recent sent time which had a reply.
rlm_radius_udp_t const * inst
Our module instance.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Instantiate thread data for the submodule.
static fr_connection_t * thread_conn_alloc(fr_trunk_connection_t *tconn, fr_event_list_t *el, fr_connection_conf_t const *conf, char const *log_prefix, void *uctx)
static void request_demux(UNUSED fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_connection_t *conn, UNUSED void *uctx)
static unlang_action_t mod_resume(rlm_rcode_t *p_result, module_ctx_t const *mctx, UNUSED request_t *request)
Resume execution of the request, returning the rcode set during trunk execution.
fr_event_timer_t const * zombie_ev
Zombie timeout.
rlm_tacacs_tcp_t const * inst
Our module instance.
static void request_retry(fr_event_list_t *el, fr_time_t now, void *uctx)
Handle retries.
uint8_t * read
where we read data from
tcp_buffer_t send
send buffer
static void request_fail(request_t *request, NDEBUG_UNUSED void *preq, void *rctx, NDEBUG_UNUSED fr_trunk_request_state_t state, UNUSED void *uctx)
Write out a canned failure.
static int _udp_handle_free(udp_handle_t *h)
Free a connection handle, closing associated resources.
rlm_tacacs_t * parent
rlm_tacacs instance.
char const * module_name
the module that opened the connection
fr_dict_attr_autoload_t rlm_tacacs_tcp_dict_attr[]
static const conf_parser_t module_config[]
static int encode(udp_handle_t *h, request_t *request, udp_request_t *u)
fr_trunk_request_t * treq
bool outstanding
are we waiting for a reply?
fr_retry_t retry
retransmission timers
fr_ipaddr_t dst_ipaddr
IP of the home server.
static int mod_instantiate(module_inst_ctx_t const *mctx)
static bool check_for_zombie(fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_time_t now, fr_time_t last_sent)
See if the connection is zombied.
uint32_t priority
copied from request->async->priority
static void request_complete(request_t *request, NDEBUG_UNUSED void *preq, void *rctx, UNUSED void *uctx)
Response has already been written to the rctx at this point.
fr_trunk_request_t * tracking[UINT8_MAX]
all sequential!
uint16_t max_send_coalesce
Maximum number of packets to coalesce into one mmsg call.
Static configuration for the module.
Track the handle, which is tightly correlated with the FD.
Connect request_t to local tracking structure.
int fr_connection_signal_on_fd(fr_connection_t *conn, int fd)
Setup the connection to change states to connected or failed based on I/O events.
fr_connection_t * fr_connection_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, fr_connection_funcs_t const *funcs, fr_connection_conf_t const *conf, char const *log_prefix, void const *uctx)
Allocate a new connection.
void fr_connection_signal_reconnect(fr_connection_t *conn, fr_connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
#define fr_time()
Allow us to arbitrarily manipulate time.
Stores an attribute, a value and various bits of other data.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define FR_TACACS_PACKET_CODE_VALID(_code)
#define FR_MAX_PACKET_SIZE
static int talloc_const_free(void const *ptr)
Free const'd memory.
#define fr_time_gteq(_a, _b)
static int64_t fr_time_unwrap(fr_time_t time)
#define fr_time_wrap(_time)
#define fr_time_lteq(_a, _b)
#define fr_time_delta_ispos(_a)
#define fr_time_eq(_a, _b)
#define fr_time_add(_a, _b)
Add a time/time delta together.
#define fr_time_gt(_a, _b)
#define fr_time_sub(_a, _b)
Subtract one time from another.
#define fr_time_lt(_a, _b)
void fr_trunk_request_free(fr_trunk_request_t **treq_to_free)
If the trunk request is freed then update the target requests.
void fr_trunk_request_signal_cancel(fr_trunk_request_t *treq)
Cancel a trunk request.
fr_trunk_request_t * fr_trunk_request_alloc(fr_trunk_t *trunk, request_t *request)
(Pre-)Allocate a new trunk request
void fr_trunk_request_signal_sent(fr_trunk_request_t *treq)
Signal that the request was written to a connection successfully.
fr_trunk_enqueue_t fr_trunk_request_enqueue(fr_trunk_request_t **treq_out, fr_trunk_t *trunk, request_t *request, void *preq, void *rctx)
Enqueue a request that needs data written to the trunk.
uint64_t fr_trunk_connection_requests_requeue(fr_trunk_connection_t *tconn, int states, uint64_t max, bool fail_bound)
Move requests off of a connection and requeue elsewhere.
void fr_trunk_request_signal_complete(fr_trunk_request_t *treq)
Signal that a trunk request is complete.
fr_trunk_enqueue_t fr_trunk_request_requeue(fr_trunk_request_t *treq)
Re-enqueue a request on the same connection.
void fr_trunk_request_signal_partial(fr_trunk_request_t *treq)
Signal a partial write.
fr_trunk_t * fr_trunk_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, fr_trunk_io_funcs_t const *funcs, fr_trunk_conf_t const *conf, char const *log_prefix, void const *uctx, bool delay_start)
Allocate a new collection of connections.
int fr_trunk_connection_pop_request(fr_trunk_request_t **treq_out, fr_trunk_connection_t *tconn)
Pop a request off a connection's pending queue.
void fr_trunk_connection_signal_inactive(fr_trunk_connection_t *tconn)
Signal a trunk connection cannot accept more requests.
void fr_trunk_connection_callback_readable(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
Standard I/O read function.
void fr_trunk_request_signal_fail(fr_trunk_request_t *treq)
Signal that a trunk request failed.
void fr_trunk_connection_signal_reconnect(fr_trunk_connection_t *tconn, fr_connection_reason_t reason)
Signal a trunk connection is no longer viable.
void fr_trunk_connection_callback_writable(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
Standard I/O write function.
Associates request queues with a connection.
Main trunk management handle.
fr_trunk_cancel_reason_t
Reasons for a request being cancelled.
@ FR_TRUNK_CANCEL_REASON_REQUEUE
A previously sent request is being requeued.
fr_trunk_request_state_t
Used for sanity checks and to simplify freeing.
@ FR_TRUNK_REQUEST_STATE_SENT
Was written to a socket. Waiting for a response.
@ FR_TRUNK_REQUEST_STATE_PENDING
In the queue of a connection and is pending writing.
@ FR_TRUNK_REQUEST_STATE_PARTIAL
Some of the request was written to the socket, more of it should be written later.
@ FR_TRUNK_REQUEST_STATE_INIT
Initial state.
fr_trunk_connection_alloc_t connection_alloc
Allocate a new fr_connection_t.
#define FR_TRUNK_REQUEST_STATE_ALL
All request states.
fr_trunk_connection_event_t
What type of I/O events the trunk connection is currently interested in receiving.
@ FR_TRUNK_CONN_EVENT_NONE
Don't notify the trunk on connection state changes.
@ FR_TRUNK_CONN_EVENT_WRITE
Trunk should be notified if a connection is writable.
@ FR_TRUNK_CONN_EVENT_READ
Trunk should be notified if a connection is readable.
@ FR_TRUNK_CONN_EVENT_BOTH
Trunk should be notified if a connection is readable or writable.
@ FR_TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
Common configuration parameters for a trunk.
I/O functions to pass to fr_trunk_alloc.
static fr_event_list_t * el
void fr_pair_list_sort(fr_pair_list_t *list, fr_cmp_t cmp)
Sort a doubly linked list of fr_pair_ts using merge sort.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
fr_retry_state_t fr_retry_next(fr_retry_t *r, fr_time_t now)
Initialize a retransmission counter.
void fr_retry_init(fr_retry_t *r, fr_time_t now, fr_retry_config_t const *config)
Initialize a retransmission counter.
fr_time_t start
when we started the retransmission
fr_time_delta_t rt
retransmit interval
uint32_t mrc
Maximum retransmission count.
fr_retry_config_t const * config
master configuration
@ FR_RETRY_MRC
reached maximum retransmission count
@ FR_RETRY_MRD
reached maximum retransmission duration
uint32_t count
number of sent packets
fr_time_delta_t mrd
Maximum retransmission duration.
fr_time_t next
when the next timer should be set
#define fr_box_ipaddr(_val)
#define fr_box_time_delta(_val)