25#include <freeradius-devel/bio/fd_priv.h> 
   26#include <freeradius-devel/bio/null.h> 
   33#  define SOL_IP IPPROTO_IP 
   47#  ifdef IPV6_RECVPKTINFO 
   48#    include <linux/version.h> 
   49#    if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) 
   50#      ifdef IPV6_2292PKTINFO 
   51#        undef IPV6_RECVPKTINFO 
   53#        define IPV6_RECVPKTINFO IPV6_2292PKTINFO 
   54#        define IPV6_PKTINFO IPV6_2292PKTINFO 
   58#  elif defined(IPV6_2292PKTINFO) 
   59#      define IPV6_RECVPKTINFO IPV6_2292PKTINFO 
   72#  if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO) 
   73#    define IPV6_RECVPKTINFO IPV6_PKTINFO 
   79#  elif !defined(IPV6_PKTINFO) 
   80#    undef IPV6_RECVPKTINFO 
   84#define ADDR_INIT do { \ 
   85                addr->when = fr_time(); \ 
   86                addr->socket.type = my->info.socket.type; \ 
   87                addr->socket.fd = -1; \ 
   88                addr->socket.inet.ifindex = my->info.socket.inet.ifindex; \ 
 
  101        if (
my->connect.el) {
 
  103                my->connect.el = NULL;
 
 
  128        my->info.write_blocked = 
false;
 
 
  145        rcode = read(
my->info.socket.fd, 
buffer, size);
 
  157                if (rcode < 0) 
return rcode;
 
 
  181        struct sockaddr_storage sockaddr;
 
  183#ifdef STATIC_ANALYZER 
  184        sockaddr = (
struct sockaddr_storage) {};
 
  188        salen = 
sizeof(sockaddr);
 
  190        rcode = recvfrom(
my->info.socket.fd, 
buffer, size, 0, (
struct sockaddr *) &sockaddr, &salen);
 
  193                fr_assert(sockaddr.ss_family == 
my->remote_sockaddr.ss_family);
 
  194                fr_assert((sockaddr.ss_family == AF_INET) || (sockaddr.ss_family == AF_INET6)); 
 
  200        if (rcode == 0) 
return rcode;
 
 
  215        struct sockaddr_storage sockaddr;
 
  218        salen = 
sizeof(sockaddr);
 
  220        rcode = recvfrom(
my->info.socket.fd, 
buffer, size, 0, (
struct sockaddr *) &sockaddr, &salen);
 
  226                addr->
socket.inet.dst_ipaddr = 
my->info.socket.inet.src_ipaddr;
 
  227                addr->
socket.inet.dst_port = 
my->info.socket.inet.src_port;
 
  233        if (rcode == 0) 
return rcode;
 
 
  270        rcode = write(
my->info.socket.fd, 
buffer, size);
 
 
  287        struct sockaddr_storage sockaddr;
 
  298        rcode = sendto(
my->info.socket.fd, 
buffer, size, 0, (
struct sockaddr *) &sockaddr, salen);
 
 
  306#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_PKTINFO) 
  311        struct sockaddr_storage from;
 
  314#ifdef STATIC_ANALYZER 
  315        from.ss_family = AF_UNSPEC;
 
  318        memset(&
my->cbuf, 0, 
sizeof(
my->cbuf));
 
  319        memset(&
my->msgh, 0, 
sizeof(
struct msghdr));
 
  321        my->iov = (
struct iovec) {
 
  326        my->msgh = (
struct msghdr) {
 
  327                .msg_control    = 
my->cbuf,
 
  328                .msg_controllen = 
sizeof(
my->cbuf),
 
  330                .msg_namelen    = 
sizeof(from),
 
  337        rcode = recvmsg(
my->info.socket.fd, &
my->msgh, 0);
 
  342                                               &from, 
my->msgh.msg_namelen);
 
  345        if (rcode == 0) 
return rcode;
 
  353#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) 
  360        struct cmsghdr *cmsg;
 
  365        rcode = fd_fd_recvfromto_common(
my, packet_ctx, 
buffer, size);
 
  366        if (rcode <= 0) 
return rcode;
 
  370        for (cmsg = CMSG_FIRSTHDR(&
my->msgh);
 
  372             cmsg = CMSG_NXTHDR(&
my->msgh, cmsg)) {
 
  376                if ((cmsg->cmsg_level == 
SOL_IP) &&
 
  377                    (cmsg->cmsg_type == IP_PKTINFO)) {
 
  378                        struct in_pktinfo *i = (
struct in_pktinfo *) CMSG_DATA(cmsg);
 
  379                        struct sockaddr_in to;
 
  381                        to.sin_addr = i->ipi_addr;
 
  384                                                       (
struct sockaddr_storage *) &to, 
sizeof(
struct sockaddr_in));
 
  385                        addr->
socket.inet.ifindex = i->ipi_ifindex;
 
  391                if ((cmsg->cmsg_level == IPPROTO_IP) &&
 
  392                    (cmsg->cmsg_type == IP_RECVDSTADDR)) {
 
  393                        struct in_addr *i = (
struct in_addr *) CMSG_DATA(cmsg);
 
  394                        struct sockaddr_in to;
 
  398                                                       (
struct sockaddr_storage *) &to, 
sizeof(
struct sockaddr_in));
 
  404                if ((cmsg->cmsg_level == 
SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMPNS)) {
 
  408#elif defined(SO_TIMESTAMP) 
  409                if ((cmsg->cmsg_level == 
SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMP)) {
 
  424static 
ssize_t fr_bio_fd_sendfromto4(
fr_bio_t *bio, 
void *packet_ctx, const 
void *
buffer, 
size_t size)
 
  428        struct cmsghdr *cmsg;
 
  429        struct sockaddr_storage to;
 
  434        memset(&
my->cbuf, 0, 
sizeof(
my->cbuf));
 
  435        memset(&
my->msgh, 0, 
sizeof(
struct msghdr));
 
  439        my->iov = (
struct iovec) {
 
  444        my->msgh = (
struct msghdr) {
 
  445                .msg_control    = 
my->cbuf,
 
  448                .msg_namelen    = to_len,
 
  456                struct in_pktinfo *pkt;
 
  458                my->msgh.msg_controllen = CMSG_SPACE(
sizeof(*pkt));
 
  460                cmsg = CMSG_FIRSTHDR(&
my->msgh);
 
  461                cmsg->cmsg_level = 
SOL_IP;
 
  462                cmsg->cmsg_type = IP_PKTINFO;
 
  463                cmsg->cmsg_len = CMSG_LEN(
sizeof(*pkt));
 
  465                pkt = (
struct in_pktinfo *) CMSG_DATA(cmsg);
 
  466                memset(pkt, 0, 
sizeof(*pkt));
 
  467                pkt->ipi_spec_dst = addr->
socket.inet.src_ipaddr.addr.v4;
 
  468                pkt->ipi_ifindex = addr->
socket.inet.ifindex;
 
  470#elif defined(IP_SENDSRCADDR) 
  473                my->msgh.msg_controllen = CMSG_SPACE(
sizeof(*
in));
 
  475                cmsg = CMSG_FIRSTHDR(&
my->msgh);
 
  476                cmsg->cmsg_level = IPPROTO_IP;
 
  477                cmsg->cmsg_type = IP_SENDSRCADDR;
 
  478                cmsg->cmsg_len = CMSG_LEN(
sizeof(*
in));
 
  480                in = (
struct in_addr *) CMSG_DATA(cmsg);
 
  481                *
in = addr->
socket.inet.src_ipaddr.addr.v4;
 
  486        rcode = sendmsg(
my->info.socket.fd, &
my->msgh, 0);
 
  493static inline int fr_bio_fd_udpfromto_init4(
int fd)
 
  495        int proto = 0, flag = 0, opt = 1;
 
  497#ifdef HAVE_IP_PKTINFO 
  504#elif defined(IP_RECVDSTADDR) 
  510        flag = IP_RECVDSTADDR;
 
  513        return setsockopt(fd, proto, flag, &opt, 
sizeof(opt));
 
  517#if defined(IPV6_PKTINFO) 
  523        struct cmsghdr *cmsg;
 
  528        rcode = fd_fd_recvfromto_common(
my, packet_ctx, 
buffer, size);
 
  529        if (rcode <= 0) 
return rcode;
 
  533        for (cmsg = CMSG_FIRSTHDR(&
my->msgh);
 
  535             cmsg = CMSG_NXTHDR(&
my->msgh, cmsg)) {
 
  538                if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
 
  539                    (cmsg->cmsg_type == IPV6_PKTINFO)) {
 
  540                        struct in6_pktinfo *i = (
struct in6_pktinfo *) CMSG_DATA(cmsg);
 
  541                        struct sockaddr_in6 to;
 
  543                        to.sin6_addr = i->ipi6_addr;
 
  546                                                       (
struct sockaddr_storage *) &to, 
sizeof(
struct sockaddr_in6));
 
  547                        addr->
socket.inet.ifindex = i->ipi6_ifindex;
 
  552                if ((cmsg->cmsg_level == 
SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMPNS)) {
 
  556#elif defined(SO_TIMESTAMP) 
  557                if ((cmsg->cmsg_level == 
SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMP)) {
 
  572static 
ssize_t fr_bio_fd_sendfromto6(
fr_bio_t *bio, 
void *packet_ctx, const 
void *
buffer, 
size_t size)
 
  576        struct cmsghdr *cmsg;
 
  577        struct sockaddr_storage to;
 
  582        memset(&
my->cbuf, 0, 
sizeof(
my->cbuf));
 
  583        memset(&
my->msgh, 0, 
sizeof(
struct msghdr));
 
  587        my->iov = (
struct iovec) {
 
  592        my->msgh = (
struct msghdr) {
 
  593                .msg_control    = 
my->cbuf,
 
  596                .msg_namelen    = to_len,
 
  603                struct in6_pktinfo *pkt;
 
  605                my->msgh.msg_controllen = CMSG_SPACE(
sizeof(*pkt));
 
  607                cmsg = CMSG_FIRSTHDR(&
my->msgh);
 
  608                cmsg->cmsg_level = IPPROTO_IPV6;
 
  609                cmsg->cmsg_type = IPV6_PKTINFO;
 
  610                cmsg->cmsg_len = CMSG_LEN(
sizeof(*pkt));
 
  612                pkt = (
struct in6_pktinfo *) CMSG_DATA(cmsg);
 
  613                memset(pkt, 0, 
sizeof(*pkt));
 
  614                pkt->ipi6_addr = addr->
socket.inet.src_ipaddr.addr.v6;
 
  615                pkt->ipi6_ifindex = addr->
socket.inet.ifindex;
 
  619        rcode = sendmsg(
my->info.socket.fd, &
my->msgh, 0);
 
  627static inline int fr_bio_fd_udpfromto_init6(
int fd)
 
  631        return setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, 
sizeof(opt));
 
  639        len = strlen(filename);
 
  640        if (len >= 
sizeof(sun->sun_path)) {
 
  641                fr_strerror_const(
"Failed parsing unix domain socket filename: Name is too long");
 
  645        sun->sun_family = AF_LOCAL;
 
  646        memcpy(sun->sun_path, filename, len + 1); 
 
  648        *sunlen = SUN_LEN(sun);
 
 
  656        struct sockaddr_storage salocal;
 
  662            (
my->info.socket.inet.src_port != 0)) {
 
  671        salen = 
sizeof(salocal);
 
  672        memset(&salocal, 0, salen);
 
  673        if (getsockname(
my->info.socket.fd, (
struct sockaddr *) &salocal, &salen) < 0) {
 
  681        my->info.socket.inet.ifindex = 
my->info.socket.inet.src_ipaddr.scope_id;
 
 
  689        my->info.eof = 
false;
 
  690        my->info.read_blocked = 
false;
 
  691        my->info.write_blocked = 
false;
 
  696        if (
my->cb.connected) 
my->cb.connected(&
my->bio);
 
 
  713        if (
my->info.socket.af != AF_LOCAL) {
 
  715                                              &
my->info.socket.inet.dst_ipaddr, 
my->info.socket.inet.dst_port);
 
  718                                                my->info.socket.unix.path);
 
  729        if (connect(
my->info.socket.fd, (
struct sockaddr *) &
my->remote_sockaddr, 
my->remote_sockaddr_len) == 0) {
 
  744                if (tries <= my->max_tries) 
goto retry;
 
  758                if (!
my->info.write_blocked) {
 
  759                        my->info.write_blocked = 
true;
 
  762                        if (rcode < 0) 
return rcode;
 
 
  787        switch (
my->info.cfg->flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
 
 
  835        my->info.eof = 
false;
 
  837        my->info.read_blocked = 
false;
 
  838        my->info.write_blocked = 
false;
 
  851                setsockopt(
my->info.socket.fd, SOL_SOCKET, SO_NOSIGPIPE, &on, 
sizeof(on));
 
  858        if (!
my->info.cfg->async) 
return 0;
 
  861        if (rcode == 0) 
return 0;
 
  863        if (rcode != 
fr_bio_error(IO_WOULD_BLOCK)) 
return rcode;
 
 
  876        if (
my->info.socket.type == SOCK_STREAM) {                              
 
  888#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) 
  889        } 
else if (
my->info.socket.inet.src_ipaddr.af == AF_INET) {             
 
  890                if (fr_bio_fd_udpfromto_init4(
my->info.socket.fd) < 0) 
return -1;
 
  892                my->bio.read = fr_bio_fd_recvfromto4;
 
  893                my->bio.write = fr_bio_fd_sendfromto4;
 
  896#if defined(IPV6_PKTINFO) 
  897        } 
else if (
my->info.socket.inet.src_ipaddr.af == AF_INET6) {            
 
  899                if (fr_bio_fd_udpfromto_init6(
my->info.socket.fd) < 0) 
return -1;
 
  901                my->bio.read = fr_bio_fd_recvfromto6;
 
  902                my->bio.write = fr_bio_fd_sendfromto6;
 
 
  922        if (listen(
my->info.socket.fd, 
my->info.cfg->backlog_is_set ? 
my->info.cfg->backlog : 8) < 0) {
 
 
  970        if (!
my) 
return NULL;
 
  984                        .read_blocked = 
false,
 
  985                        .write_blocked = 
false,
 
 
 1035                (void) shutdown(
my->info.socket.fd, SHUT_RDWR);
 
 1039        rcode = 
close(
my->info.socket.fd);
 
 1045                        if (tries < my->max_tries) 
goto retry;
 
 1057        my->info.read_blocked = 
true;
 
 1058        my->info.write_blocked = 
true;
 
 1059        my->info.eof = 
true;
 
 1060        my->info.socket.fd = -1;
 
 
 1072        my->info.connect_errno = fd_errno;
 
 1074        if (
my->connect.error) {
 
 1075                my->connect.error(&
my->bio);
 
 
 1105                socklen_t socklen = 
sizeof(error);
 
 1120                if (getsockopt(
my->info.socket.fd, SOL_SOCKET, SO_ERROR, (
void *)&error, &socklen) < 0) {
 
 1145        my->connect.el = NULL;
 
 1150        my->connect.success(&
my->bio);
 
 
 1162        my->connect.timeout(&
my->bio);
 
 
 1196                my->info.connect_errno = ECONNABORTED;
 
 1198                my->info.connect_errno = ECONNREFUSED;
 
 1200                if (error_cb) error_cb(bio);
 
 1211                if (connected_cb) connected_cb(bio);
 
 1233        if (!connected_cb) {
 
 1238                        if (error_cb) error_cb(bio);
 
 1253        my->connect.success = connected_cb;
 
 1254        my->connect.error = error_cb;
 
 1255        my->connect.timeout = timeout_cb;
 
 1273        my->connect.el = 
el;
 
 
 1298        rcode = read(
my->info.socket.fd, 
buffer, size);
 
 1299        if (rcode >= 0) 
return 0; 
 
 1302#define flag_blocked read_blocked 
 
 1317        rcode = read(
my->info.socket.fd, 
buffer, size);
 
 1318        if (rcode > 0 ) 
return 0; 
 
 1325#define flag_blocked read_blocked 
 
 1338        switch (
my->info.type) {
 
 1343                if (
my->info.socket.type != SOCK_DGRAM) {
 
 1347                goto set_recv_buff_zero;
 
 1353                if (shutdown(
my->info.socket.fd, SHUT_RD) < 0) {
 
 1368                        if (setsockopt(
my->info.socket.fd, SOL_SOCKET, SO_RCVBUF, &opt, 
sizeof(opt)) < 0) {
 
 
 1390#if !defined(__linux__) && !defined(__FreeBSD__) 
 1391static int inline accept4(
int fd, 
struct sockaddr *sockaddr, socklen_t *salen, 
UNUSED int flags)
 
 1393        fd = accept(fd, sockaddr, salen);
 
 1398                rcode = fcntl(fd, F_GETFD);
 
 1400                        if (fcntl(fd, F_SETFD, rcode | 
FD_CLOEXEC) < 0) {
 
 
 1414#ifndef SOCK_NONBLOCK 
 1415#define SOCK_NONBLOCK 0 
 1419#define SOCK_CLOEXEC 0 
 1432        my->remote_sockaddr_len = 
sizeof(
my->remote_sockaddr);
 
 1438        fd = 
accept4(
parent->info.socket.fd, (
struct sockaddr *) &
my->remote_sockaddr, &
my->remote_sockaddr_len,
 
 1444                if (errno == EINTR) {
 
 1446                        if (tries <= my->max_tries) 
goto retry;
 
 1455        if ((
my->info.socket.af == AF_INET) || (
my->info.socket.af == AF_INET6)) {
 
 1457                                        &
my->remote_sockaddr, 
my->remote_sockaddr_len);
 
 1463        my->info.socket.fd = fd;
 
 1473        if (!
my->info.name) {
 
 
 1504        out->info.cfg = 
my->info.cfg;
 
 1509        out->info.socket = 
my->info.socket;
 
 1511        if (
my->info.socket.type == SOCK_STREAM) {
 
 
static int const char char buffer[256]
fr_bio_write_t _CONST write
write to the underlying bio
fr_bio_read_t _CONST read
read from the underlying bio
static ssize_t fr_bio_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Write raw data to a bio.
static fr_bio_t * fr_bio_head(fr_bio_t *bio)
void(* fr_bio_callback_t)(fr_bio_t *bio)
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define fr_event_fd_insert(...)
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
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()
static ssize_t fr_bio_fd_write(fr_bio_t *bio, UNUSED void *packet_ctx, const void *buffer, size_t size)
Write to fd.
int fr_bio_fd_socket_name(fr_bio_fd_t *my)
static void fr_bio_fd_el_connect(NDEBUG_UNUSED fr_event_list_t *el, NDEBUG_UNUSED int fd, NDEBUG_UNUSED int flags, void *uctx)
Connect callback for when the socket is writable.
static int fr_bio_fd_write_resume(fr_bio_t *bio)
fr_bio_t * fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
Allocate a FD bio.
static ssize_t fr_bio_fd_read_discard_stream(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Discard all reads from a TCP socket.
static int accept4(int fd, struct sockaddr *sockaddr, socklen_t *salen, UNUSED int flags)
int fr_bio_fd_init_connected(fr_bio_fd_t *my)
static ssize_t fr_bio_fd_read_connected_datagram(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Connected datagram read.
static ssize_t fr_bio_fd_try_connect(fr_bio_fd_t *my)
Try to connect().
static ssize_t fr_bio_fd_recvfrom(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read from a UDP socket where we know our IP.
static int fr_bio_fd_eof(fr_bio_t *bio)
static ssize_t fr_bio_fd_sendto(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
Write to a UDP socket where we know our IP.
int fr_filename_to_sockaddr(struct sockaddr_un *sun, socklen_t *sunlen, char const *filename)
int fr_bio_fd_init_listen(fr_bio_fd_t *my)
int fr_bio_fd_accept(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_t *bio)
Accept a new connection on a socket.
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
static int fr_bio_fd_shutdown(fr_bio_t *bio)
Orderly shutdown.
static int fr_bio_fd_accept_stream(fr_bio_fd_t *my, fr_bio_fd_t const *parent)
Accept a stream socket and initialize its flags.
static int fr_bio_fd_init_file(fr_bio_fd_t *my)
Files are a special case of connected sockets.
static void fr_bio_fd_el_timeout(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
We have a timeout on the conenction.
int fr_bio_fd_init_common(fr_bio_fd_t *my)
int fr_bio_fd_write_only(fr_bio_t *bio)
Mark up a bio as write-only.
static ssize_t fr_bio_fd_read_discard_datagram(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Discard all reads from a UDP socket.
static void fr_bio_fd_el_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
FD error when trying to connect, give up on the BIO.
int fr_bio_fd_close(fr_bio_t *bio)
Close the FD, but leave the bio allocated and alive.
static void fr_bio_fd_set_open(fr_bio_fd_t *my)
static ssize_t fr_bio_fd_read_stream(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Stream read.
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
@ FR_BIO_FD_INVALID
not set
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
@ FR_BIO_FD_LISTEN
returns new fd in buffer on fr_bio_read() or fr_bio_fd_accept()
@ FR_BIO_FD_STATE_CONNECTING
@ FR_BIO_FD_STATE_OPEN
error states must be before this
int fr_bio_fd_open(fr_bio_t *bio, fr_bio_fd_config_t const *cfg)
Opens a socket and updates sock->fd.
fr_socket_t socket
socket information, including FD.
Configuration for sockets.
Run-time status of the socket.
void fr_bio_shutdown & my
void fr_bio_fd_name(fr_bio_fd_t *my)
Set the name of an FD BIO.
#define fr_bio_fd_packet_ctx(_my, _packet_ctx)
void fr_ipaddr_get_scope_id(fr_ipaddr_t *ipaddr)
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_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
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.
int fr_bio_write_blocked(fr_bio_t *bio)
Internal BIO function to tell all BIOs that it's blocked.
ssize_t fr_bio_shutdown_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
void fr_bio_eof(fr_bio_t *bio)
Internal BIO function to run EOF callbacks.
int fr_bio_destructor(fr_bio_t *bio)
Free this bio.
ssize_t fr_bio_shutdown_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
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.
int fr_nonblock(UNUSED int fd)
ssize_t fr_bio_null_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Always return 0 on write.
ssize_t fr_bio_null_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always return 0 on read.
ssize_t fr_bio_fail_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always return error on read.
ssize_t fr_bio_fail_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Always return 0 on write.
#define fr_time()
Allow us to arbitrarily manipulate time.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
static fr_time_t fr_time_from_timeval(struct timeval const *when_tv)
Convert a timeval (wallclock time) to a fr_time_t (internal time)
#define fr_time_wrap(_time)
#define fr_time_eq(_a, _b)
static fr_time_t fr_time_from_timespec(struct timespec const *when_ts)
Convert a timespec (wallclock time) to a fr_time_t (internal time)
A time delta, a difference in time measured in nanoseconds.
#define FR_TIMER_DELETE(_ev_p)
static fr_event_list_t * el
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static size_t char ** out