The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
Macros | Functions
fd.c File Reference

BIO abstractions for file descriptors. More...

#include <freeradius-devel/bio/fd_priv.h>
#include <freeradius-devel/bio/fd_read.h>
#include <freeradius-devel/bio/fd_write.h>
#include <freeradius-devel/bio/null.h>
+ Include dependency graph for fd.c:

Go to the source code of this file.

Macros

#define ADDR_INIT
 
#define fr_bio_fd_no_sigpipe(_x)
 
#define SOCK_CLOEXEC   0
 
#define SOCK_NONBLOCK   0
 
#define SOL_IP   IPPROTO_IP
 

Functions

static int accept4 (int fd, struct sockaddr *sockaddr, socklen_t *salen, UNUSED int flags)
 
int fr_bio_fd_accept (TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_t *bio)
 Accept a new connection on a socket.
 
static int fr_bio_fd_accept_datagram (TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_fd_t *parent)
 Accept a "connection" on a datagram listening socket.
 
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.
 
fr_bio_t * fr_bio_fd_alloc (TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
 Allocate a FD bio.
 
int fr_bio_fd_close (fr_bio_t *bio)
 Close the FD, but leave the bio allocated and alive.
 
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 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 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.
 
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.
 
static int fr_bio_fd_eof (fr_bio_t *bio)
 
fr_bio_fd_info_t const * fr_bio_fd_info (fr_bio_t *bio)
 Returns a pointer to the bio-specific information.
 
int fr_bio_fd_init_common (fr_bio_fd_t *my)
 
int fr_bio_fd_init_connected (fr_bio_fd_t *my)
 
static int fr_bio_fd_init_file (fr_bio_fd_t *my)
 Files are a special case of connected sockets.
 
int fr_bio_fd_init_listen (fr_bio_fd_t *my)
 
static ssize_t fr_bio_fd_notconn_read (UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
 This FD isn't connected.
 
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_read_discard_datagram (fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
 Discard all reads from a UDP socket.
 
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 ssize_t fr_bio_fd_read_first_datagram (fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
 Return the datagram which fr_bio_fd_accept() read from the listening socket.
 
static ssize_t fr_bio_fd_read_stream (fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
 Stream read.
 
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 ssize_t fr_bio_fd_recvmsg_dst (fr_bio_fd_t *parent, uint8_t *buffer, int flags, struct sockaddr_storage *from, socklen_t *from_len, fr_ipaddr_t *dst)
 Receive a datagram, and find the address which the datagram was sent to.
 
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.
 
static void fr_bio_fd_set_open (fr_bio_fd_t *my)
 
static int fr_bio_fd_shutdown (fr_bio_t *bio)
 Orderly shutdown.
 
int fr_bio_fd_socket_name (fr_bio_fd_t *my)
 
static int fr_bio_fd_try_connect (fr_bio_fd_t *my)
 Try to 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_write_only (fr_bio_t *bio)
 Mark up a bio as write-only.
 
static int fr_bio_fd_write_resume (fr_bio_t *bio)
 
int fr_filename_to_sockaddr (struct sockaddr_un *sun, socklen_t *sunlen, char const *filename)
 

Detailed Description

BIO abstractions for file descriptors.

Id
a7762af93055263c2ceed71f06fc8102b6f5d8a4

Definition in file fd.c.

Macro Definition Documentation

◆ ADDR_INIT

#define ADDR_INIT
Value:
do { \
addr->when = fr_time(); \
addr->socket.type = my->info.socket.type; \
addr->socket.fd = -1; \
addr->socket.inet.ifindex = my->info.socket.inet.ifindex; \
} while (0)
#define fr_time()
Definition event.c:58

Definition at line 86 of file fd.c.

◆ fr_bio_fd_no_sigpipe

#define fr_bio_fd_no_sigpipe (   _x)

Definition at line 927 of file fd.c.

◆ SOCK_CLOEXEC

#define SOCK_CLOEXEC   0

Definition at line 1576 of file fd.c.

◆ SOCK_NONBLOCK

#define SOCK_NONBLOCK   0

Definition at line 1572 of file fd.c.

◆ SOL_IP

#define SOL_IP   IPPROTO_IP

Definition at line 35 of file fd.c.

Function Documentation

◆ accept4()

static int accept4 ( int  fd,
struct sockaddr *  sockaddr,
socklen_t *  salen,
UNUSED int  flags 
)
inlinestatic

Definition at line 1552 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_accept()

int fr_bio_fd_accept ( TALLOC_CTX *  ctx,
fr_bio_t **  out_p,
fr_bio_t *  bio 
)

Accept a new connection on a socket.

Definition at line 1858 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_accept_datagram()

static int fr_bio_fd_accept_datagram ( TALLOC_CTX *  ctx,
fr_bio_t **  out_p,
fr_bio_fd_t *  parent 
)
static

Accept a "connection" on a datagram listening socket.

This function is really only useful for DTLS. A datagram socket has no connections, so a connection is made by taking the source IP and port of the first datagram, and opening a new socket which is connected to that peer. The kernel then delivers the datagrams of that peer to the new socket in preference to the listening socket. This only works when the peer sends one stream of datagrams. Other UDP applications can have several datagrams from the same source IP waiting in the listening socket, and those datagrams stay in the listening socket.

The new bio is a copy of the listening bio, except that it is a connected socket. It has its own file descriptor, as connect() is a property of the socket and not of the descriptor, so dup() would connect the listening socket. The new socket needs SO_REUSEPORT, as the new socket is bound to the address which the datagram was sent to, and the port of the listening socket. That address can be more specific than the address of the listening socket, when the listening socket is bound to a wildcard.

The datagram is read directly into a buffer which belongs to the listening bio, and which is allocated once when the listening bio opens. The one read gives the datagram, the source, and the destination. The datagram is out of the socket before the new socket exists, so if the new socket cannot be opened, the datagram is lost. The peer retransmits, as a lost datagram looks like any other lost datagram.

The datagram which named the peer is saved in the new bio. The first read of the new bio returns the saved datagram. The datagram is no longer in the kernel, so no event loop will tell the application that the new socket is readable. info.read_blocked is false, and the application MUST call fr_bio_read() once after fr_bio_fd_accept() returns, and then it can wait for events as usual.

Parameters
[in]ctxto allocate the new bio in.
[out]out_pthe new bio.
[in]parentthe listening datagram bio.
Returns
  • <0 on error
  • 0 for "no datagram is waiting"
  • 1 for "the new bio is available"

Definition at line 1751 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_accept_stream()

static int fr_bio_fd_accept_stream ( fr_bio_fd_t *  my,
fr_bio_fd_t const *  parent 
)
static

Accept a stream socket and initialize its flags.

Definition at line 1583 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_alloc()

fr_bio_t * fr_bio_fd_alloc ( TALLOC_CTX *  ctx,
fr_bio_fd_config_t const *  cfg,
size_t  offset 
)

Allocate a FD bio.

The caller is responsible for tracking the FD, and all associated management of it. The bio API is intended to be simple, and does not provide wrapper functions for various ioctls. The caller should instead do that work.

Once the FD is give to the bio, its lifetime is "owned" by the bio. Calling talloc_free(bio) will close the FD.

The caller can still manage the FD for being readable / writeable. However, the caller should not call this bio directly (unless it is the only one). Instead, the caller should read from / write to the previous bio which will then eventually call this one.

Before updating any event handler readable / writeable callbacks, the caller should check fr_bio_fd_at_eof(). If true, then the handlers should not be inserted. The previous bios should still be called to process any pending data, until they return EOF.

The main purpose of an FD bio is to wrap the FD in a bio container. That, and handling retries on read / write, along with returning EOF as an error instead of zero.

Note that the read / write functions can return partial data. It is the callers responsibility to ensure that any writes continue from where they left off (otherwise dat awill be missing). And any partial reads should go to a memory bio.

If a read returns EOF, then the FD remains open until talloc_free(bio) or fr_bio_fd_close() is called.

The bio caches the cfg pointer, so the configuration has to live at least as long as the bio does. See fr_bio_fd_open().

Parameters
ctxthe talloc ctx
cfgstructure holding the configuration information
offsetonly for unconnected datagram sockets, where fr_bio_fd_packet_ctx_t is stored
Returns
  • NULL on error, memory allocation failed
  • !NULL the bio

Definition at line 1116 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_close()

int fr_bio_fd_close ( fr_bio_t *  bio)

Close the FD, but leave the bio allocated and alive.

Definition at line 1164 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_connect_full()

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()

connect() said "come back when the socket is writeable". It's now writeable, so we check if there was a connection error.

Parameters
biothe binary IO handler
elthe event list
connected_cbcallback to run when the BIO is connected
error_cbcallback to run when the FD has an error
timeoutwhen to time out the connect() attempt
timeout_cbto call when the timeout runs.
Returns
  • <0 on error
  • 0 for "try again later". If callbacks are set, the callbacks will try again. Otherwise the application has to try again.
  • 1 for "we are now connected".

Definition at line 1349 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_el_connect()

static void fr_bio_fd_el_connect ( NDEBUG_UNUSED fr_event_list_t *  el,
NDEBUG_UNUSED int  fd,
NDEBUG_UNUSED int  flags,
void *  uctx 
)
static

Connect callback for when the socket is writable.

We try to connect the socket, and if so, call the application which should update the BIO status.

Definition at line 1229 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_el_error()

static void fr_bio_fd_el_error ( UNUSED fr_event_list_t *  el,
UNUSED int  fd,
UNUSED int  flags,
int  fd_errno,
void *  uctx 
)
static

FD error when trying to connect, give up on the BIO.

Definition at line 1202 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_el_timeout()

static void fr_bio_fd_el_timeout ( UNUSED fr_timer_list_t *  tl,
UNUSED fr_time_t  now,
void *  uctx 
)
static

We have a timeout on the conenction.

Definition at line 1321 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_eof()

static int fr_bio_fd_eof ( fr_bio_t *  bio)
static

Definition at line 123 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_info()

fr_bio_fd_info_t const * fr_bio_fd_info ( fr_bio_t *  bio)

Returns a pointer to the bio-specific information.

Definition at line 1446 of file fd.c.

+ Here is the caller graph for this function:

◆ fr_bio_fd_init_common()

int fr_bio_fd_init_common ( fr_bio_fd_t *  my)

< stream socket

< connected datagram

< we know our IP address

Definition at line 985 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_init_connected()

int fr_bio_fd_init_connected ( fr_bio_fd_t *  my)

Definition at line 930 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_init_file()

static int fr_bio_fd_init_file ( fr_bio_fd_t *  my)
static

Files are a special case of connected sockets.

Definition at line 868 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_init_listen()

int fr_bio_fd_init_listen ( fr_bio_fd_t *  my)

Definition at line 1026 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_notconn_read()

static ssize_t fr_bio_fd_notconn_read ( UNUSED fr_bio_t *  bio,
UNUSED void *  packet_ctx,
UNUSED void *  buffer,
UNUSED size_t  size 
)
static

This FD isn't connected.

Definition at line 902 of file fd.c.

+ Here is the caller graph for this function:

◆ fr_bio_fd_read_connected_datagram()

static ssize_t fr_bio_fd_read_connected_datagram ( fr_bio_t *  bio,
UNUSED void *  packet_ctx,
void *  buffer,
size_t  size 
)
static

Connected datagram read.

The difference between this and stream protocols is that for datagrams. a read of zero means "no packets", where a read of zero on a steam socket means "EOF".

Connected sockets do not update per-packet contexts.

Definition at line 198 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_read_discard_datagram()

static ssize_t fr_bio_fd_read_discard_datagram ( fr_bio_t *  bio,
UNUSED void *  packet_ctx,
void *  buffer,
size_t  size 
)
static

Discard all reads from a UDP socket.

Definition at line 1456 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_read_discard_stream()

static ssize_t fr_bio_fd_read_discard_stream ( fr_bio_t *  bio,
UNUSED void *  packet_ctx,
void *  buffer,
size_t  size 
)
static

Discard all reads from a TCP socket.

Definition at line 1472 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_read_first_datagram()

static ssize_t fr_bio_fd_read_first_datagram ( fr_bio_t *  bio,
UNUSED void *  packet_ctx,
void *  buffer,
size_t  size 
)
static

Return the datagram which fr_bio_fd_accept() read from the listening socket.

fr_bio_fd_accept_datagram() has to read the datagram in order to name the peer, so the datagram is no longer in the socket. The first read returns the saved datagram, and then switches to reading the connected socket.

A datagram which is larger than the buffer is truncated, in the same way as a read of the socket.

Definition at line 237 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_read_stream()

static ssize_t fr_bio_fd_read_stream ( fr_bio_t *  bio,
UNUSED void *  packet_ctx,
void *  buffer,
size_t  size 
)
static

Stream read.

Stream sockets return 0 at EOF.  However, we want to distinguish that from the case of datagram
sockets, which return 0 when there's no data.  So we return 0 to the caller for "no data", but also
call the EOF function to tell all of the related BIOs that we're at EOF.

Definition at line 158 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_recvfrom()

static ssize_t fr_bio_fd_recvfrom ( fr_bio_t *  bio,
void *  packet_ctx,
void *  buffer,
size_t  size 
)
static

Read from a UDP socket where we know our IP.

Definition at line 259 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_recvmsg_dst()

static ssize_t fr_bio_fd_recvmsg_dst ( fr_bio_fd_t *  parent,
uint8_t *  buffer,
int  flags,
struct sockaddr_storage *  from,
socklen_t *  from_len,
fr_ipaddr_t *  dst 
)
static

Receive a datagram, and find the address which the datagram was sent to.

A wildcard listener asks the kernel for the destination address of each datagram, which arrives as a control message. A listener bound to one address has no need of the control message, as every datagram was sent to that address.

Parameters
[in]parentthe listening bio.
[in]bufferof FR_BIO_FD_MAX_DATAGRAM octets.
[in]flagsfor recvmsg().
[out]fromthe source of the datagram.
[out]from_lenlength of the source.
[out]dstthe destination of the datagram. af is AF_UNSPEC when the kernel did not say.
Returns
  • >=0 size of the datagram.
  • <0 on error, with errno set.

Definition at line 1644 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_sendto()

static ssize_t fr_bio_fd_sendto ( fr_bio_t *  bio,
void *  packet_ctx,
const void *  buffer,
size_t  size 
)
static

Write to a UDP socket where we know our IP.

Definition at line 328 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_set_open()

static void fr_bio_fd_set_open ( fr_bio_fd_t *  my)
static

Definition at line 747 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_shutdown()

static int fr_bio_fd_shutdown ( fr_bio_t *  bio)
static

Orderly shutdown.

Definition at line 96 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_socket_name()

int fr_bio_fd_socket_name ( fr_bio_fd_t *  my)

Definition at line 714 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_try_connect()

static int fr_bio_fd_try_connect ( fr_bio_fd_t *  my)
static

Try to connect().

If connect is blocking, we either succeed or error immediately. Otherwise, the caller has to select the socket for writeability, and then call fr_bio_fd_connect() as soon as the socket is writeable.

Definition at line 773 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_write()

static ssize_t fr_bio_fd_write ( fr_bio_t *  bio,
UNUSED void *  packet_ctx,
const void *  buffer,
size_t  size 
)
static

Write to fd.

This function is used for connected sockets, where we ignore the packet_ctx.

Definition at line 293 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_write_only()

int fr_bio_fd_write_only ( fr_bio_t *  bio)

Mark up a bio as write-only.

Definition at line 1493 of file fd.c.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fr_bio_fd_write_resume()

static int fr_bio_fd_write_resume ( fr_bio_t *  bio)
static

Definition at line 144 of file fd.c.

+ Here is the caller graph for this function:

◆ fr_filename_to_sockaddr()

int fr_filename_to_sockaddr ( struct sockaddr_un *  sun,
socklen_t *  sunlen,
char const *  filename 
)

Definition at line 696 of file fd.c.

+ Here is the caller graph for this function: