25 RCSID(
"$Id: 8fe720681456fe47a9bbca30641313e2e59061a1 $")
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)
251 UNUSED int flags,
void *uctx);
280 fr_log(log, log_type,
file,
line,
"request %s, allocated %s:%u", request->name,
281 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 length %ld 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",
738 h->
mmsgvec[i].msg_hdr.msg_iovlen = 1;
761 h->
name =
fr_asprintf(h,
"proto udp local %pV port %u remote %pV port %u",
772 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt,
sizeof(
int)) < 0) {
781 socklen_t socklen =
sizeof(int);
785 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt,
sizeof(
int)) < 0) {
786 WARN(
"%s - Failed setting 'SO_SNDBUF', write performance may be sub-optimal: %s",
791 if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, &socklen) < 0) {
792 WARN(
"%s - Failed getting 'SO_SNDBUF', write performance may be sub-optimal: %s",
804 WARN(
"%s - Max coalesced outbound data will be %zu bytes", h->
module_name,
822 WARN(
"%s - Modifying 'SO_SNDBUF' value is not supported on this system, "
823 "write performance may be sub-optimal", h->
module_name);
824 WARN(
"%s - Max coalesced outbound data will be %zu bytes", h->
module_name, h->
inst->send_buff_actual);
886 DEBUG4(
"Freeing rlm_radius_udp handle %p", handle);
925 char const *log_prefix,
void *uctx)
1004 switch (notify_on) {
1056 switch (notify_on) {
1106 if (ret != 0)
return ret;
1112 if (ret != 0)
return ret;
1151 .secret_length = talloc_array_length(
inst->secret) - 1,
1156 .request_code = u->
code,
1157 .request_authenticator = request_authenticator,
1158 .tmp_ctx = talloc(ctx,
uint8_t),
1159 .end =
data + data_len,
1168 data, data_len, &decode_ctx) < 0) {
1177 RDEBUG(
"Received %s ID %d length %ld reply packet on connection %s",
1181 *response_code = code;
1201 int proxy_state = 6;
1263 }
else if (
inst->parent->originate) {
1282 inst->secret, talloc_array_length(
inst->secret) - 1,
1283 u->
code,
id, &request->request_pairs);
1285 RPERROR(
"Failed encoding packet");
1292 if (packet_len < 0) {
1296 have = u->
packet_len - (proxy_state + message_authenticator);
1297 need = have - packet_len;
1300 RERROR(
"Failed encoding packet. Have %zu bytes of buffer, need %zu bytes",
1303 RERROR(
"Failed encoding packet. Have %zu bytes of buffer, need %zu bytes. "
1304 "Increase 'max_packet_size'", have, need);
1337 if ((
vp->vp_length == 5) && (memcmp(
vp->vp_octets, &
inst->parent->proxy_state, 4) == 0)) {
1348 if (
count >= 4)
RWARN(
"Potential proxy loop detected! Please recheck your configuration.");
1353 memcpy(attr + 2, &
inst->parent->proxy_state, 4);
1354 attr[6] =
count & 0xff;
1368 if (message_authenticator) {
1375 packet_len +=
msg[1];
1381 u->
packet[2] = (packet_len >> 8) & 0xff;
1382 u->
packet[3] = packet_len & 0xff;
1403 end = u->
packet + packet_len;
1409 if (attr[1] != 6)
continue;
1418 memcpy(&delay, attr + 2, 4);
1419 delay = ntohl(delay);
1421 delay = htonl(delay);
1422 memcpy(attr + 2, &delay, 4);
1433 if (message_authenticator)
goto sign;
1443 talloc_array_length(
inst->secret) - 1) < 0) {
1444 RERROR(
"Failed signing packet");
1477 INFO(
"%s - No replies during 'zombie_period', marking connection %s as dead", h->
module_name, h->
name);
1501 ERROR(
"Failed inserting revive timeout for connection");
1576 ERROR(
"Failed inserting zombie timeout for connection");
1639 REDEBUG(
"Reached maximum_retransmit_duration (%pVs > %pVs), failing request",
1644 REDEBUG(
"Reached maximum_retransmit_count (%u > %u), failing request",
1669 h = talloc_get_type_abort(treq->tconn->conn->h,
udp_handle_t);
1687 REDEBUG(
"Reached maximum_retransmit_duration (%pVs > %pVs), failing request",
1692 REDEBUG(
"Reached maximum_retransmit_count (%u > %u), failing request",
1700 WARN(
"%s - No response to status check, marking connection as dead - %s", h->
module_name, h->
name);
1717 size_t total_len = 0;
1723 for (i = 0, queued = 0; (i <
inst->max_send_coalesce) && (total_len < h->send_buff_actual); i++) {
1738 request = treq->request;
1774 RDEBUG(
"Sending %s ID %d length %ld over connection %s",
1795 RDEBUG(
"Retransmitting %s ID %d length %ld over connection %s",
1830 if (queued == 0)
return;
1848 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1855 WARN(
"%s - Failed sending data over connection %s: %s",
1870 ERROR(
"%s - Failed sending data over connection %s: %s",
1881 ERROR(
"%s - Failed sending data over connection %s: %s",
1892 for (i = 0; i < sent; i++) {
1905 request = treq->request;
1912 action =
inst->parent->originate ?
"Originated" :
"Proxied";
1917 action =
"Retransmitted";
1921 RDEBUG(
"%s status check. Expecting response within %pVs", action,
1925 RERROR(
"Failed inserting retransmit timeout for connection");
1930 }
else if (!
inst->parent->synchronous) {
1931 RDEBUG(
"%s request. Expecting response within %pVs", action,
1935 RERROR(
"Failed inserting retransmit timeout for connection");
1944 RERROR(
"Failed inserting timeout for connection");
1953 RDEBUG(
"%s request. Relying on NAS to perform more retransmissions", action);
1974 size_t total_len = 0;
1976 for (i = 0, queued = 0; (i <
inst->max_send_coalesce) && (total_len < h->send_buff_actual); i++) {
1991 request = treq->request;
2003 RDEBUG(
"Sending %s ID %d length %ld over connection %s",
2023 if (queued == 0)
return;
2038 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
2045 WARN(
"%s - Failed sending data over connection %s: %s",
2060 ERROR(
"%s - Failed sending data over connection %s: %s",
2071 ERROR(
"%s - Failed sending data over connection %s: %s",
2078 for (i = 0; i < sent; i++) {
2099 bool error_601 =
false;
2114 memcpy(&error, attr + 2, 4);
2115 error = ntohl(error);
2116 if (error == 601) error_601 =
true;
2124 memcpy(&response_length, attr + 2, 4);
2141 if (attr[1] != 7)
continue;
2151 if ((attr[3] != 0) ||
2165 if (attr[6] != u->
code) {
2178 if (error_601 && response_length && (response_length > h->
buflen)) {
2179 if (response_length < 4096) response_length = 4096;
2180 if (response_length > 65535) response_length = 65535;
2182 DEBUG(
"%s - Increasing buffer size to %u for connection %s", h->
module_name, response_length, h->
name);
2188 h->
buflen = response_length;
2191 memcpy(h->
buffer, attr, end - attr);
2245 DEBUG(
"Received %d / %u replies for status check, on connection - %s",
2266 DEBUG(
"Received enough replies to status check, marking connection as active - %s", h->
name);
2310 if (slen == 0)
return;
2313 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
return;
2315 ERROR(
"%s - Failed reading response from socket: %s",
2322 ERROR(
"%s - Packet too short, expected at least %zu bytes got %zd bytes",
2333 WARN(
"%s - Ignoring reply with ID %i that arrived too late",
2339 request = treq->request;
2348 if (!
check(h, &slen)) {
2349 RWARN(
"Ignoring malformed packet");
2353 reason =
decode(request->reply_ctx, &reply, &code, h, request, u, rr->vector, h->
buffer, (
size_t)slen);
2437 treq->request->reply->code = code;
2603 case FR_SIGNAL_CANCEL:
2647 if (!r->
treq)
return 0;
2681 RWDEBUG(
"Status-Server is reserved for internal use, and cannot be sent manually.");
2697 u->
code = request->packet->code;
2699 u->
priority = request->async->priority;
2700 u->
recv_time = request->async->recv_time;
2726 REDEBUG(
"Unable to queue packet - connections at maximum capacity");
2734 REDEBUG(
"All destinations are down - cannot send packet");
2738 REDEBUG(
"Unable to queue packet");
2783 inst->trunk_conf = &
inst->parent->trunk_conf;
2785 inst->trunk_conf->req_pool_headers = 4;
2788 thread->
el = mctx->
el;
2791 inst->trunk_conf,
inst->parent->name, thread,
false);
2792 if (!thread->
trunk)
return -1;
2804 ERROR(
"IO module cannot be instantiated directly");
2814 if (
inst->max_send_coalesce == 0)
inst->max_send_coalesce = 1;
2819 if (
inst->dst_ipaddr.af == AF_UNSPEC) {
2828 if (
inst->src_ipaddr.af == AF_UNSPEC) {
2829 memset(&
inst->src_ipaddr, 0,
sizeof(
inst->src_ipaddr));
2831 inst->src_ipaddr.af =
inst->dst_ipaddr.af;
2833 if (
inst->src_ipaddr.af == AF_INET) {
2834 inst->src_ipaddr.prefix = 32;
2836 inst->src_ipaddr.prefix = 128;
2840 else if (
inst->src_ipaddr.af !=
inst->dst_ipaddr.af) {
2841 cf_log_err(
conf,
"The 'ipaddr' and 'src_ipaddr' configuration items must "
2842 "be both of the same address family");
2846 if (!
inst->dst_port) {
2859 if (
inst->replicate) {
2863 inst->recv_buff_is_set =
true;
2871 inst->recv_buff = 0;
2874 if (
inst->recv_buff_is_set) {
2882 if (
inst->send_buff_is_set) {
2895 .name =
"radius_udp",
2899 .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 FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#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,...)
@ FR_CONNECTION_STATE_CONNECTING
Waiting for connection to establish.
@ FR_CONNECTION_STATE_FAILED
Connection has failed.
@ FR_CONNECTION_STATE_INIT
Init state, sets up connection.
@ FR_CONNECTION_STATE_CONNECTED
File descriptor is open (ready for writing).
@ FR_CONNECTION_FAILED
Connection is being reconnected because it failed.
Holds a complete set of functions for a connection.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
#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_DISCONNECT_REQUEST
RFC3575/RFC5176 - Disconnect-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_COA_REQUEST
RFC3575/RFC5176 - CoA-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_ACCOUNTING_REQUEST
RFC2866 - Accounting-Request.
@ 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.
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.
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 DEBUG_ENABLED
True if global debug level 1 messages are enabled.
#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.
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 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.
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(uint8_t *packet, size_t packet_len, uint8_t const *original, char const *secret, size_t secret_len, int code, int id, fr_pair_list_t *vps)
Encode VPS into a raw RADIUS packet.
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
#define RADIUS_AUTH_VECTOR_OFFSET
#define RADIUS_MAX_PACKET_SIZE
#define RADIUS_MESSAGE_AUTHENTICATOR_LENGTH
TALLOC_CTX * tmp_ctx
for temporary things cleaned up during decoding
uint32_t fr_rand(void)
Return a 32-bit random number.
#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.
static unsigned int hash(char const *username, unsigned int tablesize)
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 void request_mux_replicate(UNUSED fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_connection_t *conn, UNUSED void *uctx)
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.
static int8_t request_prioritise(void const *one, void const *two)
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.
fr_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)
static void thread_conn_notify_replicate(fr_trunk_connection_t *tconn, fr_connection_t *conn, fr_event_list_t *el, fr_trunk_connection_event_t notify_on, UNUSED void *uctx)
A special version of the trunk/event loop glue function which always discards incoming data.
uint16_t dst_port
Port of the home server.
static void request_mux(fr_event_list_t *el, fr_trunk_connection_t *tconn, fr_connection_t *conn, UNUSED void *uctx)
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 fr_connection_state_t conn_failed(void *handle, fr_connection_state_t state, UNUSED void *uctx)
Connection failed.
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)
#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 fr_connection_state_t conn_init(void **h_out, fr_connection_t *conn, void *uctx)
Initialise a new outbound connection.
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
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 request_cancel(UNUSED fr_connection_t *conn, void *preq_to_reset, fr_trunk_cancel_reason_t reason, UNUSED void *uctx)
Remove the request from any tracking structures.
static void conn_discard(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
Read and discard data.
fr_trunk_request_t * treq
Used for signalling.
rlm_radius_t * parent
rlm_radius instance.
static fr_dict_attr_t const * attr_proxy_state
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)
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 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.
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 status_check_reply(fr_trunk_request_t *treq, fr_time_t now)
Deal with replies replies to status checks and possible negotiation.
static void status_check_retry(UNUSED fr_event_list_t *el, fr_time_t now, void *uctx)
static void request_fail(request_t *request, void *preq, void *rctx, NDEBUG_UNUSED fr_trunk_request_state_t state, UNUSED void *uctx)
Write out a canned failure.
static void request_retry(fr_event_list_t *el, fr_time_t now, void *uctx)
Handle retries when a request is being sent asynchronously.
static void request_conn_release_replicate(UNUSED fr_connection_t *conn, void *preq_to_reset, UNUSED void *uctx)
Clear out anything associated with the handle from the request.
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.
static fr_dict_attr_t const * attr_acct_delay_time
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.
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)
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.
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
bool require_ma
saved from the original packet.
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.
fr_trunk_t * trunk
trunk handler
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.
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
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.
bool can_retransmit
can we retransmit this packet?
fr_event_timer_t const * zombie_ev
Zombie timeout.
bool status_checking
whether we're doing status checks
size_t buflen
Receive buffer length.
char const * module_name
the module that opened the connection
fr_trunk_request_t * treq
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 fr_connection_signal_connected(fr_connection_t *conn)
Asynchronously signal that the connection is open.
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.
#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.
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)
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
#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 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_connection_signal_active(fr_trunk_connection_t *tconn)
Signal a trunk connection is no longer full.
void fr_trunk_request_signal_cancel(fr_trunk_request_t *treq)
Cancel a trunk request.
fr_trunk_enqueue_t fr_trunk_request_enqueue_on_conn(fr_trunk_request_t **treq_out, fr_trunk_connection_t *tconn, request_t *request, void *preq, void *rctx, bool ignore_limits)
Enqueue additional requests on a specific connection.
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_state_log(fr_log_t const *log, fr_log_type_t log_type, char const *file, int line, fr_trunk_request_t const *treq)
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.
@ FR_TRUNK_ENQUEUE_NO_CAPACITY
At maximum number of connections, and no connection has capacity.
@ FR_TRUNK_ENQUEUE_OK
Operation was successful.
@ FR_TRUNK_ENQUEUE_DST_UNAVAILABLE
Destination is down.
@ FR_TRUNK_ENQUEUE_FAIL
General failure.
Common configuration parameters for a trunk.
I/O functions to pass to fr_trunk_alloc.
static fr_event_list_t * el
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
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