25 RCSID(
"$Id: aabc07be690e2376cc46eceb382d3ab6d60c1b99 $")
27 #include <freeradius-devel/io/application.h>
28 #include <freeradius-devel/io/listen.h>
29 #include <freeradius-devel/io/pair.h>
30 #include <freeradius-devel/missing.h>
31 #include <freeradius-devel/server/connection.h>
32 #include <freeradius-devel/util/debug.h>
33 #include <freeradius-devel/util/heap.h>
34 #include <freeradius-devel/util/udp.h>
36 #include <sys/socket.h>
45 #define check(_handle, _len_p) fr_radius_ok((_handle)->buffer, (size_t *)(_len_p), \
46 (_handle)->thread->inst->parent->max_attributes, false, NULL)
281 fr_log(log, log_type,
file,
line,
"request %s, allocated %s:%u", request->name,
282 request->alloc_file, request->alloc_line);
350 request->async = talloc_zero(request,
fr_async_t);
352 request->name = talloc_strdup(request, h->
module_name);
361 while ((map = map_list_next(&
inst->parent->status_check_map, map))) {
411 u->
code =
inst->parent->status_check;
412 request->packet->code = u->
code;
474 DEBUG(
"%s - Reached maximum_retransmit_duration (%pVs > %pVs), failing status checks",
480 DEBUG(
"%s - Reached maximum_retransmit_count (%u > %u), failing status checks",
528 if (slen == 0)
return;
532 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
543 ERROR(
"%s - Failed reading response from socket: %s",
555 ERROR(
"%s - Packet too short, expected at least %zu bytes got %zd bytes",
561 ERROR(
"%s - Received response with incorrect or expired ID. Expected %u, got %u",
566 if (!
check(h, &slen))
return;
568 if (
decode(h, &reply, &code,
592 DEBUG(
"%s - Received %u / %u replies for status check, on connection - %s",
594 DEBUG(
"%s - Next status check packet will be in %pVs",
640 DEBUG(
"%s - Sending %s ID %d over connection %s",
653 ERROR(
"%s - Failed sending %s ID %d length %ld over connection %s: %s",
668 DEBUG(
"%s - %s request. Expecting response within %pVs",
689 if (shutdown(h->
fd, SHUT_RDWR) < 0) {
690 DEBUG3(
"%s - Failed shutting down connection %s: %s",
695 DEBUG3(
"%s - Failed closing connection %s: %s",
739 h->
mmsgvec[i].msg_hdr.msg_iovlen = 1;
762 h->
name =
fr_asprintf(h,
"proto udp local %pV port %u remote %pV port %u",
773 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt,
sizeof(
int)) < 0) {
782 socklen_t socklen =
sizeof(int);
786 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt,
sizeof(
int)) < 0) {
787 WARN(
"%s - Failed setting 'SO_SNDBUF', write performance may be sub-optimal: %s",
792 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, &socklen) < 0) {
793 WARN(
"%s - Failed getting 'SO_SNDBUF', write performance may be sub-optimal: %s",
805 WARN(
"%s - Max coalesced outbound data will be %zu bytes", h->
module_name,
823 WARN(
"%s - Modifying 'SO_SNDBUF' value is not supported on this system, "
824 "write performance may be sub-optimal", h->
module_name);
825 WARN(
"%s - Max coalesced outbound data will be %zu bytes", h->
module_name, h->
inst->send_buff_actual);
887 DEBUG4(
"Freeing rlm_radius_udp handle %p", handle);
927 char const *log_prefix,
void *
uctx)
1007 switch (notify_on) {
1060 switch (notify_on) {
1110 if (ret != 0)
return ret;
1116 if (ret != 0)
return ret;
1155 .request_code = u->
code,
1156 .request_authenticator = request_authenticator,
1157 .tmp_ctx = talloc(ctx,
uint8_t),
1158 .end =
data + data_len,
1160 .require_message_authenticator = ((*(
parent->received_message_authenticator) &
parent->require_message_authenticator) |
1173 RDEBUG(
"Received %s ID %d length %ld reply packet on connection %s",
1186 !*(
parent->received_message_authenticator) &&
1189 RINFO(
"Packet contained a valid Message-Authenticator. Setting \"require_message_authenticator = yes\"");
1190 *(
parent->received_message_authenticator) =
true;
1194 *response_code = code;
1231 .common = &
inst->common_ctx,
1238 .add_proxy_state = !
inst->parent->originate,
1261 RPERROR(
"Failed encoding packet");
1268 if (packet_len < 0) {
1273 need = have - packet_len;
1276 RERROR(
"Failed encoding packet. Have %zu bytes of buffer, need %zu bytes",
1279 RERROR(
"Failed encoding packet. Have %zu bytes of buffer, need %zu bytes. "
1280 "Increase 'max_packet_size'", have, need);
1288 fr_assert((
size_t) packet_len <= u->packet_len);
1314 talloc_array_length(
inst->secret) - 1) < 0) {
1315 RERROR(
"Failed signing packet");
1343 INFO(
"%s - No replies during 'zombie_period', marking connection %s as dead", h->
module_name, h->
name);
1367 ERROR(
"Failed inserting revive timeout for connection");
1442 ERROR(
"Failed inserting zombie timeout for connection");
1505 REDEBUG(
"Reached maximum_retransmit_duration (%pVs > %pVs), failing request",
1510 REDEBUG(
"Reached maximum_retransmit_count (%u > %u), failing request",
1535 h = talloc_get_type_abort(treq->tconn->conn->h,
udp_handle_t);
1553 REDEBUG(
"Reached maximum_retransmit_duration (%pVs > %pVs), failing request",
1558 REDEBUG(
"Reached maximum_retransmit_count (%u > %u), failing request",
1566 WARN(
"%s - No response to status check, marking connection as dead - %s", h->
module_name, h->
name);
1584 size_t total_len = 0;
1590 for (i = 0, queued = 0; (i <
inst->max_send_coalesce) && (total_len < h->send_buff_actual); i++) {
1605 request = treq->request;
1641 RDEBUG(
"Sending %s ID %d length %ld over connection %s",
1662 RDEBUG(
"Retransmitting %s ID %d length %ld over connection %s",
1697 if (queued == 0)
return;
1715 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1722 WARN(
"%s - Failed sending data over connection %s: %s",
1737 ERROR(
"%s - Failed sending data over connection %s: %s",
1748 ERROR(
"%s - Failed sending data over connection %s: %s",
1759 for (i = 0; i < sent; i++) {
1772 request = treq->request;
1779 action =
inst->parent->originate ?
"Originated" :
"Proxied";
1784 action =
"Retransmitted";
1788 RDEBUG(
"%s status check. Expecting response within %pVs", action,
1792 RERROR(
"Failed inserting retransmit timeout for connection");
1797 }
else if (!
inst->parent->synchronous) {
1798 RDEBUG(
"%s request. Expecting response within %pVs", action,
1802 RERROR(
"Failed inserting retransmit timeout for connection");
1811 RERROR(
"Failed inserting timeout for connection");
1820 RDEBUG(
"%s request. Relying on NAS to perform more retransmissions", action);
1842 size_t total_len = 0;
1844 for (i = 0, queued = 0; (i <
inst->max_send_coalesce) && (total_len < h->send_buff_actual); i++) {
1859 request = treq->request;
1871 RDEBUG(
"Sending %s ID %d length %ld over connection %s",
1891 if (queued == 0)
return;
1906 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1913 WARN(
"%s - Failed sending data over connection %s: %s",
1928 ERROR(
"%s - Failed sending data over connection %s: %s",
1939 ERROR(
"%s - Failed sending data over connection %s: %s",
1946 for (i = 0; i < sent; i++) {
1967 bool error_601 =
false;
1982 memcpy(&error, attr + 2, 4);
1983 error = ntohl(error);
1984 if (error == 601) error_601 =
true;
1992 memcpy(&response_length, attr + 2, 4);
2009 if (attr[1] != 7)
continue;
2019 if ((attr[3] != 0) ||
2033 if (attr[6] != u->
code) {
2046 if (error_601 && response_length && (response_length > h->
buflen)) {
2047 if (response_length < 4096) response_length = 4096;
2048 if (response_length > 65535) response_length = 65535;
2050 DEBUG(
"%s - Increasing buffer size to %u for connection %s", h->
module_name, response_length, h->
name);
2056 h->
buflen = response_length;
2059 memcpy(h->
buffer, attr, end - attr);
2113 DEBUG(
"Received %d / %u replies for status check, on connection - %s",
2126 DEBUG(
"Received enough replies to status check, marking connection as active - %s", h->
name);
2171 if (slen == 0)
return;
2174 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
return;
2176 ERROR(
"%s - Failed reading response from socket: %s",
2183 ERROR(
"%s - Packet too short, expected at least %zu bytes got %zd bytes",
2194 WARN(
"%s - Ignoring reply with ID %i that arrived too late",
2200 request = treq->request;
2209 if (!
check(h, &slen)) {
2210 RWARN(
"Ignoring malformed packet");
2214 reason =
decode(request->reply_ctx, &reply, &code, h, request, u, rr->vector, h->
buffer, (
size_t)slen);
2298 treq->request->reply->code = code;
2463 case FR_SIGNAL_CANCEL:
2507 if (!r->
treq)
return 0;
2541 RWDEBUG(
"Status-Server is reserved for internal use, and cannot be sent manually.");
2557 u->
code = request->packet->code;
2559 u->
priority = request->async->priority;
2560 u->
recv_time = request->async->recv_time;
2586 REDEBUG(
"Unable to queue packet - connections at maximum capacity");
2594 REDEBUG(
"All destinations are down - cannot send packet");
2598 REDEBUG(
"Unable to queue packet");
2621 .connection_notify = thread_conn_notify,
2623 .request_mux = request_mux,
2634 .connection_notify = thread_conn_notify_replicate,
2636 .request_mux = request_mux_replicate,
2643 thread->
el = mctx->
el;
2646 &
inst->trunk_conf,
inst->parent->name, thread,
false);
2647 if (!thread->
trunk)
return -1;
2659 ERROR(
"IO module cannot be instantiated directly");
2669 if (
inst->max_send_coalesce == 0)
inst->max_send_coalesce = 1;
2674 if (
inst->dst_ipaddr.af == AF_UNSPEC) {
2680 .secret =
inst->secret,
2681 .secret_length = talloc_array_length(
inst->secret) - 1,
2682 .proxy_state =
inst->parent->proxy_state,
2689 if (
inst->src_ipaddr.af == AF_UNSPEC) {
2690 memset(&
inst->src_ipaddr, 0,
sizeof(
inst->src_ipaddr));
2692 inst->src_ipaddr.af =
inst->dst_ipaddr.af;
2694 if (
inst->src_ipaddr.af == AF_INET) {
2695 inst->src_ipaddr.prefix = 32;
2697 inst->src_ipaddr.prefix = 128;
2701 else if (
inst->src_ipaddr.af !=
inst->dst_ipaddr.af) {
2702 cf_log_err(
conf,
"The 'ipaddr' and 'src_ipaddr' configuration items must "
2703 "be both of the same address family");
2707 if (!
inst->dst_port) {
2720 if (
inst->replicate) {
2724 inst->recv_buff_is_set =
true;
2732 inst->recv_buff = 0;
2735 if (
inst->recv_buff_is_set) {
2743 if (
inst->send_buff_is_set) {
2748 memcpy(&
inst->trunk_conf, &
inst->parent->trunk_conf,
sizeof(
inst->trunk_conf));
2749 inst->trunk_conf.req_pool_headers = 4;
2759 .name =
"radius_udp",
2763 .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.
static int const char char buffer[256]
#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_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
#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,...)
@ CONNECTION_STATE_FAILED
Connection has failed.
@ CONNECTION_STATE_CONNECTED
File descriptor is open (ready for writing).
@ CONNECTION_STATE_INIT
Init state, sets up connection.
@ 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.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
fr_dcursor_eval_t void const * uctx
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error.
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
@ FR_RADIUS_CODE_MAX
Maximum possible protocol code.
@ FR_RADIUS_CODE_DISCONNECT_ACK
RFC3575/RFC5176 - Disconnect-Ack (positive)
@ FR_RADIUS_CODE_STATUS_SERVER
RFC2865/RFC5997 - Status Server (request)
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
@ FR_RADIUS_CODE_ACCOUNTING_RESPONSE
RFC2866 - Accounting-Response.
@ FR_RADIUS_CODE_COA_NAK
RFC3575/RFC5176 - CoA-Nak (not willing to perform)
@ FR_RADIUS_CODE_COA_ACK
RFC3575/RFC5176 - CoA-Ack (positive)
@ FR_RADIUS_CODE_DISCONNECT_NAK
RFC3575/RFC5176 - Disconnect-Nak (not willing to perform)
@ FR_RADIUS_CODE_PROTOCOL_ERROR
RFC7930 - Protocol-Error (generic NAK)
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
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.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#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.
Minimal data structure to use the new code.
static bool fr_pair_encode_is_error(ssize_t slen)
Determine if the return code for an encoding function is a fatal error.
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 HEXDUMP3(_data, _len, _fmt,...)
#define RHEXDUMP3(_data, _len, _fmt,...)
int map_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *out, request_t *request, map_t const *map, UNUSED void *uctx)
Convert a map to a fr_pair_t.
int map_to_request(request_t *request, map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert map_t to fr_pair_t (s) and add them to a request_t.
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.
void fr_log(fr_log_t const *log, fr_log_type_t type, char const *file, int line, char const *fmt,...)
Send a server log message to its destination.
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_OCTETS
Raw octets.
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen, int flags)
Emulates the real sendmmsg in userland.
void * thread
Thread specific instance data.
void * rctx
Resume ctx that a module previously set.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
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 uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
#define RADIUS_HEADER_LENGTH
#define RADIUS_AUTH_VECTOR_LENGTH
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.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
static fr_internal_encode_ctx_t encode_ctx
ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t *packet, size_t packet_len, fr_radius_decode_ctx_t *decode_ctx)
int fr_radius_sign(uint8_t *packet, uint8_t const *vector, uint8_t const *secret, size_t secret_len)
Sign a previously encoded packet.
ssize_t fr_radius_encode(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_radius_encode_ctx_t *packet_ctx)
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
@ FR_RADIUS_REQUIRE_MA_YES
Require Message-Authenticator.
@ FR_RADIUS_REQUIRE_MA_AUTO
Only require Message-Authenticator if we've previously received a packet from this client with Messag...
#define RADIUS_AUTH_VECTOR_OFFSET
#define RADIUS_MAX_PACKET_SIZE
fr_radius_ctx_t const * common
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
uint32_t fr_rand(void)
Return a 32-bit random number.
Smaller fast random number generator.
#define RETURN_MODULE_NOOP
#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.
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
#define request_local_alloc_external(_ctx, _args)
Allocate a new external request outside of the request pool.
fr_time_delta_t revive_interval
module_t common
Common fields to all loadable modules.
fr_retry_config_t retry[FR_RADIUS_CODE_MAX]
uint32_t status_check
code of status-check type
fr_time_delta_t response_window
fr_time_delta_t zombie_period
bool synchronous
Retransmit when receiving a duplicate request.
Public structure describing an I/O path for an outgoing socket.
uint32_t recv_buff
How big the kernel's receive buffer should be.
static int8_t request_prioritise(void const *one, void const *two)
static bool check_for_zombie(fr_event_list_t *el, trunk_connection_t *tconn, fr_time_t now, fr_time_t last_sent)
See if the connection is zombied.
static fr_dict_attr_t const * attr_packet_type
static fr_dict_attr_t const * attr_user_password
static int _udp_result_free(udp_result_t *r)
Free a udp_result_t.
trunk_conf_t trunk_conf
trunk configuration
static void request_complete(request_t *request, void *preq, void *rctx, UNUSED void *uctx)
Response has already been written to the rctx at this point.
static void status_check_alloc(udp_handle_t *h)
static int _udp_request_free(udp_request_t *u)
Free a udp_request_t.
static int encode(rlm_radius_udp_t const *inst, request_t *request, udp_request_t *u, uint8_t id)
uint16_t dst_port
Port of the home server.
static fr_dict_attr_t const * attr_eap_message
fr_ipaddr_t dst_ipaddr
IP of the home server.
static rlm_rcode_t radius_code_to_rcode[FR_RADIUS_CODE_MAX]
Turn a reply code into a module rcode;.
static void udp_request_reset(udp_request_t *u)
Clear out any connection specific resources from a udp request.
static void conn_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
Connection errored.
uint32_t send_buff
How big the kernel's send buffer should be.
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.
static void conn_writable_status_check(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
static void request_conn_release(connection_t *conn, void *preq_to_reset, UNUSED void *uctx)
Clear out anything associated with the handle from the request.
static void request_fail(request_t *request, void *preq, void *rctx, NDEBUG_UNUSED trunk_request_state_t state, UNUSED void *uctx)
Write out a canned failure.
#define check(_handle, _len_p)
static void request_timeout(fr_event_list_t *el, fr_time_t now, void *uctx)
Handle timeouts when a request is being sent synchronously.
static void conn_error_status_check(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
Connection errored.
bool send_buff_is_set
Whether we were provided with a send_buf.
static fr_dict_t const * dict_radius
static void request_free(UNUSED request_t *request, void *preq_to_free, UNUSED void *uctx)
Explicitly free resources associated with the protocol request.
static void conn_status_check_timeout(fr_event_list_t *el, fr_time_t now, void *uctx)
Status check timer when opening the connection for the first time.
static void zombie_timeout(fr_event_list_t *el, fr_time_t now, void *uctx)
Mark a connection dead after "zombie_interval".
struct udp_request_s udp_request_t
fr_ipaddr_t src_ipaddr
IP we open our socket on.
static fr_dict_attr_t const * attr_extended_attribute_1
static void request_cancel(UNUSED connection_t *conn, void *preq_to_reset, trunk_cancel_reason_t reason, UNUSED void *uctx)
Remove the request from any tracking structures.
fr_dict_autoload_t rlm_radius_udp_dict[]
static void conn_status_check_again(fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Send the next status check packet.
static fr_dict_attr_t const * attr_error_cause
static void status_check_next(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Handle retries for a status check.
struct iovec out
Describes buffer to send.
static void revive_timeout(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Revive a connection after "revive_interval".
static void conn_discard(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Read and discard data.
fr_radius_ctx_t common_ctx
rlm_radius_t * parent
rlm_radius instance.
static fr_dict_attr_t const * attr_proxy_state
static void conn_readable_status_check(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
Read the incoming status-check response.
static fr_dict_attr_t const * attr_nas_identifier
char const * interface
Interface to bind to.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Instantiate thread data for the submodule.
static void status_check_reply(trunk_request_t *treq, fr_time_t now)
Deal with replies replies to status checks and possible negotiation.
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.
static decode_fail_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 const request_authenticator[static RADIUS_AUTH_VECTOR_LENGTH], uint8_t *data, size_t data_len)
Decode response packet data, extracting relevant information and validating the packet.
static void udp_tracking_entry_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line, radius_track_entry_t *te)
Log additional information about a tracking entry.
static void protocol_error_reply(udp_request_t *u, udp_result_t *r, udp_handle_t *h)
Deal with Protocol-Error replies, and possible negotiation.
static void request_conn_release_replicate(UNUSED connection_t *conn, void *preq_to_reset, UNUSED void *uctx)
Clear out anything associated with the handle from the request.
static void status_check_retry(UNUSED fr_event_list_t *el, fr_time_t now, void *uctx)
static void request_retry(fr_event_list_t *el, fr_time_t now, void *uctx)
Handle retries when a request is being sent asynchronously.
trunk_request_t * treq
Used for signalling.
static unlang_action_t mod_enqueue(rlm_rcode_t *p_result, void **rctx_out, void *instance, void *thread, request_t *request)
static int _udp_handle_free(udp_handle_t *h)
Free a connection handle, closing associated resources.
uint32_t max_packet_size
Maximum packet size.
CC_NO_UBSAN(function)
Initialise a new outbound connection.
char const * secret
Shared secret.
static const conf_parser_t module_config[]
fr_dict_attr_autoload_t rlm_radius_udp_dict_attr[]
bool replicate
Copied from parent->replicate.
static fr_dict_attr_t const * attr_original_packet_code
static void status_check_reset(udp_handle_t *h, udp_request_t *u)
Reset a status_check packet, ready to reuse.
static connection_state_t conn_failed(void *handle, connection_state_t state, UNUSED void *uctx)
Connection failed.
rlm_radius_io_t rlm_radius_udp
uint16_t max_send_coalesce
Maximum number of packets to coalesce into one mmsg call.
static fr_dict_attr_t const * attr_event_timestamp
static fr_dict_attr_t const * attr_response_length
static int mod_instantiate(module_inst_ctx_t const *mctx)
bool recv_buff_is_set
Whether we were provided with a recv_buf.
static fr_dict_attr_t const * attr_message_authenticator
Static configuration for the module.
udp_request_t * status_u
for sending status check packets
fr_time_t last_reply
When we last received a reply.
uint16_t src_port
Source port specific to this connection.
rlm_rcode_t rcode
from the transport
fr_time_t first_sent
first time we sent a packet since going idle
uint8_t * buffer
Receive buffer.
fr_event_list_t * el
Event list.
static void request_demux(UNUSED fr_event_list_t *el, trunk_connection_t *tconn, connection_t *conn, UNUSED void *uctx)
fr_time_t last_idle
last time we had nothing to do
size_t packet_len
Length of the packet.
uint8_t id
Last ID assigned to this packet.
fr_ipaddr_t src_ipaddr
Source IP address.
bool require_message_authenticator
saved from the original packet.
fr_pair_list_t extra
VPs for debugging, like Proxy-State.
fr_time_t recv_time
copied from request->async->recv_time
fr_event_timer_t const * ev
timer for retransmissions
fr_time_t last_sent
last time we sent a packet.
udp_result_t * status_r
for faking out status checks as real packets
rlm_radius_udp_t const * inst
our instance
size_t send_buff_actual
What we believe the maximum SO_SNDBUF size to be.
struct mmsghdr * mmsgvec
Vector of inbound/outbound packets.
radius_track_t * tt
RADIUS ID tracking structure.
bool synchronous
cached from inst->parent->synchronous
trunk_t * trunk
trunk handler
radius_track_entry_t * rr
ID tracking, resend count, etc.
request_t * status_request
uint8_t * packet
Packet we write to the network.
char const * name
From IP PORT to IP PORT.
uint32_t max_packet_size
Our max packet size. may be different from the parent.
udp_coalesced_t * coalesced
Outbound coalesced requests.
bool status_check
is this packet a status check?
fr_time_t mrs_time
Most recent sent time which had a reply.
uint32_t num_replies
number of reply packets, sent is in retry.count
rlm_radius_udp_t const * inst
Our module instance.
fr_event_timer_t const * zombie_ev
Zombie timeout.
bool status_checking
whether we're doing status checks
size_t buflen
Receive buffer length.
static connection_state_t conn_init(void **h_out, connection_t *conn, void *uctx)
Initialise a new outbound connection.
char const * module_name
the module that opened the connection
fr_retry_t retry
retransmission timers
uint32_t priority
copied from request->async->priority
uint8_t last_id
Used when replicating to ensure IDs are distributed evenly.
Track the handle, which is tightly correlated with the FD.
Connect request_t to local tracking structure.
void connection_signal_reconnect(connection_t *conn, connection_reason_t reason)
Asynchronously signal the connection should be reconnected.
int connection_signal_on_fd(connection_t *conn, int fd)
Setup the connection to change states to connected or failed based on I/O events.
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.
void connection_signal_connected(connection_t *conn)
Asynchronously signal that the connection is open.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
module_instance_t const * parent
Parent module's instance (if any).
#define pair_append_request(_attr, _da)
Allocate and append a fr_pair_t to the request list.
#define pair_delete_request(_pair_or_da)
Delete a fr_pair_t in the request list.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
#define tmpl_is_attr(vpt)
int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP 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.
tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
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 talloc_get_type_abort_const
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.
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
#define fr_time_lt(_a, _b)
void radius_track_state_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line, radius_track_t *tt, radius_track_log_extra_t extra)
Print out the state of every tracking entry.
int radius_track_entry_update(radius_track_entry_t *te, uint8_t const *vector)
Update a tracking entry with the authentication vector.
radius_track_t * radius_track_alloc(TALLOC_CTX *ctx)
Create an radius_track_t.
radius_track_entry_t * radius_track_entry_find(radius_track_t *tt, uint8_t packet_id, uint8_t const *vector)
Find a tracking entry from a request authenticator.
#define radius_track_entry_release(_te)
void * uctx
Result/resumption context.
unsigned int num_requests
number of requests in the allocation
#define radius_track_entry_reserve(_te_out, _ctx, _tt, _request, _code, _uctx)
request_t * request
as always...
Track one request to a response.
void trunk_connection_callback_readable(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
Standard I/O read function.
void trunk_connection_callback_writable(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
Standard I/O write function.
void trunk_request_signal_fail(trunk_request_t *treq)
Signal that a trunk request failed.
uint64_t trunk_connection_requests_requeue(trunk_connection_t *tconn, int states, uint64_t max, bool fail_bound)
Move requests off of a connection and requeue elsewhere.
trunk_enqueue_t trunk_request_enqueue_on_conn(trunk_request_t **treq_out, trunk_connection_t *tconn, request_t *request, void *preq, void *rctx, bool ignore_limits)
Enqueue additional requests on a specific connection.
trunk_enqueue_t trunk_request_enqueue(trunk_request_t **treq_out, trunk_t *trunk, request_t *request, void *preq, void *rctx)
Enqueue a request that needs data written to the trunk.
trunk_enqueue_t trunk_request_requeue(trunk_request_t *treq)
Re-enqueue a request on the same connection.
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_cancel(trunk_request_t *treq)
Cancel a trunk request.
void trunk_request_free(trunk_request_t **treq_to_free)
If the trunk request is freed then update the target requests.
trunk_request_t * trunk_request_alloc(trunk_t *trunk, request_t *request)
(Pre-)Allocate a new trunk request
void trunk_connection_signal_active(trunk_connection_t *tconn)
Signal a trunk connection is no longer full.
void trunk_connection_signal_inactive(trunk_connection_t *tconn)
Signal a trunk connection cannot accept more requests.
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.
void trunk_request_state_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line, trunk_request_t const *treq)
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.
Main trunk management handle.
#define TRUNK_REQUEST_STATE_ALL
All request states.
trunk_connection_alloc_t connection_alloc
Allocate a new connection_t.
trunk_connection_event_t
What type of I/O events the trunk connection is currently interested in receiving.
@ TRUNK_CONN_EVENT_BOTH
Trunk should be notified if a connection is readable or writable.
@ TRUNK_CONN_EVENT_WRITE
Trunk should be notified if a connection is writable.
@ TRUNK_CONN_EVENT_NONE
Don't notify the trunk on connection state changes.
@ TRUNK_CONN_EVENT_READ
Trunk should be notified if a connection is readable.
trunk_cancel_reason_t
Reasons for a request being cancelled.
@ TRUNK_CANCEL_REASON_REQUEUE
A previously sent request is being requeued.
@ TRUNK_ENQUEUE_DST_UNAVAILABLE
Destination is down.
@ TRUNK_ENQUEUE_FAIL
General failure.
@ TRUNK_ENQUEUE_OK
Operation was successful.
@ TRUNK_ENQUEUE_NO_CAPACITY
At maximum number of connections, and no connection has capacity.
@ TRUNK_ENQUEUE_IN_BACKLOG
Request should be enqueued in backlog.
trunk_request_state_t
Used for sanity checks and to simplify freeing.
@ TRUNK_REQUEST_STATE_PARTIAL
Some of the request was written to the socket, more of it should be written later.
@ TRUNK_REQUEST_STATE_INIT
Initial state.
@ TRUNK_REQUEST_STATE_PENDING
In the queue of a connection and is pending writing.
@ TRUNK_REQUEST_STATE_SENT
Was written to a socket. Waiting for a response.
Common configuration parameters for a trunk.
I/O functions to pass to trunk_alloc.
static fr_event_list_t * el
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
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.
struct value_pair_s fr_pair_t
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 updated
last update, really a cached "now".
fr_time_t next
when the next timer should be set
char const * fr_strerror(void)
Get the last library error.
#define fr_box_ipaddr(_val)
#define fr_box_time_delta(_val)
static size_t char ** out