BIO_ACCEPT(3)

πŸ“¦ version 4.1.0, in opensuse-leap 16.0

✨ NAME ✨

okay so this is the BIO_ACCEPT(3) page from the Library Functions Manual, and it's serving all the socket-operation wrapper cuties: BIO_get_host_ip, BIO_get_port, BIO_get_accept_socket, BIO_accept, BIO_sock_error, BIO_sock_non_fatal_error, BIO_sock_should_retry, BIO_socket_nbio, and BIO_set_tcp_ndelay β€” literally wrappers for socket operations πŸ’….

πŸ›  SYNOPSIS πŸ› 

bestie, they all come from this include, no cap:

#include <openssl/bio.h>

int
BIO_get_host_ip(const char *hostname, unsigned char *in_addr_buffer);

int
BIO_get_port(const char *servname, unsigned short *port);

int
BIO_get_accept_socket(char *host_port, int bind_mode);

int
BIO_accept(int socket, char **addr);

int
BIO_sock_error(int socket);

int
BIO_sock_non_fatal_error(int errnum);

int
BIO_sock_should_retry(int retval);

int
BIO_socket_nbio(int socket, int mode);

int
BIO_set_tcp_ndelay(int socket, int on);

πŸ’– DESCRIPTION πŸ’–

okay, here's the tea per function, fr fr:

  • BIO_get_host_ip() β€” looks up one IPv4 address for the given hostname using getaddrinfo(3) and writes the first returned IPv4 address into *in_addr_buffer. The caller is responsible for providing a buffer that is at least sizeof(in_addr_t) bytes long. After a successful call, the caller needs to cast in_addr_buffer to (in_addr_t *). buffer sizing is not a vibe to skip πŸ’€
  • BIO_get_port() β€” looks up servname in the services(5) database using getaddrinfo(3) and stores the associated port number at the location specified by the port argument. cute and to the point πŸŽ€
  • BIO_get_accept_socket() β€” creates an IPv4 TCP socket and listen(2)s for incoming connections. The string host_port is parsed. If it contains a colon, the substring before the colon is interpreted as a local hostname of the interface to bind(2) to. If the hostname is empty, consists of a single asterisk ("*:..."), or if there is no colon, INADDR_ANY is used instead of a local hostname. The rest of the string host_port, or the whole string if it contains no colon, is treated as a service name. The hostname and the service name are converted to a local IP address and port number using getaddrinfo(3). If bind_mode is the constant BIO_BIND_REUSEADDR, allowing local address reuse is attempted using setsockopt(2) with an argument of SO_REUSEADDR before calling bind(2). that's a lot of parsing, but she ate πŸ’…
  • BIO_accept() β€” calls accept(2) to receive one connection on the socket. When it receives a connection, it free(3)s *addr, and if it is an IPv4 connection, it allocates a new string, writes the peer IP address in dotted decimal form, a colon, and the decimal port number into the string, and stores a pointer to the string in *addr. For other address families or if getnameinfo(3) or memory allocation fails, *addr is set to NULL but BIO_accept() succeeds anyway. iconic behavior, tbh ✨
  • BIO_sock_error() β€” retrieves, clears, and returns the error status code of the socket by calling getsockopt(2) with arguments SOL_SOCKET and SO_ERROR. very "check the vibes, then clear the vibes" 😭
  • BIO_sock_non_fatal_error() β€” determines whether the error status code errnum represents a recoverable error. lowkey important πŸ¦‹
  • BIO_sock_should_retry() β€” determines whether a recoverable error occurred by inspecting both errno(2) and retval, which is supposed to usually be the return value of a previously called function like BIO_accept(), BIO_read(3), or BIO_write(3). retry energy, but make it informed πŸ”₯
  • BIO_socket_nbio() β€” if mode is non-zero, switches the socket to non-blocking mode using fcntl(2). If mode is 0, it switches to blocking mode. choose your fighter 🫢
  • BIO_set_tcp_ndelay() β€” sets the TCP_NODELAY option on the socket if on is 1 or clears it if on is 0; see tcp(4) for details. tiny flag, big mood ⭐

πŸŽ€ RETURN VALUES πŸŽ€

  • BIO_get_host_ip(), BIO_get_port(), and BIO_socket_nbio() return 1 on success or 0 on failure. simple queen math πŸ’–
  • BIO_get_accept_socket() returns the file descriptor of the newly created listening socket or -1 if host_port is NULL, no service is specified, or getaddrinfo(3), socket(2), bind(2), listen(2), or memory allocation fails. yeah, that's a whole list of possible Ls 😭
  • BIO_accept() returns the file descriptor of the received connection, -1 on fatal errors, that is, when addr is NULL or accept(2) fails fatally, or -2 when accept(2) fails in a non-fatal way and might succeed when retried later. bestie, -2 means "try again later", don't panic πŸ’…
  • BIO_sock_error() returns an error status code like EAGAIN, ECONNABORTED, ECONNREFUSED, ECONNRESET, ELOOP, EMSGSIZE, ENOBUFS, ENOTCONN, EPIPE, ETIMEDOUT, or others, 0 if the socket is not in an error state, or 1 if getsockopt(2) fails. not me memorizing the whole error alphabet πŸ”€πŸ’€
  • BIO_sock_non_fatal_error() returns 1 if errnum is EAGAIN, EALREADY, EINPROGRESS, EINTR, or ENOTCONN and 0 otherwise, even if errnum is 0. yes, even if it's 0 β€” she said what she said πŸŽ€
  • BIO_sock_should_retry() returns 1 if BIO_sock_non_fatal_error(errno) is 1 and retval is either 0 or -1, or 0 otherwise. retry check: passed or not passed, no in-between 🌸
  • BIO_set_tcp_ndelay() returns 0 on success or -1 on failure. short king energy 🫑

🚨 ERRORS 🚨

If BIO_get_host_ip(), BIO_get_port(), or BIO_get_accept_socket() fail or BIO_accept() fails fatally, the following diagnostics can be retrieved with ERR_get_error(3), ERR_GET_REASON(3), and ERR_reason_error_string(3):

  • BIO_R_ACCEPT_ERROR β€” "accept error": accept(2) failed fatally in BIO_accept(). πŸ’€
  • BIO_R_BAD_HOSTNAME_LOOKUP β€” "bad hostname lookup": getaddrinfo(3) failed or hostname was NULL in BIO_get_host_ip(), or getaddrinfo(3) failed in BIO_get_accept_socket(). 🫠
  • BIO_R_INVALID_ARGUMENT β€” "invalid argument": getaddrinfo(3) failed in BIO_get_port(). πŸ™ˆ
  • ERR_R_MALLOC_FAILURE β€” "malloc failure": Memory allocation failed in BIO_get_accept_socket(), or BIO_accept() succeeded but was unable to allocate memory for *addr. For BIO_accept(), the returned file descriptor is valid, and communication with the peer can be attempted using it. okay but the fd still works, so don't spiral 😭✨
  • BIO_R_NO_PORT_SPECIFIED β€” "no port specified": The servname argument was NULL in BIO_get_port(), or host_port was NULL or ended after the first colon in BIO_get_accept_socket(). no port, no party πŸŽ€
  • BIO_R_NULL_PARAMETER β€” "null parameter": The addr argument was NULL in BIO_accept(). bestie WHERE is the addr πŸ’€
  • BIO_R_UNABLE_TO_BIND_SOCKET β€” "unable to bind socket": bind(2) failed in BIO_get_accept_socket(). πŸ’…
  • BIO_R_UNABLE_TO_CREATE_SOCKET β€” "unable to create socket": socket(2) failed in BIO_get_accept_socket(). πŸ˜”
  • BIO_R_UNABLE_TO_LISTEN_SOCKET β€” "unable to listen socket": listen(2) failed in BIO_get_accept_socket(). not listening, literally πŸ™ˆ

πŸ‘€ SEE ALSO πŸ‘€

go say hi to bind(2), connect(2), errno(2), fcntl(2), getsockopt(2), listen(2), sigaction(2), socket(2), BIO_new(3), BIO_read(3), getaddrinfo(3), ip(4), and tcp(4) β€” the whole linked universe is right there πŸŒˆπŸ‘‘

πŸ“œ HISTORY πŸ“œ

  • BIO_sock_should_retry() first appeared in SSLeay 0.6.5, and the other functions except BIO_socket_nbio() in SSLeay 0.8.0. They have all been available since OpenBSD 2.4. vintage but still relevant, iykyk πŸ¦‹
  • BIO_socket_nbio() first appeared in SSLeay 0.9.1 and has been available since OpenBSD 2.6. late arrival, main character energy πŸ‘‘

mwah πŸ’‹ this page is brought to you by Debian, dated April 30, 2023 β€” BIO_ACCEPT(3), signing off 🫢✨

πŸ“¦ where this page comes from