From e0c4e43e40390e44614d14817e34b47e1c17d630 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Mon, 1 Aug 2022 10:33:00 +0100 Subject: [PATCH] BIO_sendmmsg/BIO_recvmmsg (API only) Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/18923) --- crypto/bio/bio_cb.c | 22 +++- crypto/bio/bio_err.c | 19 ++++ crypto/bio/bio_lib.c | 94 ++++++++++++++++ crypto/bio/bio_meth.c | 22 ++++ doc/build.info | 6 ++ doc/man3/BIO_meth_new.pod | 27 ++++- doc/man3/BIO_sendmmsg.pod | 220 ++++++++++++++++++++++++++++++++++++++ include/internal/bio.h | 2 + include/openssl/bio.h.in | 58 ++++++++-- include/openssl/bioerr.h | 2 + util/libcrypto.num | 7 ++ util/other.syms | 5 + 12 files changed, 476 insertions(+), 8 deletions(-) create mode 100644 doc/man3/BIO_sendmmsg.pod diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c index 522a05369d..8e4f79ea3c 100644 --- a/crypto/bio/bio_cb.c +++ b/crypto/bio/bio_cb.c @@ -24,6 +24,8 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, char *p; int left; size_t l = 0; + BIO_MMSG_CB_ARGS *args; + long ret_ = ret; if (processed != NULL) l = *processed; @@ -69,6 +71,16 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, BIO_snprintf(p, left, "ctrl(%d) - %s\n", argi, bio->method->name); break; + case BIO_CB_RECVMMSG: + args = (BIO_MMSG_CB_ARGS *)argp; + BIO_snprintf(p, left, "recvmmsg(%zu) - %s", + args->num_msg, bio->method->name); + break; + case BIO_CB_SENDMMSG: + args = (BIO_MMSG_CB_ARGS *)argp; + BIO_snprintf(p, left, "sendmmsg(%zu) - %s", + args->num_msg, bio->method->name); + break; case BIO_CB_RETURN | BIO_CB_READ: BIO_snprintf(p, left, "read return %d processed: %zu\n", ret, l); break; @@ -84,6 +96,14 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, case BIO_CB_RETURN | BIO_CB_CTRL: BIO_snprintf(p, left, "ctrl return %d\n", ret); break; + case BIO_CB_RETURN | BIO_CB_RECVMMSG: + BIO_snprintf(p, left, "recvmmsg processed: %zu\n", len); + ret_ = (long)len; + break; + case BIO_CB_RETURN | BIO_CB_SENDMMSG: + BIO_snprintf(p, left, "sendmmsg processed: %zu\n", len); + ret_ = (long)len; + break; default: BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd); break; @@ -96,7 +116,7 @@ long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len, else fputs(buf, stderr); #endif - return ret; + return ret_; } #ifndef OPENSSL_NO_DEPRECATED_3_0 diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c index 466280b647..87a744ec49 100644 --- a/crypto/bio/bio_err.c +++ b/crypto/bio/bio_err.c @@ -75,6 +75,10 @@ static const ERR_STRING_DATA BIO_str_reasons[] = { {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WRITE_TO_READ_ONLY_BIO), "write to read only BIO"}, {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WSASTARTUP), "WSAStartup"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LOCAL_ADDR_NOT_AVAILABLE), + "local address not available"}, + {ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NON_FATAL), + "non-fatal or transient error"}, {0, NULL} }; @@ -88,3 +92,18 @@ int ossl_err_load_BIO_strings(void) #endif return 1; } + +#ifndef OPENSSL_NO_SOCK + +int BIO_err_is_non_fatal(unsigned int errcode) +{ + if (ERR_SYSTEM_ERROR(errcode)) + return BIO_sock_non_fatal_error(ERR_GET_REASON(errcode)); + else if (ERR_GET_LIB(errcode) == ERR_LIB_BIO + && ERR_GET_REASON(errcode) == BIO_R_NON_FATAL) + return 1; + else + return 0; +} + +#endif diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index b5454f14b2..f6d40b2d1c 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -397,6 +397,100 @@ int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written) || (b != NULL && dlen == 0); /* order is important for *written */ } +int BIO_sendmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + size_t ret; + BIO_MMSG_CB_ARGS args; + + if (b == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (b->method == NULL || b->method->bsendmmsg == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + if (HAS_CALLBACK(b)) { + args.msg = msg; + args.stride = stride; + args.num_msg = num_msg; + args.flags = flags; + args.msgs_processed = msgs_processed; + + ret = (size_t)bio_call_callback(b, BIO_CB_SENDMMSG, (void *)&args, + 0, 0, 0, 0, NULL); + if (ret == 0) + return 0; + } + + if (!b->init) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return 0; + } + + ret = b->method->bsendmmsg(b, msg, stride, num_msg, flags, msgs_processed); + + if (HAS_CALLBACK(b)) + ret = (size_t)bio_call_callback(b, BIO_CB_SENDMMSG | BIO_CB_RETURN, + (void *)&args, ret, 0, 0, 0, NULL); + + return ret; +} + +int BIO_recvmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + size_t ret; + BIO_MMSG_CB_ARGS args; + + if (b == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (b->method == NULL || b->method->brecvmmsg == NULL) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNSUPPORTED_METHOD); + return 0; + } + + if (HAS_CALLBACK(b)) { + args.msg = msg; + args.stride = stride; + args.num_msg = num_msg; + args.flags = flags; + args.msgs_processed = msgs_processed; + + ret = bio_call_callback(b, BIO_CB_RECVMMSG, (void *)&args, + 0, 0, 0, 0, NULL); + if (ret == 0) + return 0; + } + + if (!b->init) { + *msgs_processed = 0; + ERR_raise(ERR_LIB_BIO, BIO_R_UNINITIALIZED); + return 0; + } + + ret = b->method->brecvmmsg(b, msg, stride, num_msg, flags, msgs_processed); + + if (HAS_CALLBACK(b)) + ret = (size_t)bio_call_callback(b, BIO_CB_RECVMMSG | BIO_CB_RETURN, + (void *)&args, ret, 0, 0, 0, NULL); + + return ret; +} + int BIO_puts(BIO *b, const char *buf) { int ret; diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c index 469715ba09..3865d82f0e 100644 --- a/crypto/bio/bio_meth.c +++ b/crypto/bio/bio_meth.c @@ -218,3 +218,25 @@ int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, biom->callback_ctrl = callback_ctrl; return 1; } + +int BIO_meth_set_sendmmsg(BIO_METHOD *biom, + int (*bsendmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *)) +{ + biom->bsendmmsg = bsendmmsg; + return 1; +} + +int (*BIO_meth_get_sendmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *) { + return biom->bsendmmsg; +} + +int BIO_meth_set_recvmmsg(BIO_METHOD *biom, + int (*brecvmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *)) +{ + biom->brecvmmsg = brecvmmsg; + return 1; +} + +int (*BIO_meth_get_recvmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *) { + return biom->brecvmmsg; +} diff --git a/doc/build.info b/doc/build.info index 0977b03023..c029f798ef 100644 --- a/doc/build.info +++ b/doc/build.info @@ -671,6 +671,10 @@ DEPEND[html/man3/BIO_s_socket.html]=man3/BIO_s_socket.pod GENERATE[html/man3/BIO_s_socket.html]=man3/BIO_s_socket.pod DEPEND[man/man3/BIO_s_socket.3]=man3/BIO_s_socket.pod GENERATE[man/man3/BIO_s_socket.3]=man3/BIO_s_socket.pod +DEPEND[html/man3/BIO_sendmmsg.html]=man3/BIO_sendmmsg.pod +GENERATE[html/man3/BIO_sendmmsg.html]=man3/BIO_sendmmsg.pod +DEPEND[man/man3/BIO_sendmmsg.3]=man3/BIO_sendmmsg.pod +GENERATE[man/man3/BIO_sendmmsg.3]=man3/BIO_sendmmsg.pod DEPEND[html/man3/BIO_set_callback.html]=man3/BIO_set_callback.pod GENERATE[html/man3/BIO_set_callback.html]=man3/BIO_set_callback.pod DEPEND[man/man3/BIO_set_callback.3]=man3/BIO_set_callback.pod @@ -2907,6 +2911,7 @@ html/man3/BIO_s_file.html \ html/man3/BIO_s_mem.html \ html/man3/BIO_s_null.html \ html/man3/BIO_s_socket.html \ +html/man3/BIO_sendmmsg.html \ html/man3/BIO_set_callback.html \ html/man3/BIO_should_retry.html \ html/man3/BIO_socket_wait.html \ @@ -3504,6 +3509,7 @@ man/man3/BIO_s_file.3 \ man/man3/BIO_s_mem.3 \ man/man3/BIO_s_null.3 \ man/man3/BIO_s_socket.3 \ +man/man3/BIO_sendmmsg.3 \ man/man3/BIO_set_callback.3 \ man/man3/BIO_should_retry.3 \ man/man3/BIO_socket_wait.3 \ diff --git a/doc/man3/BIO_meth_new.pod b/doc/man3/BIO_meth_new.pod index 86301b9718..5be14b2a28 100644 --- a/doc/man3/BIO_meth_new.pod +++ b/doc/man3/BIO_meth_new.pod @@ -9,7 +9,8 @@ BIO_meth_set_write, BIO_meth_get_read, BIO_meth_set_read, BIO_meth_get_puts, BIO_meth_set_puts, BIO_meth_get_gets, BIO_meth_set_gets, BIO_meth_get_ctrl, BIO_meth_set_ctrl, BIO_meth_get_create, BIO_meth_set_create, BIO_meth_get_destroy, BIO_meth_set_destroy, BIO_meth_get_callback_ctrl, -BIO_meth_set_callback_ctrl - Routines to build up BIO methods +BIO_meth_set_callback_ctrl, BIO_meth_set_sendmmsg, BIO_meth_get_sendmmsg, +BIO_meth_set_recvmmsg, BIO_meth_get_recvmmsg - Routines to build up BIO methods =head1 SYNOPSIS @@ -56,6 +57,25 @@ BIO_meth_set_callback_ctrl - Routines to build up BIO methods int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, long (*callback_ctrl)(BIO *, int, BIO_info_cb *)); + ossl_ssize_t (*BIO_meth_get_sendmmsg(const BIO_METHOD *biom))(BIO *, + BIO_MSG *, + size_t, + size_t, + uint64_t); + int BIO_meth_set_sendmmsg(BIO_METHOD *biom, + ossl_ssize_t (*f) (BIO *, BIO_MSG *, size_t, + size_t, uint64_t)); + + ossl_ssize_t (*BIO_meth_get_recvmmsg(const BIO_METHOD *biom))(BIO *, + BIO_MSG *, + size_t, + size_t, + uint64_t); + int BIO_meth_set_recvmmsg(BIO_METHOD *biom, + ossl_ssize_t (*f) (BIO *, BIO_MSG *, size_t, + size_t, uint64_t)); + + =head1 DESCRIPTION The B type is a structure used for the implementation of new BIO @@ -136,6 +156,11 @@ the L page for more information. This function will be cal in response to the application calling BIO_callback_ctrl(). The parameters for the function have the same meaning as for BIO_callback_ctrl(). +BIO_meth_get_sendmmsg(), BIO_meth_set_sendmmsg(), BIO_meth_get_recvmmsg() and +BIO_meth_set_recvmmsg() get and set the functions used for handling +BIO_sendmmsg() and BIO_recvmmsg() calls respectively. See L for +more information. + =head1 RETURN VALUES BIO_get_new_index() returns the new BIO type value or -1 if an error occurred. diff --git a/doc/man3/BIO_sendmmsg.pod b/doc/man3/BIO_sendmmsg.pod new file mode 100644 index 0000000000..6940847e22 --- /dev/null +++ b/doc/man3/BIO_sendmmsg.pod @@ -0,0 +1,220 @@ +=pod + +=head1 NAME + +BIO_sendmmsg, BIO_recvmmsg, BIO_dgram_set_local_addr_enable, +BIO_dgram_get_local_addr_enable, BIO_dgram_get_local_addr_cap, +BIO_err_is_non_fatal - send and receive multiple datagrams in a single call + +=head1 SYNOPSIS + + #include + + typedef struct bio_msg_st { + void *data; + size_t data_len; + BIO_ADDR *peer, *local; + uint64_t flags; + } BIO_MSG; + + int BIO_sendmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed); + int BIO_recvmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed); + + int BIO_dgram_set_local_addr_enable(BIO *b, int enable); + int BIO_dgram_get_local_addr_enable(BIO *b, int *enable); + int BIO_dgram_get_local_addr_cap(BIO *b); + int BIO_err_is_non_fatal(unsigned int errcode); + +=head1 DESCRIPTION + +BIO_sendmmsg() and BIO_recvmmsg() functions can be used to send and receive +multiple messages in a single call to a BIO. They are analagous to sendmmsg(2) +and recvmmsg(2) on operating systems which provide those functions. + +The B structure provides a subset of the functionality of the B structure defined by POSIX. These functions accept an array of +B structures. On any particular invocation, these functions may process +all of the passed structures, some of them, or none of them. This is indicated +by the value stored in I<*msgs_processed>, which expresses the number of +messages processed. + +The caller should set the I member of a B to a buffer containing +the data to send, or to be filled with a received message. I should be +set to the size of the buffer in bytes. If the given B is processed (in +other words, if the integer returned by the function is greater than or equal to +that B's array index), I will be modified to specify the +actual amount of data sent or received. + +The I field of a B provides input per-message flags to the +invocation. If the invocation processes that B, the I field is +written with output per-message flags, or zero if no such flags are applicable. + +Currently, no input or output per-message flags are defined and this field +should be set to zero before calling BIO_sendmmsg() or BIO_recvmmsg(). + +The I argument to BIO_sendmmsg() and BIO_recvmmsg() provides global +flags which affect the entire invocation. No global flags are currently +defined and this argument should be set to zero. + +When these functions are used to send and receive datagrams, the I field +of a B allows the destination address of sent datagrams to be specified +on a per-datagram basis, and the source address of received datagrams to be +determined. The I field should be set to point to a B, which +will be read by BIO_sendmmsg() and used as the destination address for sent +datagrams, and written by BIO_recvmmsg() with the source address of received +datagrams. + +Similarly, the I field of a B allows the source address of sent +datagrams to be specified on a per-datagram basis, and the destination address +of received datagrams to be determined. Unlike I, support for I +must be explicitly enabled on a B before it can be used; see +BIO_dgram_set_local_addr_enable(). If I is non-NULL in a B and +support for I has not been enabled, processing of that B fails. + +I and I should be set to NULL if they are not required. Support for +I may not be available on all platforms; on these platforms, these +functions always fail if I is non-NULL. + +If I is specified and local address support is enabled, but the operating +system does not report a local address for a specific received message, the +B it points to will be cleared (address family set to C). +This is known to happen on Windows when a packet is received which was sent by +the local system, regardless of whether the packet's destination address was the +loopback address or the IP address of a local non-loopback interface. This is +also known to happen on macOS in some circumstances, such as for packets sent +before local address support was enabled for a receiving socket. These are +OS-specific limitations. As such, users of this API using local address support +should expect to sometimes receive a cleared local B instead of the +correct value. + +The I argument must be set to C. This argument +facilitates backwards compatibility if fields are added to B. Callers +must zero-initialize B. + +I should be sent to the maximum number of messages to send or receive, +which is also the length of the array pointed to by I. + +I must be non-NULL and points to an integer written with the +number of messages successfully processed; see the RETURN VALUES section for +further discussion. + +Unlike most BIO functions, these functions explicitly support multi-threaded +use. Multiple concurrent writers and multiple concurrent readers of the same BIO +are permitted in any combination. As such, these functions do not clear, set, or +otherwise modify BIO retry flags. The return value must be used to determine +whether an operation should be retried; see below. + +The support for concurrent use extends to BIO_sendmmsg() and BIO_recvmmsg() +only, and no other function may be called on a given BIO while any call to +BIO_sendmmsg() or BIO_recvmmsg() is in progress, or vice versa. + +BIO_dgram_set_local_addr_enable() and BIO_dgram_get_local_addr_enable() control +whether local address support is enabled. To enable local address support, call +BIO_dgram_set_local_addr_enable() with an argument of 1. The call will fail if +local address support is not available for the platform. +BIO_dgram_get_local_addr_enable() retrieves the value set by +BIO_dgram_set_local_addr_enable(). + +BIO_dgram_get_local_addr_cap() determines if the B is capable of supporting +local addresses. + +BIO_err_is_non_fatal() determines if a packed error code represents an error +which is transient in nature. + +=head1 NOTES + +Some implementations of the BIO_sendmmsg() and BIO_recvmmsg() BIO methods might +always process at most one message at a time, for example when OS-level +functionality to transmit or receive multiple messages at a time is not +available. + +=head1 RETURN VALUES + +On success, the functions BIO_sendmmsg() and BIO_recvmmsg() return 1 and write +the number of messages successfully processed (which need not be nonzero) to +I. Where a positive value n is written to I, all +entries in the B array from 0 through n-1 inclusive have their +I and I fields updated with the results of the operation on +that message. If the call was to BIO_recvmmsg() and the I or I +fields of that message are non-NULL, the B structures they point to +are written with the relevant address. + +On failure, the functions BIO_sendmmsg() and BIO_recvmmsg() return 0 and write +zero to I. Thus I is always written regardless +of the outcome of the function call. + +If BIO_sendmmsg() and BIO_recvmmsg() fail, they always raise an B +error using L. Any error may be raised, but the following in +particular may be noted: + +=over 2 + +=item B + +The I field was set to a non-NULL value, but local address support is not +available or not enabled on the BIO. + +=item B + +The BIO_sendmmsg() or BIO_recvmmsg() method is not supported on the BIO. + +=item B + +The call failed due to a transient, non-fatal error (for example, because the +BIO is in nonblocking mode and the call would otherwise have blocked). + +Implementations of this interface which do not make system calls and thereby +pass through system error codes using B (for example, memory-based +implementations) should issue this reason code to indicate a transient failure. +However, users of this interface should not test for this reason code directly, +as there are multiple possible packed error codes representing a transient +failure; use BIO_err_is_non_fatal() instead (discussed below). + +=item Socket errors + +OS-level socket errors are reported using an error with library code +B; for a packed error code B where +C, the OS-level socket error code can be +retrieved using C. The packed error code can be +retrieved by calling L after the call to BIO_sendmmsg() +or BIO_recvmmsg() returns 0. + +=item Non-fatal errors + +Whether an error is transient can be determined by passing the packed error code +to BIO_err_is_non_fatal(). Callers should do this instead of testing the reason +code directly, as there are many possible error codes which can indicate a +transient error, many of which are system specific. + +=back + +BIO_dgram_set_local_addr_enable() returns 1 if local address support was +successfully enabled or disabled and 0 otherwise. + +BIO_dgram_get_local_addr_enable() returns 1 if the local address support enable +flag was successfully retrieved. + +BIO_dgram_get_local_addr_cap() returns 1 if the B can support local +addresses. + +BIO_err_is_non_fatal() returns 1 if the passed packed error code represents an +error which is transient in nature. + +=head1 HISTORY + +These functions were added in OpenSSL 3.1. + +=head1 COPYRIGHT + +Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/include/internal/bio.h b/include/internal/bio.h index 547a73d02d..40218e1fb0 100644 --- a/include/internal/bio.h +++ b/include/internal/bio.h @@ -27,6 +27,8 @@ struct bio_method_st { int (*create) (BIO *); int (*destroy) (BIO *); long (*callback_ctrl) (BIO *, int, BIO_info_cb *); + int (*bsendmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *); + int (*brecvmmsg) (BIO *, BIO_MSG *, size_t, size_t, uint64_t, size_t *); }; void bio_free_ex_data(BIO *bio); diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index 1de1790ba7..2bbfc75714 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -172,6 +172,10 @@ extern "C" { # define BIO_CTRL_SET_INDENT 80 # define BIO_CTRL_GET_INDENT 81 +# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP 82 +# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE 83 +# define BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE 84 + # ifndef OPENSSL_NO_KTLS # define BIO_get_ktls_send(b) \ (BIO_ctrl(b, BIO_CTRL_GET_KTLS_SEND, 0, NULL) > 0) @@ -257,12 +261,14 @@ void BIO_clear_flags(BIO *b, int flags); # define BIO_RR_ACCEPT 0x03 /* These are passed by the BIO callback */ -# define BIO_CB_FREE 0x01 -# define BIO_CB_READ 0x02 -# define BIO_CB_WRITE 0x03 -# define BIO_CB_PUTS 0x04 -# define BIO_CB_GETS 0x05 -# define BIO_CB_CTRL 0x06 +# define BIO_CB_FREE 0x01 +# define BIO_CB_READ 0x02 +# define BIO_CB_WRITE 0x03 +# define BIO_CB_PUTS 0x04 +# define BIO_CB_GETS 0x05 +# define BIO_CB_CTRL 0x06 +# define BIO_CB_RECVMMSG 0x07 +# define BIO_CB_SENDMMSG 0x08 /* * The callback is called before and after the underling operation, The @@ -339,6 +345,21 @@ struct bio_dgram_sctp_prinfo { }; # endif +/* BIO_sendmmsg/BIO_recvmmsg-related definitions */ +typedef struct bio_msg_st { + void *data; + size_t data_len; + BIO_ADDR *peer, *local; + uint64_t flags; +} BIO_MSG; + +typedef struct bio_mmsg_cb_args_st { + BIO_MSG *msg; + size_t stride, num_msg; + uint64_t flags; + size_t *msgs_processed; +} BIO_MMSG_CB_ARGS; + /* * #define BIO_CONN_get_param_hostname BIO_ctrl */ @@ -580,6 +601,12 @@ int BIO_ctrl_reset_read_request(BIO *b); (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)(peer)) # define BIO_dgram_get_mtu_overhead(b) \ (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU_OVERHEAD, 0, NULL) +# define BIO_dgram_get_local_addr_cap(b) \ + (int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP, 0, NULL) +# define BIO_dgram_get_local_addr_enable(b, penable) \ + (int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE, 0, (char *)(penable)) +# define BIO_dgram_set_local_addr_enable(b, enable) \ + (int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE, (enable), NULL) /* ctrl macros for BIO_f_prefix */ # define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p)) @@ -622,10 +649,16 @@ void BIO_vfree(BIO *a); int BIO_up_ref(BIO *a); int BIO_read(BIO *b, void *data, int dlen); int BIO_read_ex(BIO *b, void *data, size_t dlen, size_t *readbytes); +__owur int BIO_recvmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed); int BIO_gets(BIO *bp, char *buf, int size); int BIO_get_line(BIO *bio, char *buf, int size); int BIO_write(BIO *b, const void *data, int dlen); int BIO_write_ex(BIO *b, const void *data, size_t dlen, size_t *written); +__owur int BIO_sendmmsg(BIO *b, BIO_MSG *msg, + size_t stride, size_t num_msg, uint64_t flags, + size_t *msgs_processed); int BIO_puts(BIO *bp, const char *buf); int BIO_indent(BIO *b, int indent, int max); long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); @@ -687,6 +720,7 @@ int BIO_dgram_sctp_msg_waiting(BIO *b); # ifndef OPENSSL_NO_SOCK int BIO_sock_should_retry(int i); int BIO_sock_non_fatal_error(int error); +int BIO_err_is_non_fatal(unsigned int errcode); int BIO_socket_wait(int fd, int for_read, time_t max_time); # endif int BIO_wait(BIO *bio, time_t max_time, unsigned int nap_milliseconds); @@ -840,12 +874,24 @@ int BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int)); int BIO_meth_set_write_ex(BIO_METHOD *biom, int (*bwrite) (BIO *, const char *, size_t, size_t *)); +int BIO_meth_set_sendmmsg(BIO_METHOD *biom, + int (*f) (BIO *, BIO_MSG *, size_t, size_t, + uint64_t, size_t *)); +int (*BIO_meth_get_sendmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *, + size_t, size_t, + uint64_t, size_t *); int (*BIO_meth_get_read(const BIO_METHOD *biom)) (BIO *, char *, int); int (*BIO_meth_get_read_ex(const BIO_METHOD *biom)) (BIO *, char *, size_t, size_t *); int BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int)); int BIO_meth_set_read_ex(BIO_METHOD *biom, int (*bread) (BIO *, char *, size_t, size_t *)); +int BIO_meth_set_recvmmsg(BIO_METHOD *biom, + int (*f) (BIO *, BIO_MSG *, size_t, size_t, + uint64_t, size_t *)); +int (*BIO_meth_get_recvmmsg(const BIO_METHOD *biom))(BIO *, BIO_MSG *, + size_t, size_t, + uint64_t, size_t *); int (*BIO_meth_get_puts(const BIO_METHOD *biom)) (BIO *, const char *); int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *)); diff --git a/include/openssl/bioerr.h b/include/openssl/bioerr.h index 67a151dd5c..c707d545fa 100644 --- a/include/openssl/bioerr.h +++ b/include/openssl/bioerr.h @@ -64,5 +64,7 @@ # define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131 # define BIO_R_WRITE_TO_READ_ONLY_BIO 126 # define BIO_R_WSASTARTUP 122 +# define BIO_R_LOCAL_ADDR_NOT_AVAILABLE 148 +# define BIO_R_NON_FATAL 149 #endif diff --git a/util/libcrypto.num b/util/libcrypto.num index 6406849f3f..a078f5c549 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5448,3 +5448,10 @@ CMS_SignedData_verify ? 3_1_0 EXIST::FUNCTION:CMS OPENSSL_strcasecmp ? 3_0_3 EXIST::FUNCTION: OPENSSL_strncasecmp ? 3_0_3 EXIST::FUNCTION: BIO_s_dgram_mem ? 3_1_0 EXIST::FUNCTION: +BIO_recvmmsg ? 3_1_0 EXIST::FUNCTION: +BIO_sendmmsg ? 3_1_0 EXIST::FUNCTION: +BIO_meth_set_sendmmsg ? 3_1_0 EXIST::FUNCTION: +BIO_meth_get_sendmmsg ? 3_1_0 EXIST::FUNCTION: +BIO_meth_set_recvmmsg ? 3_1_0 EXIST::FUNCTION: +BIO_meth_get_recvmmsg ? 3_1_0 EXIST::FUNCTION: +BIO_err_is_non_fatal ? 3_1_0 EXIST::FUNCTION:SOCK diff --git a/util/other.syms b/util/other.syms index 2fe4b67987..77e2a9e0c6 100644 --- a/util/other.syms +++ b/util/other.syms @@ -141,8 +141,13 @@ ASYNC_stack_alloc_fn datatype ASYNC_stack_free_fn datatype # ASN1_BIT_STRING_digest define +BIO_IS_ERRNO define +BIO_UNPACK_ERRNO define BIO_append_filename define BIO_destroy_bio_pair define +BIO_dgram_get_local_addr_cap define +BIO_dgram_get_local_addr_enable define +BIO_dgram_set_local_addr_enable define BIO_do_accept define BIO_do_connect define BIO_do_handshake define