24#include <freeradius-devel/io/listen.h>
25#include <freeradius-devel/io/master.h>
27#include <freeradius-devel/server/base.h>
28#include <freeradius-devel/server/module.h>
29#include <freeradius-devel/util/debug.h>
31#include <freeradius-devel/util/misc.h>
32#include <freeradius-devel/util/syserror.h>
169 talloc_free_children(track);
205 if (ret != 0)
return ret;
252 if (ret != 0)
return ret;
280static int8_t
track_cmp(
void const *one,
void const *two)
297 if (ret != 0)
return ret;
385#define DUP_FIELD(_x) do { if (parent->_x) {c->_x = talloc_strdup(c, parent->_x); if (!c->_x) {goto error;}}} while (0)
386#define COPY_FIELD(_x) c->_x = parent->_x
396 COPY_FIELD(require_message_authenticator_is_set);
441 pthread_mutex_lock(&client->
mutex);
444 pthread_mutex_unlock(&client->
mutex);
449 pthread_mutex_unlock(&client->
mutex);
471 TALLOC_FREE(connection->
client);
519 DEBUG(
"proto_%s - Ignoring connection from client %s - 'max_connections' limit reached.",
521 if (fd >= 0)
close(fd);
530 inst_name = talloc_asprintf(NULL,
"%"PRIu64, thread->
client_id++);
562 MEM(connection->
address = talloc_memdup(connection, address,
sizeof(*address)));
563 (void) talloc_set_name_const(connection->
address,
"fr_io_address_t");
565 connection->
parent = client;
569 memset(connection->
client, 0,
sizeof(*connection->
client));
585 if (
inst->app_io->track_duplicates) {
643 switch (client->
state) {
651 radclient->
active =
false;
671 memcpy(li, thread->
listen,
sizeof(*li));
686 inst->app_io->common.thread_inst_size);
689 inst->app_io->common.name);
709 memcpy(li, thread->
listen,
sizeof(*li));
726 if (
inst->app_io->connection_set(connection->
child, connection->
address) < 0) {
727 DEBUG(
"proto_%s - Failed setting connection for socket.",
inst->app->common.name);
748 struct sockaddr_storage src;
753 DEBUG(
"proto_%s - Failed getting IP address",
inst->app->common.name);
758 if (
inst->app_io->open(connection->
child) < 0) {
759 DEBUG(
"proto_%s - Failed opening connected socket.",
inst->app->common.name);
766 if (connect(fd, (
struct sockaddr *) &src, salen) < 0) {
777 if (
inst->app_io->fd_set(connection->
child, fd) < 0) {
778 DEBUG3(
"Failed setting FD to %s",
inst->app_io->common.name);
784 if (!
inst->app_io->get_name) {
785 connection->
name =
fr_asprintf(connection,
"proto_%s from client %pV port "
786 "%u to server %pV port %u",
787 inst->app->common.name,
793 connection->
name =
inst->app_io->get_name(connection->
child);
807 pthread_mutex_lock(&client->
mutex);
815 pthread_mutex_unlock(&client->
mutex);
816 ERROR(
"proto_%s - Failed inserting connection into tracking table. "
817 "Closing it, and discarding all packets for connection %s.",
818 inst->app_io->common.name, connection->
name);
822 pthread_mutex_unlock(&client->
mutex);
829 connection->
name = talloc_strdup(connection, nak->
name);
831 connection->
el = nak->
el;
835 DEBUG(
"proto_%s - starting connection %s",
inst->app_io->common.name, connection->
name);
837 if (!connection->
nr) {
838 ERROR(
"proto_%s - Failed inserting connection into scheduler. "
839 "Closing it, and diuscarding all packets for connection %s.",
840 inst->app_io->common.name, connection->
name);
841 pthread_mutex_lock(&client->
mutex);
843 pthread_mutex_unlock(&client->
mutex);
846 if (fd >= 0)
close(fd);
885 *
inst = (*connection)->client->inst;
886 if (thread) *thread = NULL;
887 if (child) *child = (*connection)->child;
902 radclient->
secret = radclient->
nas_type = talloc_strdup(radclient,
"");
952 memset(client, 0,
sizeof(*client));
954 client->
state = state;
984 if (
inst->app_io->track_duplicates) {
996 (void) pthread_mutex_init(&client->
mutex, NULL);
1005 ERROR(
"proto_%s - Failed inserting client %s into tracking table. Discarding client, and all packets for it.",
1033 uint8_t const *packet,
size_t packet_len,
1049 memcpy(my_address, address,
sizeof(*address));
1078 track, packet, packet_len);
1088 if (!old)
goto do_insert;
1112 len = talloc_array_length(old->
packet);
1113 if ((len == talloc_array_length(track->
packet)) &&
1122 DEBUG(
"Ignoring duplicate packet while client %s is still pending dynamic definition",
1213 pending->
track = track;
1271 int value, accept_fd = -1;
1284 if (*leftover)
goto do_read;
1298 if (connection->
dead) {
1299 DEBUG(
"Dead connection %s", connection->
name);
1314 track = pending->
track;
1320 talloc_set_destructor(pending, NULL);
1333 DEBUG3(
"Discarding old packet");
1342 *packet_ctx = track;
1344 recv_time = *recv_time_p = pending->
recv_time;
1353 memcpy(&address, track->
address,
sizeof(address));
1363 }
else if (!connection && (
inst->ipproto == IPPROTO_TCP)) {
1364 struct sockaddr_storage saremote;
1367 salen =
sizeof(saremote);
1374 accept_fd = accept(child->
fd,
1375 (
struct sockaddr *) &saremote, &salen);
1381 if (accept_fd < 0) {
1382 DEBUG(
"proto_%s - failed to accept new socket: %s",
1392#ifdef STATIC_ANALYZER
1393 saremote.ss_family = AF_INET;
1399 if ((saremote.ss_family == AF_INET) || (saremote.ss_family == AF_INET6)) {
1403 salen =
sizeof(saremote);
1408 (void) getsockname(accept_fd, (
struct sockaddr *) &saremote, &salen);
1411 address.
socket.
type = (
inst->ipproto == IPPROTO_TCP) ? SOCK_STREAM : SOCK_DGRAM;
1423 local_address = &address;
1443 packet_len =
inst->app_io->read(child, (
void **) &local_address, &recv_time,
1444 buffer, buffer_len, leftover);
1445 if (packet_len <= 0) {
1454 if (
inst->app->priority) {
1463 DEBUG2(
"proto_%s - ignoring packet from IP %pV. It is not configured as 'type = ...'",
1481 connection->
paused =
true;
1494 &address.
socket.inet.src_ipaddr.addr, address.
socket.inet.src_ipaddr.prefix);
1498 client = connection->
client;
1504 address = *connection->
address;
1511 if (accept_fd >= 0)
close(accept_fd);
1530 radclient =
inst->app_io->client_find(thread->
child, &address.
socket.inet.src_ipaddr,
inst->ipproto);
1538 radclient->
active =
true;
1540 }
else if (
inst->dynamic_clients) {
1542 if (accept_fd < 0) {
1543 DEBUG(
"proto_%s - ignoring packet from client IP address %pV - "
1544 "too many dynamic clients are defined",
1547 DEBUG(
"proto_%s - ignoring connection attempt from client IP address %pV "
1548 "- too many dynamic clients are defined",
1559 address.
socket.inet.src_ipaddr.prefix);
1561 DEBUG3(
"Source IP %pV is outside of 'allowed' network range",
1569 if (network->
af == AF_UNSPEC) {
1570 DEBUG3(
"Source IP %pV is forbidden by the 'deny' network range",
1584 if (accept_fd < 0) {
1585 DEBUG(
"proto_%s - ignoring packet from unknown client IP address %pV",
1588 DEBUG(
"proto_%s - ignoring connection attempt from unknown client IP address %pV",
1606 if (accept_fd >= 0) {
1629 bool is_dup =
false;
1633 DEBUG(
"Failed tracking packet from client %s - discarding it",
1645 DEBUG(
"Ignoring retransmit from client %s - we are not responding to this request", client->
radclient->
shortname);
1649 if (!track->
reply) {
1651 DEBUG(
"Ignoring retransmit from client %s - we are still processing the request", client->
radclient->
shortname);
1656 nr = connection->
nr;
1702 DEBUG(
"Too many pending packets for client %pV - discarding packet",
1721 DEBUG(
"Client %pV is still being dynamically defined. "
1722 "Caching this packet until the client has been defined",
1748 *packet_ctx = track;
1768 my_connection.
address = &address;
1770 pthread_mutex_lock(&client->
mutex);
1773 pthread_mutex_unlock(&client->
mutex);
1780 DEBUG(
"Discarding packet to NAKed connection %s", connection->
name);
1796 DEBUG(
"Sending packet to connection %s", connection->
name);
1815 buffer, packet_len, recv_time);
1827 bool is_dup =
false;
1835 DEBUG2(
"Received injected packet for an unconnected socket.");
1840 if (priority <= 0) {
1848 buffer, buffer_len, recv_time, &is_dup);
1850 DEBUG2(
"Failed injecting packet to tracking table");
1867 DEBUG2(
"Failed injecting packet due to allocation error");
1885 if (
inst->app_io->open(thread->
child) < 0)
return -1;
1926 if (!
inst->submodule)
return;
1928 if (
inst->app_io->event_list_set) {
1929 inst->app_io->event_list_set(child,
el, nr);
1940 connection->
el =
el;
1941 connection->
nr = nr;
1973 if (client->
ev)
return;
1975 switch (client->
state) {
1981 delay =
inst->idle_timeout;
1989 delay =
inst->nak_lifetime;
2030 connection->
dead =
true;
2072 DEBUG(
"proto_%s - No packets are using unconnected socket %s",
inst->app_io->common.name, connection->
name);
2096 pthread_mutex_lock(&client->
mutex);
2099 pthread_mutex_unlock(&client->
mutex);
2115 DEBUG(
"proto_%s - idle timeout for connection %s",
inst->app_io->common.name, connection->
name);
2127 delay =
inst->idle_timeout;
2141 delay =
inst->check_interval;
2146 ERROR(
"proto_%s - Failed adding timeout for dynamic client %s. It will be permanent!",
2182 DEBUG(
"proto_%s - cleaning up request in %.6fs",
inst->app_io->common.name,
2187 DEBUG(
"proto_%s - Failed adding cleanup_delay for packet. Discarding packet immediately",
2188 inst->app_io->common.name);
2196 DEBUG2(
"TIMER - proto_%s - cleanup delay",
inst->app_io->common.name);
2198 DEBUG2(
"proto_%s - cleaning up",
inst->app_io->common.name);
2239 el = connection->
el;
2260 DEBUG3(
"Suppressing reply as we have a newer packet");
2281 packet_len =
inst->app_io->write(child, track, request_time,
2282 buffer, buffer_len, written);
2283 if (packet_len <= 0) {
2294 if ((
size_t) packet_len < buffer_len) {
2302 if (!
inst->app_io->track_duplicates)
goto setup_timer;
2310 if (!track->
reply) {
2338 if ((buffer_len == 1) && (*
buffer ==
true)) {
2339 DEBUG(
"Request has timed out trying to define a new client. Trying again.");
2348 if (buffer_len == 1) {
2351 if (client->
table) TALLOC_FREE(client->
table);
2367 if (connection && (
inst->ipproto == IPPROTO_UDP)) {
2371 errno = ECONNREFUSED;
2384 fr_assert(buffer_len ==
sizeof(radclient));
2386 memcpy(&radclient,
buffer,
sizeof(radclient));
2397 DEBUG(
"Client IP address %pV IP version does not match the source network %pV of the packet.",
2407 DEBUG(
"Client IP address %pV is not within the prefix with the defined network %pV",
2412 ipaddr = radclient->
ipaddr;
2415 DEBUG(
"Client IP address %pV is not within the defined network %pV.",
2429 if (((radclient->
ipaddr.
af == AF_INET) &&
2431 ((radclient->
ipaddr.
af == AF_INET6) &&
2433 ERROR(
"Cannot define a dynamic client as a network");
2451#define COPY_FIELD(_x) client->radclient->_x = radclient->_x
2452#define DUP_FIELD(_x) client->radclient->_x = talloc_strdup(client->radclient, radclient->_x)
2469 COPY_FIELD(require_message_authenticator_is_set);
2487 talloc_steal(radclient, radclient->
cs);
2514 if (connection->
paused) {
2543 DEBUG(
"proto_%s - cannot use connected sockets as underlying 'transport = %s' does not support it.",
2544 inst->app_io->common.name,
inst->submodule->module->exported->name);
2567 (void) pthread_mutex_init(&client->
mutex, NULL);
2629 if (
inst->app_io->close) {
2632 ret =
inst->app_io->close(child);
2633 if (ret < 0)
return ret;
2639 if (!connection)
return 0;
2645 DEBUG(
"Closing connection %s", connection->
name);
2676 inst->app_io_conf =
inst->submodule->conf;
2677 inst->app_io_instance =
inst->submodule->data;
2685 if (!
inst->app_io->track_duplicates) {
2691 if (!
inst->app_io->track_create) {
2692 cf_log_err(
inst->app_io_conf,
"Internal error: 'track_duplicates' is set, but there is no 'track create' function");
2701 if (
inst->app_io->network_get) {
2702 inst->app_io->network_get(&
inst->ipproto, &
inst->dynamic_clients, &
inst->networks,
inst->app_io_instance);
2705 if ((
inst->ipproto == IPPROTO_TCP) && !
inst->app_io->connection_set) {
2706 cf_log_err(
inst->app_io_conf,
"Missing 'connection set' API for proto_%s",
inst->app_io->common.name);
2713 if (
inst->dynamic_clients) {
2717 cf_log_err(
conf,
"Cannot use 'dynamic_clients = yes' as the virtual server has no 'new client { ... }' section defined.");
2774 num = talloc_array_length(allow);
2777 for (i = 0; i < num; i++) {
2783 if (allow[i].af != af) {
2794 &allow[i].addr, allow[i].prefix);
2814 &allow[i].addr, allow[i].prefix);
2817 fr_strerror_const(
"Entry is completely enclosed inside of a previously defined network.");
2828 &allow[i].addr, allow[i].prefix,
2839 num = talloc_array_length(deny);
2840 if (!num)
return trie;
2846 for (i = 0; i < num; i++) {
2852 if (deny[i].af != af) {
2863 &deny[i].addr, deny[i].prefix);
2874 &deny[i].addr, deny[i].prefix);
2877 "contained within a previous 'allow'", i + 1,
fr_box_ipaddr(deny[i]));
2887 if (network->
af != af) {
2900 &deny[i].addr, deny[i].prefix,
2910 deny[i].
af = AF_UNSPEC;
2926 size_t default_message_size,
size_t num_messages)
2934 if (!
inst->app_io) {
2939 if (!
inst->app_io->common.thread_inst_size) {
2940 fr_strerror_const(
"IO modules MUST set 'thread_inst_size' when using the master IO handler.");
2986 if (
inst->dynamic_clients) {
3010 memcpy(child, li,
sizeof(*child));
3020 inst->app_io->common.thread_inst_size);
3024 inst->app_io->common.name);
3043 if (
inst->app_io->open(child) < 0) {
3044 cf_log_err(
inst->app_io_conf,
"Failed opening %s interface",
inst->app_io->common.name);
3066 ERROR(
"Failed opening %s - that port is already in use by another listener in server %s { ... } - %s",
3111 if (
unlikely(!thread))
return NULL;
3123 address->
socket.inet.src_port = src_port;
3124 address->
socket.inet.dst_port = dst_port;
3126 address->
socket.inet.src_ipaddr = *src_ipaddr;
3127 address->
socket.inet.dst_ipaddr = *dst_ipaddr;
3137 .name =
"radius_master_io",
3141 .default_message_size = 4096,
3142 .track_duplicates =
true,
static int const char char buffer[256]
module_t common
Common fields to all loadable modules.
fr_io_track_create_t track_create
create a tracking structure
bool track_duplicates
track duplicate packets
fr_io_name_t get_name
get the socket name
fr_io_track_cmp_t track_compare
compare two tracking structures
Public structure describing an I/O path for a protocol.
#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_PREFER_LARGER(_a, _b)
Evaluates to -1 for a > b, and +1 for a < b.
#define CMP_RETURN(_a, _b, _field)
Return if the comparison is not 0 (is unequal)
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#define FR_TIME_DELTA_BOUND_CHECK(_name, _var, _op, _bound)
A section grouping multiple CONF_PAIR.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
char const * cf_section_name1(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
CONF_SECTION * cf_section_dup(TALLOC_CTX *ctx, CONF_SECTION *parent, CONF_SECTION const *cs, char const *name1, char const *name2, bool copy_meta)
Duplicate a configuration section.
#define cf_log_err(_cf, _fmt,...)
#define cf_log_warn(_cf, _fmt,...)
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
#define fr_event_filter_update(...)
#define FR_EVENT_RESUME(_s, _f)
Re-add the filter for a func from kevent.
#define FR_EVENT_SUSPEND(_s, _f)
Temporarily remove the filter for a func from kevent.
#define fr_event_timer_at(...)
#define fr_event_timer_in(...)
Callbacks for the FR_EVENT_FILTER_IO filter.
Structure describing a modification to a filter's state.
void * fr_hash_table_find(fr_hash_table_t *ht, void const *data)
Find data in a hash table.
uint32_t fr_hash_update(void const *data, size_t size, uint32_t hash)
uint32_t fr_hash(void const *data, size_t size)
bool fr_hash_table_insert(fr_hash_table_t *ht, void const *data)
Insert data into a hash table.
bool fr_hash_table_delete(fr_hash_table_t *ht, void const *data)
Remove and free data (if a free function was specified)
uint32_t fr_hash_table_num_elements(fr_hash_table_t *ht)
#define fr_hash_table_alloc(_ctx, _hash_node, _cmp_node, _free_node)
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
void * fr_heap_pop(fr_heap_t **hp)
Remove a node from the heap.
int fr_heap_extract(fr_heap_t **hp, void *data)
Remove a node from the heap.
unsigned int fr_heap_index_t
static void * fr_heap_peek(fr_heap_t *h)
Return the item from the top of the heap but don't pop it.
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init)
Creates a heap that can be used with non-talloced elements.
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
static unsigned int fr_heap_num_elements(fr_heap_t *h)
Return the number of elements in the heap.
#define FR_HEAP_INDEX_INVALID
int fr_ipaddr_from_sockaddr(fr_ipaddr_t *ipaddr, uint16_t *port, struct sockaddr_storage const *sa, socklen_t salen)
Convert sockaddr to our internal ip address representation.
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
void fr_ipaddr_mask(fr_ipaddr_t *addr, uint8_t prefix)
Zeroes out the host portion of an fr_ipaddr_t.
uint8_t prefix
Prefix length - Between 0-32 for IPv4 and 0-128 for IPv6.
union fr_ipaddr_t::@130 addr
fr_socket_t socket
src/dst ip and port.
fr_client_t const * radclient
old-style client definition
size_t num_messages
for the message ring buffer
char const * name
printable name for this socket - set by open
bool track_duplicates
do we track duplicate packets?
fr_socket_t * app_io_addr
for tracking duplicate sockets
void const * app_instance
size_t default_message_size
copied from app_io, but may be changed
bool connected
is this for a connected socket?
void const * app_io_instance
I/O path configuration context.
CONF_SECTION * server_cs
CONF_SECTION of the server.
void * thread_instance
thread / socket context
int fd
file descriptor for this socket - set by open
fr_app_io_t const * app_io
I/O path functions.
int fr_network_listen_delete(fr_network_t *nr, fr_listen_t *li)
Delete a socket from a network.
int fr_network_listen_inject(fr_network_t *nr, fr_listen_t *li, uint8_t const *packet, size_t packet_len, fr_time_t recv_time)
Inject a packet for a listener to read.
void fr_network_listen_read(fr_network_t *nr, fr_listen_t *li)
Signal the network to read from a listener.
void fr_network_listen_write(fr_network_t *nr, fr_listen_t *li, uint8_t const *packet, size_t packet_len, void *packet_ctx, fr_time_t request_time)
Inject a packet for a listener to write.
char const * server
Name of the virtual server client is associated with.
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
char const * secret
Secret PSK.
bool active
for dynamic clients
fr_ipaddr_t src_ipaddr
IPv4/IPv6 address to send responses from (family must match ipaddr).
char const * nas_type
Type of client (arbitrary).
int proto
Protocol number.
CONF_SECTION * cs
CONF_SECTION that was parsed to generate the client.
bool dynamic
Whether the client was dynamically defined.
char const * longname
Client identifier.
fr_socket_limit_t limit
Connections per client (TCP clients only).
char const * shortname
Client nickname.
bool use_connected
do we use connected sockets for this client
CONF_SECTION * server_cs
Virtual server that the client is associated with.
Describes a host allowed to send packets to the server.
int fr_event_timer_delete(fr_event_timer_t const **ev_p)
Delete a timer event from the event list.
Stores all information relating to an event list.
fr_listen_t * child
The child (app_io) IO path.
fr_network_t * nr
network for this connection
static int8_t alive_client_cmp(void const *one, void const *two)
bool in_trie
is the client in the trie?
bool paused
event filter doesn't like resuming something that isn't paused
bool in_parent_hash
for tracking thread issues
static fr_client_t * radclient_clone(TALLOC_CTX *ctx, fr_client_t const *parent)
static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time_p, uint8_t *buffer, size_t buffer_len, size_t *leftover)
Implement 99% of the read routines.
int packets
number of packets using this connection
static void client_expiry_timer(fr_event_list_t *el, fr_time_t now, void *uctx)
uint32_t num_pending_packets
number of pending packets
static int track_dedup_free(fr_io_track_t *track)
fr_rb_tree_t * table
tracking table for packets
static int8_t pending_packet_cmp(void const *one, void const *two)
fr_heap_t * pending_clients
heap of pending clients
static fr_io_track_t * fr_io_track_add(fr_io_client_t *client, fr_io_address_t *address, uint8_t const *packet, size_t packet_len, fr_time_t recv_time, bool *is_dup)
bool ready_to_delete
are we ready to delete this client?
static fr_io_pending_packet_t * fr_io_pending_alloc(fr_io_client_t *client, uint8_t const *buffer, size_t packet_len, fr_io_track_t *track, int priority)
static int _client_live_free(fr_io_client_t *client)
fr_heap_index_t pending_id
for pending clients
static int pending_free(fr_io_pending_packet_t *pending)
bool use_connected
does this client allow connected sub-sockets?
fr_io_client_t * client
our local client (pending or connected).
static int track_free(fr_io_track_t *track)
fr_app_io_t fr_master_app_io
fr_listen_t * listen
The master IO path.
static int8_t pending_client_cmp(void const *one, void const *two)
fr_io_track_t * fr_master_io_track_alloc(fr_listen_t *li, fr_client_t *radclient, fr_ipaddr_t const *src_ipaddr, int src_port, fr_ipaddr_t const *dst_ipaddr, int dst_port)
fr_io_address_t * address
full information about the connection.
static int8_t address_cmp(void const *one, void const *two)
fr_event_timer_t const * ev
when we clean up the client
fr_listen_t * child
child listener (app_io) for this socket
fr_listen_t * listen
master listener for this socket
static void packet_expiry_timer(fr_event_list_t *el, fr_time_t now, void *uctx)
fr_network_t * nr
network for the master socket
fr_trie_t * fr_master_io_network(TALLOC_CTX *ctx, int af, fr_ipaddr_t *allow, fr_ipaddr_t *deny)
Create a trie from arrays of allow / deny IP addresses.
static fr_io_pending_packet_t * pending_packet_pop(fr_io_thread_t *thread)
fr_ipaddr_t network
network for dynamic clients
static void mod_event_list_set(fr_listen_t *li, fr_event_list_t *el, void *nr)
Set the event list for a new socket.
static int mod_open(fr_listen_t *li)
Open a new listener.
pthread_mutex_t mutex
for parent / child signaling
static fr_io_client_t * client_alloc(TALLOC_CTX *ctx, fr_io_client_state_t state, fr_io_instance_t const *inst, fr_io_thread_t *thread, fr_client_t *radclient, fr_ipaddr_t const *network)
fr_io_instance_t const * inst
parent instance for master IO handler
fr_trie_t * trie
trie of clients
fr_io_client_state_t
Client states.
@ PR_CLIENT_DYNAMIC
dynamically defined client
@ PR_CLIENT_CONNECTED
dynamically defined client in a connected socket
@ PR_CLIENT_PENDING
dynamic client pending definition
@ PR_CLIENT_NAK
negative cache entry
@ PR_CLIENT_STATIC
static / global clients
static void get_inst(fr_listen_t *li, fr_io_instance_t const **inst, fr_io_thread_t **thread, fr_io_connection_t **connection, fr_listen_t **child)
static fr_event_update_t pause_read[]
static int8_t track_connected_cmp(void const *one, void const *two)
fr_heap_t * alive_clients
heap of active clients
fr_schedule_t * sc
the scheduler
static fr_io_connection_t * fr_io_connection_alloc(fr_io_instance_t const *inst, fr_io_thread_t *thread, fr_io_client_t *client, int fd, fr_io_address_t *address, fr_io_connection_t *nak)
Create a new connection.
fr_hash_table_t * addresses
list of src/dst addresses used by this client
int fr_master_io_listen(fr_io_instance_t *inst, fr_schedule_t *sc, size_t default_message_size, size_t num_messages)
static int connection_free(fr_io_connection_t *connection)
int fr_io_listen_free(fr_listen_t *li)
char const * name
taken from proto_FOO_TRANSPORT
fr_heap_index_t alive_id
for all clients
fr_event_list_t * el
event list for this connection
fr_io_client_state_t state
state of this client
int packets
number of packets using this client
static ssize_t mod_write(fr_listen_t *li, void *packet_ctx, fr_time_t request_time, uint8_t *buffer, size_t buffer_len, size_t written)
bool dead
roundabout way to get the network side to close a socket
fr_event_list_t * el
event list, for the master socket.
uint64_t client_id
Unique client identifier.
static char const * mod_name(fr_listen_t *li)
module_instance_t * mi
for submodule
static int _client_free(fr_io_client_t *client)
static int mod_close(fr_listen_t *li)
Close the socket.
static uint32_t connection_hash(void const *ctx)
fr_io_connection_t * connection
parent connection
fr_heap_t * pending
pending packets for this client
static int count_connections(UNUSED uint8_t const *key, UNUSED size_t keylen, void *data, void *ctx)
Count the number of connections used by active clients.
static int8_t connection_cmp(void const *one, void const *two)
static int8_t track_cmp(void const *one, void const *two)
fr_hash_table_t * ht
for tracking connected sockets
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_client_t * radclient
old-style definition of this client
fr_ipaddr_t src_ipaddr
packets come from this address
static fr_event_update_t resume_read[]
uint32_t num_connections
number of dynamic connections
fr_io_client_t * parent
points to the parent client.
static fr_client_t * radclient_alloc(TALLOC_CTX *ctx, int ipproto, fr_io_address_t *address)
static int mod_inject(fr_listen_t *li, uint8_t const *buffer, size_t buffer_len, fr_time_t recv_time)
Inject a packet to a connection.
Client definitions for master IO.
uint8_t * reply
reply packet (if any)
fr_event_timer_t const * ev
when we clean up this tracking entry
int packets
number of packets using this entry
fr_time_t dynamic
timestamp for packet doing dynamic client definition
void * app_io_instance
Easy access to the app_io instance.
fr_app_io_t const * app_io
Easy access to the app_io handle.
fr_io_address_t const * address
of this packet.. shared between multiple packets
bool do_not_respond
don't respond
bool discard
whether or not we discard the packet
fr_time_t timestamp
when this packet was received
bool finished
are we finished the request?
uint8_t * packet
really a tracking structure, not a packet
size_t reply_len
length of reply, or 1 for "do not reply"
fr_io_client_t * client
client handling this packet.
fr_time_t expires
when this packet expires
int fr_nonblock(UNUSED int fd)
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for instantiation calls.
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
static char const * proto(int id, int porttype)
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
#define fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free)
Allocs a red black that verifies elements are of a specific talloc type.
The main red black tree structure.
static unsigned int hash(char const *username, unsigned int tablesize)
fr_network_t * fr_schedule_listen_add(fr_schedule_t *sc, fr_listen_t *li)
Add a fr_listen_t to a scheduler.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
module_instantiate_t instantiate
Callback to allow the module to register any per-instance resources like sockets and file handles.
@ MODULE_INSTANCE_BOOTSTRAPPED
Module instance has been bootstrapped, but not yet instantiated.
size_t thread_inst_size
Size of the module's thread-specific instance data.
fr_time_delta_t idle_timeout
static const uchar sc[16]
module_list_type_t const module_list_type_thread_local
Callbacks for a thread local list.
void module_list_mask_set(module_list_t *ml, module_instance_state_t mask)
Set a new bootstrap/instantiate state for a list.
module_instance_t * module_instance_copy(module_list_t *dst, module_instance_t const *src, char const *inst_name)
Duplicate a module instance, placing it in a new module list.
module_list_t * module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name, bool write_protect)
Allocate a new module list.
int module_thread_instantiate(TALLOC_CTX *ctx, module_instance_t *mi, fr_event_list_t *el)
Allocate thread-local instance data for a module.
int module_instantiate(module_instance_t *instance)
Manually complete module setup by calling its instantiate function.
int module_instance_conf_parse(module_instance_t *mi, CONF_SECTION *conf)
Covert a CONF_SECTION into parsed module instance data.
eap_aka_sim_process_conf_t * inst
#define fr_time()
Allow us to arbitrarily manipulate time.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define talloc_get_type_abort_const
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
static int talloc_const_free(void const *ptr)
Free const'd memory.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
#define fr_time_delta_lt(_a, _b)
static int64_t fr_time_unwrap(fr_time_t time)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_wrap(_time)
#define fr_time_wrap(_time)
#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_neq(_a, _b)
A time delta, a difference in time measured in nanoseconds.
void * fr_trie_remove_by_key(fr_trie_t *ft, void const *key, size_t keylen)
Remove a key and return the associated user ctx.
fr_trie_t * fr_trie_alloc(TALLOC_CTX *ctx, fr_trie_key_t get_key, fr_free_t free_data)
Allocate a trie.
int fr_trie_walk(fr_trie_t *ft, void *ctx, fr_trie_walk_t callback)
void * fr_trie_lookup_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Lookup a key in a trie and return user ctx, if any.
void * fr_trie_match_by_key(fr_trie_t const *ft, void const *key, size_t keylen)
Match a key and length in a trie and return user ctx, if any.
int fr_trie_insert_by_key(fr_trie_t *ft, void const *key, size_t keylen, void const *data)
Insert a key and user ctx into a trie.
static fr_event_list_t * el
int fd
File descriptor if this is a live socket.
int type
SOCK_STREAM, SOCK_DGRAM, etc.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print
#define fr_box_ipaddr(_val)
#define fr_box_time_delta(_val)
bool listen_record(fr_listen_t *li)
Record that we're listening on a particular IP / port.
fr_listen_t * listen_find_any(fr_listen_t *li)
See if another global listener is using a particular IP / port.