23#include <freeradius-devel/util/test/acutest_common_init.h>
24#include <freeradius-devel/util/test/acutest_helpers.h>
27#include <freeradius-devel/bio/bio_priv.h>
28#include <freeradius-devel/bio/fd.h>
29#include <freeradius-devel/util/syserror.h>
52 struct sockaddr_in sin = {
53 .sin_family = AF_INET,
54 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
56 socklen_t
len =
sizeof(sin);
59 fd = socket(AF_INET, SOCK_STREAM, 0);
60 if (fd < 0)
return -1;
62 if ((bind(fd, (
struct sockaddr *) &sin,
sizeof(sin)) < 0) ||
63 (listen(fd, 5) < 0) ||
64 (getsockname(fd, (
struct sockaddr *) &sin, &
len) < 0)) {
69 *port = ntohs(sin.sin_port);
102 if (listen_fd < 0)
goto done;
110 .socket_type = SOCK_STREAM,
115 .addr.v4.s_addr = htonl(INADDR_LOOPBACK),
132 TEST_MSG(
"connect_full returned %d. 0 means deferred, 1 means connected at once, <0 means failed", rcode);
134 if (rcode < 0)
goto done;
148 TEST_MSG(
"connected_count = %d, error_count = %d, timeout_count = %d, connect_errno = %d",
151 TEST_CASE(
"neither the error callback nor the timeout callback ran");
159 if (listen_fd >= 0) close(listen_fd);
181 struct sockaddr_in6 sin6 = {
182 .sin6_family = AF_INET6,
183 .sin6_addr = IN6ADDR_LOOPBACK_INIT,
188 fd = socket(AF_INET6, SOCK_DGRAM, 0);
189 if (fd < 0)
return false;
191 usable = (bind(fd, (
struct sockaddr *) &sin6,
sizeof(sin6)) == 0);
205 struct sockaddr_storage to;
210 struct timeval recv_timeout = { .tv_sec = 5 };
220 .socket_type = SOCK_DGRAM,
224 .prefix = (af == AF_INET) ? 32 : 128,
235 TEST_MSG(
"the bio did not learn the port which the kernel picked");
241 loopback = (
fr_ipaddr_t) { .
af = AF_INET, .prefix = 32, .addr.v4.s_addr = htonl(INADDR_LOOPBACK) };
243 loopback = (
fr_ipaddr_t) { .
af = AF_INET6, .prefix = 128, .addr.v6 = in6addr_loopback };
248 fd = socket(af, SOCK_DGRAM, 0);
250 if (fd < 0)
goto done;
252 rcode = sendto(fd,
"x", 1, 0, (
struct sockaddr *) &to, to_len);
255 if (rcode != 1)
goto done;
261 TEST_CHECK(setsockopt(info->
socket.
fd, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout,
sizeof(recv_timeout)) == 0);
265 TEST_CASE(
"the packet is read, not dropped");
267 TEST_MSG(
"fr_bio_read returned %zd", rcode);
268 if (rcode != 1)
goto done;
270 TEST_CASE(
"the destination is the loopback address and the port of the bio");
276 if (fd >= 0) close(fd);
static int const char char buffer[256]
static ssize_t fr_bio_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read raw data from a bio.
static int packet_ctx
the tests pass only the address of packet_ctx
static void cb_timeout(fr_bio_t *bio)
static void recvfromto_test(int af)
static void test_deferred_connect_success_calls_connected_cb(void)
A deferred connect which succeeds has to call the connected callback.
static bool ipv6_loopback_usable(void)
Read one packet through an unconnected UDP bio bound to the wildcard address.
static void test_recvfromto6(void)
static int loopback_listen(uint16_t *port)
Open a TCP socket listening on loopback.
static void cb_error(fr_bio_t *bio)
static int connected_count
static void test_recvfromto4(void)
static void cb_connected(fr_bio_t *bio)
int fr_bio_fd_connect_full(fr_bio_t *bio, fr_event_list_t *el, fr_bio_callback_t connected_cb, fr_bio_callback_t error_cb, fr_time_delta_t *timeout, fr_bio_callback_t timeout_cb)
Finalize a connect()
fr_bio_t * fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
Allocate a FD bio.
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
fr_socket_t socket
as connected socket
@ FR_BIO_FD_TRANSPORT_TCP
TCP over IPv4 or IPv6.
@ FR_BIO_FD_TRANSPORT_UDP
UDP over IPv4 or IPv6.
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
@ FR_BIO_FD_STATE_OPEN
error states must be before this
fr_ipaddr_t dst_ipaddr
their IP address
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
fr_ipaddr_t src_ipaddr
our IP address
Configuration for sockets.
Run-time status of the socket.
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.
fr_cmp_ret_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
Compare two ip addresses.
void fr_event_service(fr_event_list_t *el)
Service any outstanding timer or file descriptor events.
int fr_event_corral(fr_event_list_t *el, fr_time_t now, bool wait)
Gather outstanding timer and file descriptor events.
fr_event_list_t * fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t status, void *status_uctx)
Initialise a new event list.
Stores all information relating to an event list.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
A time delta, a difference in time measured in nanoseconds.
static fr_event_list_t * el
int fd
File descriptor if this is a live socket.
char const * fr_strerror(void)
Get the last library error.
static fr_sbuff_err_t char size_t * len