mirror of https://github.com/openssl/openssl.git
BIO_s_dgram_pair
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/18442)
This commit is contained in:
parent
a29ad912b8
commit
b88ce46ee8
|
@ -78,6 +78,8 @@ static const ERR_STRING_DATA BIO_str_reasons[] = {
|
||||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WSASTARTUP), "WSAStartup"},
|
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_WSASTARTUP), "WSAStartup"},
|
||||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LOCAL_ADDR_NOT_AVAILABLE),
|
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_LOCAL_ADDR_NOT_AVAILABLE),
|
||||||
"local address not available"},
|
"local address not available"},
|
||||||
|
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_PEER_ADDR_NOT_AVAILABLE),
|
||||||
|
"peer address not available"},
|
||||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NON_FATAL),
|
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_NON_FATAL),
|
||||||
"non-fatal or transient error"},
|
"non-fatal or transient error"},
|
||||||
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_PORT_MISMATCH),
|
{ERR_PACK(ERR_LIB_BIO, 0, BIO_R_PORT_MISMATCH),
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,7 @@ SOURCE[../../libcrypto]=\
|
||||||
SOURCE[../../libcrypto]=\
|
SOURCE[../../libcrypto]=\
|
||||||
bss_null.c bss_mem.c bss_bio.c bss_fd.c bss_file.c \
|
bss_null.c bss_mem.c bss_bio.c bss_fd.c bss_file.c \
|
||||||
bss_sock.c bss_conn.c bss_acpt.c bss_dgram.c \
|
bss_sock.c bss_conn.c bss_acpt.c bss_dgram.c \
|
||||||
bss_log.c bss_core.c
|
bss_log.c bss_core.c bss_dgram_pair.c
|
||||||
|
|
||||||
# Filters
|
# Filters
|
||||||
SOURCE[../../libcrypto]=\
|
SOURCE[../../libcrypto]=\
|
||||||
|
|
|
@ -146,12 +146,14 @@ BIO_R_LOCAL_ADDR_NOT_AVAILABLE:111:local addr not available
|
||||||
BIO_R_LOOKUP_RETURNED_NOTHING:142:lookup returned nothing
|
BIO_R_LOOKUP_RETURNED_NOTHING:142:lookup returned nothing
|
||||||
BIO_R_MALFORMED_HOST_OR_SERVICE:130:malformed host or service
|
BIO_R_MALFORMED_HOST_OR_SERVICE:130:malformed host or service
|
||||||
BIO_R_NBIO_CONNECT_ERROR:110:nbio connect error
|
BIO_R_NBIO_CONNECT_ERROR:110:nbio connect error
|
||||||
|
BIO_R_NON_FATAL:112:non fatal
|
||||||
BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED:143:\
|
BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED:143:\
|
||||||
no accept addr or service specified
|
no accept addr or service specified
|
||||||
BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED:144:no hostname or service specified
|
BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED:144:no hostname or service specified
|
||||||
BIO_R_NO_PORT_DEFINED:113:no port defined
|
BIO_R_NO_PORT_DEFINED:113:no port defined
|
||||||
BIO_R_NO_SUCH_FILE:128:no such file
|
BIO_R_NO_SUCH_FILE:128:no such file
|
||||||
BIO_R_PORT_MISMATCH:150:port mismatch
|
BIO_R_PORT_MISMATCH:150:port mismatch
|
||||||
|
BIO_R_PEER_ADDR_NOT_AVAILABLE:114:peer addr not available
|
||||||
BIO_R_TFO_DISABLED:106:tfo disabled
|
BIO_R_TFO_DISABLED:106:tfo disabled
|
||||||
BIO_R_TFO_NO_KERNEL_SUPPORT:108:tfo no kernel support
|
BIO_R_TFO_NO_KERNEL_SUPPORT:108:tfo no kernel support
|
||||||
BIO_R_TRANSFER_ERROR:104:transfer error
|
BIO_R_TRANSFER_ERROR:104:transfer error
|
||||||
|
|
|
@ -651,6 +651,10 @@ DEPEND[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod
|
||||||
GENERATE[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod
|
GENERATE[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod
|
||||||
DEPEND[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
|
DEPEND[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
|
||||||
GENERATE[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
|
GENERATE[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod
|
||||||
|
DEPEND[html/man3/BIO_s_dgram_pair.html]=man3/BIO_s_dgram_pair.pod
|
||||||
|
GENERATE[html/man3/BIO_s_dgram_pair.html]=man3/BIO_s_dgram_pair.pod
|
||||||
|
DEPEND[man/man3/BIO_s_dgram_pair.3]=man3/BIO_s_dgram_pair.pod
|
||||||
|
GENERATE[man/man3/BIO_s_dgram_pair.3]=man3/BIO_s_dgram_pair.pod
|
||||||
DEPEND[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
|
DEPEND[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
|
||||||
GENERATE[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
|
GENERATE[html/man3/BIO_s_fd.html]=man3/BIO_s_fd.pod
|
||||||
DEPEND[man/man3/BIO_s_fd.3]=man3/BIO_s_fd.pod
|
DEPEND[man/man3/BIO_s_fd.3]=man3/BIO_s_fd.pod
|
||||||
|
@ -2914,6 +2918,7 @@ html/man3/BIO_s_accept.html \
|
||||||
html/man3/BIO_s_bio.html \
|
html/man3/BIO_s_bio.html \
|
||||||
html/man3/BIO_s_connect.html \
|
html/man3/BIO_s_connect.html \
|
||||||
html/man3/BIO_s_core.html \
|
html/man3/BIO_s_core.html \
|
||||||
|
html/man3/BIO_s_dgram_pair.html \
|
||||||
html/man3/BIO_s_fd.html \
|
html/man3/BIO_s_fd.html \
|
||||||
html/man3/BIO_s_file.html \
|
html/man3/BIO_s_file.html \
|
||||||
html/man3/BIO_s_mem.html \
|
html/man3/BIO_s_mem.html \
|
||||||
|
@ -3514,6 +3519,7 @@ man/man3/BIO_s_accept.3 \
|
||||||
man/man3/BIO_s_bio.3 \
|
man/man3/BIO_s_bio.3 \
|
||||||
man/man3/BIO_s_connect.3 \
|
man/man3/BIO_s_connect.3 \
|
||||||
man/man3/BIO_s_core.3 \
|
man/man3/BIO_s_core.3 \
|
||||||
|
man/man3/BIO_s_dgram_pair.3 \
|
||||||
man/man3/BIO_s_fd.3 \
|
man/man3/BIO_s_fd.3 \
|
||||||
man/man3/BIO_s_file.3 \
|
man/man3/BIO_s_file.3 \
|
||||||
man/man3/BIO_s_mem.3 \
|
man/man3/BIO_s_mem.3 \
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
BIO_s_dgram_pair, BIO_new_bio_dgram_pair, BIO_dgram_set_no_trunc,
|
||||||
|
BIO_dgram_get_no_trunc, BIO_dgram_get_effective_caps, BIO_dgram_get_caps,
|
||||||
|
BIO_dgram_set_caps, BIO_dgram_set_mtu, BIO_dgram_get_mtu - datagram pair BIO
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
|
||||||
|
const BIO_METHOD *BIO_s_dgram_pair(void);
|
||||||
|
|
||||||
|
int BIO_new_bio_dgram_pair(BIO **bio1, size_t writebuf1,
|
||||||
|
BIO **bio2, size_t writebuf2);
|
||||||
|
int BIO_dgram_set_no_trunc(BIO *bio, int enable);
|
||||||
|
int BIO_dgram_get_no_trunc(BIO *bio);
|
||||||
|
uint32_t BIO_dgram_get_effective_caps(BIO *bio);
|
||||||
|
uint32_t BIO_dgram_get_caps(BIO *bio);
|
||||||
|
int BIO_dgram_set_caps(BIO *bio, uint32_t caps);
|
||||||
|
int BIO_dgram_set_mtu(BIO *bio, unsigned int mtu);
|
||||||
|
unsigned int BIO_dgram_get_mtu(BIO *bio);
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
BIO_s_dgram_pair() returns the method for a BIO datagram pair. A BIO datagram
|
||||||
|
pair is similar to a BIO pair (see L<BIO_s_bio(3)>) but has datagram semantics.
|
||||||
|
Broadly, this means that the length of the buffer passed to a write call will
|
||||||
|
match that retrieved by a read call. If the buffer passed to a read call is too
|
||||||
|
short, the datagram is truncated or the read fails, depending on how the BIO is
|
||||||
|
configured.
|
||||||
|
|
||||||
|
The BIO datagram pair attaches certain metadata to each write, such as source
|
||||||
|
and destination addresses. This information may be retrieved on read.
|
||||||
|
|
||||||
|
A typical application of a BIO datagram pair is to allow an application to keep
|
||||||
|
all datagram network I/O requested by libssl under application control.
|
||||||
|
|
||||||
|
The BIO datagram pair is designed to support multithreaded use where certain
|
||||||
|
restrictions are observed; see THREADING.
|
||||||
|
|
||||||
|
The BIO datagram pair allows each half of a pair to signal to the other half
|
||||||
|
whether they support certain capabilities; see CAPABILITY INDICATION.
|
||||||
|
|
||||||
|
BIO_new_bio_dgram_pair() combines the calls to L<BIO_new(3)>,
|
||||||
|
L<BIO_make_bio_pair(3)> and L<BIO_set_write_buf_size(3)> to create a connected
|
||||||
|
pair of BIOs B<bio1>, B<bio2> with write buffer sizes B<writebuf1> and
|
||||||
|
B<writebuf2>. If either size is zero then the default size is used.
|
||||||
|
|
||||||
|
L<BIO_make_bio_pair(3)> may be used to join two datagram pair BIOs into a pair.
|
||||||
|
The two BIOs must both use the method returned by BIO_s_dgram_pair() and neither
|
||||||
|
of the BIOs may currently be associated in a pair.
|
||||||
|
|
||||||
|
L<BIO_destroy_bio_pair(3)> destroys the association between two connected BIOs.
|
||||||
|
Freeing either half of the pair will automatically destroy the association.
|
||||||
|
|
||||||
|
L<BIO_reset(3)> clears any data in the write buffer of the given BIO. This means
|
||||||
|
that the opposite BIO in the pair will no longer have any data waiting to be
|
||||||
|
read.
|
||||||
|
|
||||||
|
The BIO maintains a fixed size internal write buffer. When the buffer is full,
|
||||||
|
further writes will fail until the buffer is drained via calls to
|
||||||
|
L<BIO_read(3)>. The size of the buffer can be changed using
|
||||||
|
L<BIO_set_write_buf_size(3)> and queried using L<BIO_get_write_buf_size(3)>.
|
||||||
|
|
||||||
|
Note that the write buffer is partially consumed by metadata stored internally
|
||||||
|
which is attached to each datagram, such as source and destination addresses.
|
||||||
|
The size of this overhead is undefined and may change between releases.
|
||||||
|
|
||||||
|
The standard L<BIO_ctrl_pending(3)> call has modified behaviour and returns the
|
||||||
|
size of the next datagram waiting to be read in bytes. An application can use
|
||||||
|
this function to ensure it provides an adequate buffer to a subsequent read
|
||||||
|
call. If no datagram is waiting to be read, zero is returned.
|
||||||
|
|
||||||
|
This BIO does not support sending or receiving zero-length datagrams. Passing a
|
||||||
|
zero-length buffer to BIO_write is treated as a no-op.
|
||||||
|
|
||||||
|
L<BIO_eof(3)> returns 1 only if the given BIO datagram pair BIO is not currently
|
||||||
|
connected to a peer BIO.
|
||||||
|
|
||||||
|
L<BIO_get_write_guarantee(3)> and L<BIO_ctrl_get_write_guarantee(3)> return how
|
||||||
|
large a datagram the next call to L<BIO_write(3)> can accept. If there is not
|
||||||
|
enough space in the write buffer to accept another datagram equal in size to the
|
||||||
|
configured MTU, zero is returned (see below). This is intended to avoid a
|
||||||
|
situation where an application attempts to read a datagram from a network
|
||||||
|
intending to write it to a BIO datagram pair, but where the received datagram
|
||||||
|
ends up being too large to write to the BIO datagram pair.
|
||||||
|
|
||||||
|
BIO_dgram_set_no_trunc() and BIO_ctrl_get_no_trunc() set and retrieve the
|
||||||
|
truncation mode for the given half of a BIO datagram pair. When no-truncate mode
|
||||||
|
is enabled, BIO_read() will fail if the buffer provided is inadequate to hold
|
||||||
|
the next datagram to be read. If no-truncate mode is disabled (the default), the
|
||||||
|
datagram will be silently truncated. This default behaviour maintains
|
||||||
|
compatibility with the semantics of the Berkeley sockets API.
|
||||||
|
|
||||||
|
BIO_dgram_set_mtu() and BIO_dgram_get_mtu() may be used to set an informational
|
||||||
|
MTU value on the BIO datagram pair. If BIO_dgram_set_mtu() is used on a BIO
|
||||||
|
which is currently part of a BIO datagram pair, the MTU value is set on both
|
||||||
|
halves of the pair. The value does not affect the operation of the BIO datagram
|
||||||
|
pair (except for BIO_get_write_guarantee(); see above) but may be used by other
|
||||||
|
code to determine a requested MTU. When a BIO datagram pair BIO is created, the
|
||||||
|
MTU is set to an unspecified but valid value.
|
||||||
|
|
||||||
|
L<BIO_flush(3)> is a no-op.
|
||||||
|
|
||||||
|
=head1 NOTES
|
||||||
|
|
||||||
|
The halves of a BIO datagram pair have independent lifetimes and must be
|
||||||
|
separately freed.
|
||||||
|
|
||||||
|
=head1 THREADING
|
||||||
|
|
||||||
|
L<BIO_recvmmsg(3)>, L<BIO_sendmmsg(3)>, L<BIO_read(3)>, L<BIO_write(3)>,
|
||||||
|
L<BIO_pending(3)>, L<BIO_get_write_guarantee(3)> and L<BIO_flush(3)> may be used
|
||||||
|
by multiple threads simultaneously on the same BIO datagram pair. Specific
|
||||||
|
L<BIO_ctrl(3)> operations (namely BIO_CTRL_PENDING, BIO_CTRL_FLUSH and
|
||||||
|
BIO_C_GET_WRITE_GUARANTEE) may also be used. Invoking any other BIO call, or any
|
||||||
|
other L<BIO_ctrl(3)> operation, on either half of a BIO datagram pair while any
|
||||||
|
other BIO call is also in progress to either half of the same BIO datagram pair
|
||||||
|
results in undefined behaviour.
|
||||||
|
|
||||||
|
=head1 CAPABILITY INDICATION
|
||||||
|
|
||||||
|
The BIO datagram pair can be used to enqueue datagrams which have source and
|
||||||
|
destination addresses attached. It is important that the component consuming one
|
||||||
|
side of a BIO datagram pair understand whether the other side of the pair will
|
||||||
|
honour any source and destination addresses it attaches to each datagram. For
|
||||||
|
example, if datagrams are queued with destination addresses set but simply read
|
||||||
|
by simple calls to L<BIO_read(3)>, the destination addresses will be discarded.
|
||||||
|
|
||||||
|
Each half of a BIO datagram pair can have capability flags set on it which
|
||||||
|
indicate whether source and destination addresses will be honoured by the reader
|
||||||
|
and whether they will be provided by the writer. These capability flags should
|
||||||
|
be set via a call to BIO_dgram_set_caps(), and these capabilities will be
|
||||||
|
reflected in the value returned by BIO_dgram_get_effective_caps() on the
|
||||||
|
opposite BIO. If necessary, the capability value previously set can be retrieved
|
||||||
|
using BIO_dgram_get_caps(). Note that BIO_dgram_set_caps() on a given BIO
|
||||||
|
controls the capabilities advertised to the peer, and
|
||||||
|
BIO_dgram_get_effective_caps() on a given BIO determines the capabilities
|
||||||
|
advertised by the peer of that BIO.
|
||||||
|
|
||||||
|
The following capabilities are available:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item B<BIO_DGRAM_CAP_HANDLES_SRC_ADDR>
|
||||||
|
|
||||||
|
The user of the datagram pair BIO promises to honour source addresses provided
|
||||||
|
with datagrams written to the BIO pair.
|
||||||
|
|
||||||
|
=item B<BIO_DGRAM_CAP_HANDLES_DST_ADDR>
|
||||||
|
|
||||||
|
The user of the datagram pair BIO promises to honour destination addresses provided
|
||||||
|
with datagrams written to the BIO pair.
|
||||||
|
|
||||||
|
=item B<BIO_DGRAM_CAP_PROVIDES_SRC_ADDR>
|
||||||
|
|
||||||
|
The user of the datagram pair BIO advertises the fact that it will provide source
|
||||||
|
addressing information with future writes to the BIO pair, where available.
|
||||||
|
|
||||||
|
=item B<BIO_DGRAM_CAP_PROVIDES_DST_ADDR>
|
||||||
|
|
||||||
|
The user of the datagram pair BIO advertises the fact that it will provide
|
||||||
|
destination addressing information with future writes to the BIO pair, where
|
||||||
|
available.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
If a caller attempts to specify a destination address (for example, using
|
||||||
|
L<BIO_sendmmsg(3)>) and the peer has not advertised the
|
||||||
|
B<BIO_DGRAM_CAP_HANDLES_DST_ADDR> capability, the operation fails. Thus,
|
||||||
|
capability negotiation is mandatory.
|
||||||
|
|
||||||
|
If a caller attempts to specify a source address when writing, or requests a
|
||||||
|
destination address when receiving, and local address support has not been
|
||||||
|
enabled, the operation fails; see L<BIO_dgram_set_local_addr_enable(3)>.
|
||||||
|
|
||||||
|
If a caller attempts to enable local address support using
|
||||||
|
L<BIO_dgram_set_local_addr_enable(3)> and L<BIO_dgram_get_local_addr_cap(3)>
|
||||||
|
does not return 1 (meaning that the peer has not advertised both the
|
||||||
|
B<BIO_DGRAM_CAP_HANDLES_SRC_ADDR> and the B<BIO_DGRAM_CAP_PROVIDES_DST_ADDR>
|
||||||
|
capability), the operation fails.
|
||||||
|
|
||||||
|
B<BIO_DGRAM_CAP_PROVIDES_SRC_ADDR> and B<BIO_DGRAM_CAP_PROVIDES_DST_ADDR>
|
||||||
|
indicate that the application using that half of a BIO datagram pair promises to
|
||||||
|
provide source and destination addresses respectively when writing datagrams to
|
||||||
|
that half of the BIO datagram pair. However, these capability flags do not
|
||||||
|
affect the behaviour of the BIO datagram pair.
|
||||||
|
|
||||||
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
|
BIO_new_bio_dgram_pair() returns 1 on success, with the new BIOs available in
|
||||||
|
B<bio1> and B<bio2>, or 0 on failure, with NULL pointers stored into the
|
||||||
|
locations for B<bio1> and B<bio2>. Check the error stack for more information.
|
||||||
|
|
||||||
|
BIO_dgram_set_no_trunc(), BIO_dgram_set_caps() and BIO_dgram_set_mtu() return 1
|
||||||
|
on success and 0 on failure.
|
||||||
|
|
||||||
|
BIO_dgram_get_no_trunc() returns 1 if no-truncate mode is enabled on a BIO, or 0
|
||||||
|
if no-truncate mode is not enabled or not supported on a given BIO.
|
||||||
|
|
||||||
|
BIO_dgram_get_effective_caps() and BIO_dgram_get_caps() return zero if no
|
||||||
|
capabilities are supported.
|
||||||
|
|
||||||
|
BIO_dgram_get_mtu() returns the MTU value configured on the BIO, or zero if the
|
||||||
|
operation is not supported.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<BIO_s_bio(3)>, L<bio(7)>
|
||||||
|
|
||||||
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
|
Copyright 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<https://www.openssl.org/source/license.html>.
|
||||||
|
|
||||||
|
=cut
|
|
@ -158,6 +158,11 @@ particular may be noted:
|
||||||
The I<local> field was set to a non-NULL value, but local address support is not
|
The I<local> field was set to a non-NULL value, but local address support is not
|
||||||
available or not enabled on the BIO.
|
available or not enabled on the BIO.
|
||||||
|
|
||||||
|
=item B<BIO_R_PEER_ADDR_NOT_AVAILABLE>
|
||||||
|
|
||||||
|
The I<peer> field was set to a non-NULL value, but peer address support is not
|
||||||
|
available on the BIO.
|
||||||
|
|
||||||
=item B<BIO_R_UNSUPPORTED_METHOD>
|
=item B<BIO_R_UNSUPPORTED_METHOD>
|
||||||
|
|
||||||
The BIO_sendmmsg() or BIO_recvmmsg() method is not supported on the BIO.
|
The BIO_sendmmsg() or BIO_recvmmsg() method is not supported on the BIO.
|
||||||
|
|
|
@ -68,6 +68,7 @@ extern "C" {
|
||||||
# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
|
# define BIO_TYPE_DGRAM_SCTP (24|BIO_TYPE_SOURCE_SINK|BIO_TYPE_DESCRIPTOR)
|
||||||
# endif
|
# endif
|
||||||
# define BIO_TYPE_CORE_TO_PROV (25|BIO_TYPE_SOURCE_SINK)
|
# define BIO_TYPE_CORE_TO_PROV (25|BIO_TYPE_SOURCE_SINK)
|
||||||
|
# define BIO_TYPE_DGRAM_PAIR (26|BIO_TYPE_SOURCE_SINK)
|
||||||
|
|
||||||
#define BIO_TYPE_START 128
|
#define BIO_TYPE_START 128
|
||||||
|
|
||||||
|
@ -175,6 +176,17 @@ extern "C" {
|
||||||
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP 82
|
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_CAP 82
|
||||||
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE 83
|
# define BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE 83
|
||||||
# define BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE 84
|
# define BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE 84
|
||||||
|
# define BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS 85
|
||||||
|
# define BIO_CTRL_DGRAM_GET_CAPS 86
|
||||||
|
# define BIO_CTRL_DGRAM_SET_CAPS 87
|
||||||
|
# define BIO_CTRL_DGRAM_GET_NO_TRUNC 88
|
||||||
|
# define BIO_CTRL_DGRAM_SET_NO_TRUNC 89
|
||||||
|
|
||||||
|
# define BIO_DGRAM_CAP_NONE 0U
|
||||||
|
# define BIO_DGRAM_CAP_HANDLES_SRC_ADDR (1U << 0)
|
||||||
|
# define BIO_DGRAM_CAP_HANDLES_DST_ADDR (1U << 1)
|
||||||
|
# define BIO_DGRAM_CAP_PROVIDES_SRC_ADDR (1U << 2)
|
||||||
|
# define BIO_DGRAM_CAP_PROVIDES_DST_ADDR (1U << 3)
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_KTLS
|
# ifndef OPENSSL_NO_KTLS
|
||||||
# define BIO_get_ktls_send(b) \
|
# define BIO_get_ktls_send(b) \
|
||||||
|
@ -607,6 +619,20 @@ int BIO_ctrl_reset_read_request(BIO *b);
|
||||||
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE, 0, (char *)(penable))
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_LOCAL_ADDR_ENABLE, 0, (char *)(penable))
|
||||||
# define BIO_dgram_set_local_addr_enable(b, enable) \
|
# define BIO_dgram_set_local_addr_enable(b, enable) \
|
||||||
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE, (enable), NULL)
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_LOCAL_ADDR_ENABLE, (enable), NULL)
|
||||||
|
# define BIO_dgram_get_effective_caps(b) \
|
||||||
|
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_EFFECTIVE_CAPS, 0, NULL)
|
||||||
|
# define BIO_dgram_get_caps(b) \
|
||||||
|
(uint32_t)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_CAPS, 0, NULL)
|
||||||
|
# define BIO_dgram_set_caps(b, caps) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_CAPS, (long)(caps), NULL)
|
||||||
|
# define BIO_dgram_get_no_trunc(b) \
|
||||||
|
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_NO_TRUNC, 0, NULL)
|
||||||
|
# define BIO_dgram_set_no_trunc(b, enable) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_NO_TRUNC, (enable), NULL)
|
||||||
|
# define BIO_dgram_get_mtu(b) \
|
||||||
|
(unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU, 0, NULL)
|
||||||
|
# define BIO_dgram_set_mtu(b, mtu) \
|
||||||
|
(int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_MTU, (mtu), NULL)
|
||||||
|
|
||||||
/* ctrl macros for BIO_f_prefix */
|
/* ctrl macros for BIO_f_prefix */
|
||||||
# define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
|
# define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p))
|
||||||
|
@ -702,6 +728,7 @@ const BIO_METHOD *BIO_f_nbio_test(void);
|
||||||
const BIO_METHOD *BIO_f_prefix(void);
|
const BIO_METHOD *BIO_f_prefix(void);
|
||||||
const BIO_METHOD *BIO_s_core(void);
|
const BIO_METHOD *BIO_s_core(void);
|
||||||
# ifndef OPENSSL_NO_DGRAM
|
# ifndef OPENSSL_NO_DGRAM
|
||||||
|
const BIO_METHOD *BIO_s_dgram_pair(void);
|
||||||
const BIO_METHOD *BIO_s_datagram(void);
|
const BIO_METHOD *BIO_s_datagram(void);
|
||||||
int BIO_dgram_non_fatal_error(int error);
|
int BIO_dgram_non_fatal_error(int error);
|
||||||
BIO *BIO_new_dgram(int fd, int close_flag);
|
BIO *BIO_new_dgram(int fd, int close_flag);
|
||||||
|
@ -824,6 +851,11 @@ BIO *BIO_new_fd(int fd, int close_flag);
|
||||||
|
|
||||||
int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
|
int BIO_new_bio_pair(BIO **bio1, size_t writebuf1,
|
||||||
BIO **bio2, size_t writebuf2);
|
BIO **bio2, size_t writebuf2);
|
||||||
|
# ifndef OPENSSL_NO_DGRAM
|
||||||
|
int BIO_new_bio_dgram_pair(BIO **bio1, size_t writebuf1,
|
||||||
|
BIO **bio2, size_t writebuf2);
|
||||||
|
# endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
|
* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints.
|
||||||
* Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
|
* Otherwise returns 0 and sets *bio1 and *bio2 to NULL. Size 0 uses default
|
||||||
|
|
|
@ -41,10 +41,12 @@
|
||||||
# define BIO_R_LOOKUP_RETURNED_NOTHING 142
|
# define BIO_R_LOOKUP_RETURNED_NOTHING 142
|
||||||
# define BIO_R_MALFORMED_HOST_OR_SERVICE 130
|
# define BIO_R_MALFORMED_HOST_OR_SERVICE 130
|
||||||
# define BIO_R_NBIO_CONNECT_ERROR 110
|
# define BIO_R_NBIO_CONNECT_ERROR 110
|
||||||
|
# define BIO_R_NON_FATAL 112
|
||||||
# define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143
|
# define BIO_R_NO_ACCEPT_ADDR_OR_SERVICE_SPECIFIED 143
|
||||||
# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
|
# define BIO_R_NO_HOSTNAME_OR_SERVICE_SPECIFIED 144
|
||||||
# define BIO_R_NO_PORT_DEFINED 113
|
# define BIO_R_NO_PORT_DEFINED 113
|
||||||
# define BIO_R_NO_SUCH_FILE 128
|
# define BIO_R_NO_SUCH_FILE 128
|
||||||
|
# define BIO_R_NULL_PARAMETER 115 /* unused */
|
||||||
# define BIO_R_TFO_DISABLED 106
|
# define BIO_R_TFO_DISABLED 106
|
||||||
# define BIO_R_TFO_NO_KERNEL_SUPPORT 108
|
# define BIO_R_TFO_NO_KERNEL_SUPPORT 108
|
||||||
# define BIO_R_TRANSFER_ERROR 104
|
# define BIO_R_TRANSFER_ERROR 104
|
||||||
|
@ -64,7 +66,7 @@
|
||||||
# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
|
# define BIO_R_UNSUPPORTED_PROTOCOL_FAMILY 131
|
||||||
# define BIO_R_WRITE_TO_READ_ONLY_BIO 126
|
# define BIO_R_WRITE_TO_READ_ONLY_BIO 126
|
||||||
# define BIO_R_WSASTARTUP 122
|
# define BIO_R_WSASTARTUP 122
|
||||||
# define BIO_R_NON_FATAL 149
|
|
||||||
# define BIO_R_PORT_MISMATCH 150
|
# define BIO_R_PORT_MISMATCH 150
|
||||||
|
# define BIO_R_PEER_ADDR_NOT_AVAILABLE 151
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
|
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
* 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
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <openssl/bio.h>
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
#include "testutil.h"
|
#include "testutil.h"
|
||||||
#include "internal/sockets.h"
|
#include "internal/sockets.h"
|
||||||
|
|
||||||
|
@ -450,6 +451,299 @@ static int test_bio_dgram(int idx)
|
||||||
bio_dgram_cases[idx].local);
|
bio_dgram_cases[idx].local);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int random_data(const uint32_t *key, uint8_t *data, size_t data_len, size_t offset)
|
||||||
|
{
|
||||||
|
int ret = 0, outl;
|
||||||
|
EVP_CIPHER_CTX *ctx = NULL;
|
||||||
|
EVP_CIPHER *cipher = NULL;
|
||||||
|
static const uint8_t zeroes[2048];
|
||||||
|
uint32_t counter[4] = {0};
|
||||||
|
|
||||||
|
counter[0] = (uint32_t)offset;
|
||||||
|
|
||||||
|
ctx = EVP_CIPHER_CTX_new();
|
||||||
|
if (ctx == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
cipher = EVP_CIPHER_fetch(NULL, "ChaCha20", NULL);
|
||||||
|
if (cipher == NULL)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (EVP_EncryptInit_ex2(ctx, cipher, (uint8_t *)key, (uint8_t *)counter, NULL) == 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
while (data_len > 0) {
|
||||||
|
outl = data_len > sizeof(zeroes) ? (int)sizeof(zeroes) : (int)data_len;
|
||||||
|
if (EVP_EncryptUpdate(ctx, data, &outl, zeroes, outl) != 1)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
data += outl;
|
||||||
|
data_len -= outl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
err:
|
||||||
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
|
EVP_CIPHER_free(cipher);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_bio_dgram_pair(void)
|
||||||
|
{
|
||||||
|
int testresult = 0, blen, mtu1, mtu2, r;
|
||||||
|
BIO *bio1 = NULL, *bio2 = NULL;
|
||||||
|
uint8_t scratch[2048 + 4], scratch2[2048];
|
||||||
|
uint32_t key[8];
|
||||||
|
size_t i, num_dgram, num_processed = 0;
|
||||||
|
BIO_MSG msgs[2] = {0}, rmsgs[2] = {0};
|
||||||
|
BIO_ADDR *addr1 = NULL, *addr2 = NULL, *addr3 = NULL, *addr4 = NULL;
|
||||||
|
struct in_addr in_local;
|
||||||
|
size_t total = 0;
|
||||||
|
const uint32_t ref_caps = BIO_DGRAM_CAP_HANDLES_SRC_ADDR
|
||||||
|
| BIO_DGRAM_CAP_HANDLES_DST_ADDR
|
||||||
|
| BIO_DGRAM_CAP_PROVIDES_SRC_ADDR
|
||||||
|
| BIO_DGRAM_CAP_PROVIDES_DST_ADDR;
|
||||||
|
|
||||||
|
in_local.s_addr = ntohl(0x7f000001);
|
||||||
|
|
||||||
|
for (i = 0; i < OSSL_NELEM(key); ++i)
|
||||||
|
key[i] = test_random();
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
mtu1 = BIO_dgram_get_mtu(bio1);
|
||||||
|
if (!TEST_int_ge(mtu1, 1280))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
mtu2 = BIO_dgram_get_mtu(bio2);
|
||||||
|
if (!TEST_int_ge(mtu2, 1280))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(mtu1, mtu2))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_le(mtu1, sizeof(scratch) - 4))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
for (i = 0;; ++i) {
|
||||||
|
if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), i), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
blen = (*(uint32_t*)scratch) % mtu1;
|
||||||
|
r = BIO_write(bio1, scratch + 4, blen);
|
||||||
|
if (r == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(r, blen))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
total += blen;
|
||||||
|
if (!TEST_size_t_lt(total, 1 * 1024 * 1024))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should be able to fit at least 9 datagrams in default write buffer size
|
||||||
|
* in worst case
|
||||||
|
*/
|
||||||
|
if (!TEST_int_ge(i, 9))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Check we read back the same data */
|
||||||
|
num_dgram = i;
|
||||||
|
for (i = 0; i < num_dgram; ++i) {
|
||||||
|
if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), i), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
blen = (*(uint32_t*)scratch) % mtu1;
|
||||||
|
r = BIO_read(bio2, scratch2, sizeof(scratch2));
|
||||||
|
if (!TEST_int_eq(r, blen))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_mem_eq(scratch + 4, blen, scratch2, blen))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should now be out of data */
|
||||||
|
if (!TEST_int_eq(BIO_read(bio2, scratch2, sizeof(scratch2)), -1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* sendmmsg/recvmmsg */
|
||||||
|
if (!TEST_int_eq(random_data(key, scratch, sizeof(scratch), 0), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
msgs[0].data = scratch;
|
||||||
|
msgs[0].data_len = 19;
|
||||||
|
msgs[1].data = scratch + 19;
|
||||||
|
msgs[1].data_len = 46;
|
||||||
|
|
||||||
|
if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), OSSL_NELEM(msgs), 0,
|
||||||
|
&num_processed))
|
||||||
|
|| !TEST_size_t_eq(num_processed, 2))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rmsgs[0].data = scratch2;
|
||||||
|
rmsgs[0].data_len = 64;
|
||||||
|
rmsgs[1].data = scratch2 + 64;
|
||||||
|
rmsgs[1].data_len = 64;
|
||||||
|
if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0,
|
||||||
|
&num_processed))
|
||||||
|
|| !TEST_size_t_eq(num_processed, 2))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len, scratch, 19))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_mem_eq(rmsgs[1].data, rmsgs[1].data_len, scratch + 19, 46))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* sendmmsg/recvmmsg with peer */
|
||||||
|
addr1 = BIO_ADDR_new();
|
||||||
|
if (!TEST_ptr(addr1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_rawmake(addr1, AF_INET, &in_local,
|
||||||
|
sizeof(in_local), 1234), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
addr2 = BIO_ADDR_new();
|
||||||
|
if (!TEST_ptr(addr2))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_rawmake(addr2, AF_INET, &in_local,
|
||||||
|
sizeof(in_local), 2345), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
addr3 = BIO_ADDR_new();
|
||||||
|
if (!TEST_ptr(addr3))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
addr4 = BIO_ADDR_new();
|
||||||
|
if (!TEST_ptr(addr4))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
msgs[0].peer = addr1;
|
||||||
|
|
||||||
|
/* fails due to lack of caps on peer */
|
||||||
|
if (!TEST_false(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), OSSL_NELEM(msgs),
|
||||||
|
0, &num_processed))
|
||||||
|
|| !TEST_size_t_eq(num_processed, 0))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_dgram_set_caps(bio2, ref_caps), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_dgram_get_caps(bio2), ref_caps))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_dgram_get_effective_caps(bio1), ref_caps))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_dgram_get_effective_caps(bio2), 0))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_dgram_set_caps(bio1, ref_caps), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* succeeds with cap now available */
|
||||||
|
if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), 1, 0, &num_processed))
|
||||||
|
|| !TEST_size_t_eq(num_processed, 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* enable local addr support */
|
||||||
|
if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(bio2, 1), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rmsgs[0].data = scratch2;
|
||||||
|
rmsgs[0].data_len = 64;
|
||||||
|
rmsgs[0].peer = addr3;
|
||||||
|
rmsgs[0].local = addr4;
|
||||||
|
if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0,
|
||||||
|
&num_processed))
|
||||||
|
|| !TEST_size_t_eq(num_processed, 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len, msgs[0].data, 19))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* We didn't set the source address so this should be zero */
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_family(addr3), 0))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_family(addr4), AF_INET))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_rawport(addr4), 1234))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* test source address */
|
||||||
|
msgs[0].local = addr2;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_dgram_set_local_addr_enable(bio1, 1), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_true(BIO_sendmmsg(bio1, msgs, sizeof(BIO_MSG), 1, 0, &num_processed))
|
||||||
|
|| !TEST_size_t_eq(num_processed, 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
rmsgs[0].data = scratch2;
|
||||||
|
rmsgs[0].data_len = 64;
|
||||||
|
if (!TEST_true(BIO_recvmmsg(bio2, rmsgs, sizeof(BIO_MSG), OSSL_NELEM(rmsgs), 0, &num_processed))
|
||||||
|
|| !TEST_size_t_eq(num_processed, 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_mem_eq(rmsgs[0].data, rmsgs[0].data_len,
|
||||||
|
msgs[0].data, msgs[0].data_len))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_family(addr3), AF_INET))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_rawport(addr3), 2345))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_family(addr4), AF_INET))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_ADDR_rawport(addr4), 1234))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* test truncation, pending */
|
||||||
|
r = BIO_write(bio1, scratch, 64);
|
||||||
|
if (!TEST_int_eq(r, 64))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
memset(scratch2, 0, 64);
|
||||||
|
if (!TEST_int_eq(BIO_dgram_set_no_trunc(bio2, 1), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_read(bio2, scratch2, 32), -1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_pending(bio2), 64))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_dgram_set_no_trunc(bio2, 0), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(BIO_read(bio2, scratch2, 32), 32))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!TEST_mem_eq(scratch, 32, scratch2, 32))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
testresult = 1;
|
||||||
|
err:
|
||||||
|
BIO_free(bio1);
|
||||||
|
BIO_free(bio2);
|
||||||
|
BIO_ADDR_free(addr1);
|
||||||
|
BIO_ADDR_free(addr2);
|
||||||
|
BIO_ADDR_free(addr3);
|
||||||
|
BIO_ADDR_free(addr4);
|
||||||
|
return testresult;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) */
|
#endif /* !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) */
|
||||||
|
|
||||||
int setup_tests(void)
|
int setup_tests(void)
|
||||||
|
@ -461,6 +755,8 @@ int setup_tests(void)
|
||||||
|
|
||||||
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
|
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
|
||||||
ADD_ALL_TESTS(test_bio_dgram, OSSL_NELEM(bio_dgram_cases));
|
ADD_ALL_TESTS(test_bio_dgram, OSSL_NELEM(bio_dgram_cases));
|
||||||
|
ADD_TEST(test_bio_dgram_pair);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ IF[{- !$disabled{tests} -}]
|
||||||
keymgmt_internal_test hexstr_test provider_status_test defltfips_test \
|
keymgmt_internal_test hexstr_test provider_status_test defltfips_test \
|
||||||
bio_readbuffer_test user_property_test pkcs7_test upcallstest \
|
bio_readbuffer_test user_property_test pkcs7_test upcallstest \
|
||||||
provfetchtest prov_config_test rand_test ca_internals_test \
|
provfetchtest prov_config_test rand_test ca_internals_test \
|
||||||
bio_tfo_test membio_test list_test fips_version_test
|
bio_tfo_test membio_test bio_dgram_test list_test fips_version_test
|
||||||
|
|
||||||
IF[{- !$disabled{'deprecated-3.0'} -}]
|
IF[{- !$disabled{'deprecated-3.0'} -}]
|
||||||
PROGRAMS{noinst}=enginetest
|
PROGRAMS{noinst}=enginetest
|
||||||
|
@ -404,6 +404,10 @@ IF[{- !$disabled{tests} -}]
|
||||||
INCLUDE[membio_test]=../include ../apps/include ..
|
INCLUDE[membio_test]=../include ../apps/include ..
|
||||||
DEPEND[membio_test]=../libcrypto libtestutil.a
|
DEPEND[membio_test]=../libcrypto libtestutil.a
|
||||||
|
|
||||||
|
SOURCE[bio_dgram_test]=bio_dgram_test.c
|
||||||
|
INCLUDE[bio_dgram_test]=../include ../apps/include ..
|
||||||
|
DEPEND[bio_dgram_test]=../libcrypto libtestutil.a
|
||||||
|
|
||||||
SOURCE[params_api_test]=params_api_test.c
|
SOURCE[params_api_test]=params_api_test.c
|
||||||
INCLUDE[params_api_test]=../include ../apps/include
|
INCLUDE[params_api_test]=../include ../apps/include
|
||||||
DEPEND[params_api_test]=../libcrypto libtestutil.a
|
DEPEND[params_api_test]=../libcrypto libtestutil.a
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
#include "internal/tsan_assist.h"
|
#include "internal/tsan_assist.h"
|
||||||
#include "internal/nelem.h"
|
#include "internal/nelem.h"
|
||||||
#include "testutil.h"
|
#include "testutil.h"
|
||||||
|
@ -44,6 +45,8 @@ static const char *default_provider[] = { "default", NULL };
|
||||||
static const char *fips_provider[] = { "fips", NULL };
|
static const char *fips_provider[] = { "fips", NULL };
|
||||||
static const char *fips_and_default_providers[] = { "default", "fips", NULL };
|
static const char *fips_and_default_providers[] = { "default", "fips", NULL };
|
||||||
|
|
||||||
|
static CRYPTO_RWLOCK *global_lock;
|
||||||
|
|
||||||
#ifdef TSAN_REQUIRES_LOCKING
|
#ifdef TSAN_REQUIRES_LOCKING
|
||||||
static CRYPTO_RWLOCK *tsan_lock;
|
static CRYPTO_RWLOCK *tsan_lock;
|
||||||
#endif
|
#endif
|
||||||
|
@ -266,6 +269,19 @@ static void multi_intialise(void)
|
||||||
memset(multi_provider, 0, sizeof(multi_provider));
|
memset(multi_provider, 0, sizeof(multi_provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void multi_set_success(int ok)
|
||||||
|
{
|
||||||
|
if (CRYPTO_THREAD_write_lock(global_lock) == 0) {
|
||||||
|
/* not synchronized, but better than not reporting failure */
|
||||||
|
multi_success = ok;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
multi_success = ok;
|
||||||
|
|
||||||
|
CRYPTO_THREAD_unlock(global_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static void thead_teardown_libctx(void)
|
static void thead_teardown_libctx(void)
|
||||||
{
|
{
|
||||||
OSSL_PROVIDER **p;
|
OSSL_PROVIDER **p;
|
||||||
|
@ -407,7 +423,7 @@ static void thread_general_worker(void)
|
||||||
EVP_CIPHER_free(ciph);
|
EVP_CIPHER_free(ciph);
|
||||||
EVP_PKEY_free(pkey);
|
EVP_PKEY_free(pkey);
|
||||||
if (!testresult)
|
if (!testresult)
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void thread_multi_simple_fetch(void)
|
static void thread_multi_simple_fetch(void)
|
||||||
|
@ -417,7 +433,7 @@ static void thread_multi_simple_fetch(void)
|
||||||
if (md != NULL)
|
if (md != NULL)
|
||||||
EVP_MD_free(md);
|
EVP_MD_free(md);
|
||||||
else
|
else
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static EVP_PKEY *shared_evp_pkey = NULL;
|
static EVP_PKEY *shared_evp_pkey = NULL;
|
||||||
|
@ -466,7 +482,7 @@ static void thread_shared_evp_pkey(void)
|
||||||
err:
|
err:
|
||||||
EVP_PKEY_CTX_free(ctx);
|
EVP_PKEY_CTX_free(ctx);
|
||||||
if (!success)
|
if (!success)
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void thread_provider_load_unload(void)
|
static void thread_provider_load_unload(void)
|
||||||
|
@ -475,7 +491,7 @@ static void thread_provider_load_unload(void)
|
||||||
|
|
||||||
if (!TEST_ptr(deflt)
|
if (!TEST_ptr(deflt)
|
||||||
|| !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default")))
|
|| !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default")))
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
|
|
||||||
OSSL_PROVIDER_unload(deflt);
|
OSSL_PROVIDER_unload(deflt);
|
||||||
}
|
}
|
||||||
|
@ -532,7 +548,7 @@ static void thread_downgrade_shared_evp_pkey(void)
|
||||||
* downgrading
|
* downgrading
|
||||||
*/
|
*/
|
||||||
if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL)
|
if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL)
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_multi_downgrade_shared_pkey(void)
|
static int test_multi_downgrade_shared_pkey(void)
|
||||||
|
@ -588,7 +604,7 @@ static void test_multi_load_worker(void)
|
||||||
|
|
||||||
if (!TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, multi_load_provider))
|
if (!TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, multi_load_provider))
|
||||||
|| !TEST_true(OSSL_PROVIDER_unload(prov)))
|
|| !TEST_true(OSSL_PROVIDER_unload(prov)))
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_multi_default(void)
|
static int test_multi_default(void)
|
||||||
|
@ -644,7 +660,7 @@ static void test_obj_create_one(void)
|
||||||
if (!TEST_int_ne(id, 0)
|
if (!TEST_int_ne(id, 0)
|
||||||
|| !TEST_true(id = OBJ_create(oid, sn, ln))
|
|| !TEST_true(id = OBJ_create(oid, sn, ln))
|
||||||
|| !TEST_true(OBJ_add_sigid(id, NID_sha3_256, NID_rsa)))
|
|| !TEST_true(OBJ_add_sigid(id, NID_sha3_256, NID_rsa)))
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_obj_add(void)
|
static int test_obj_add(void)
|
||||||
|
@ -657,7 +673,7 @@ static int test_obj_add(void)
|
||||||
static void test_lib_ctx_load_config_worker(void)
|
static void test_lib_ctx_load_config_worker(void)
|
||||||
{
|
{
|
||||||
if (!TEST_int_eq(OSSL_LIB_CTX_load_config(multi_libctx, config_file), 1))
|
if (!TEST_int_eq(OSSL_LIB_CTX_load_config(multi_libctx, config_file), 1))
|
||||||
multi_success = 0;
|
multi_set_success(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int test_lib_ctx_load_config(void)
|
static int test_lib_ctx_load_config(void)
|
||||||
|
@ -667,6 +683,64 @@ static int test_lib_ctx_load_config(void)
|
||||||
1, default_provider);
|
1, default_provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
|
||||||
|
static BIO *multi_bio1, *multi_bio2;
|
||||||
|
|
||||||
|
static void test_bio_dgram_pair_worker(void)
|
||||||
|
{
|
||||||
|
ossl_unused int r;
|
||||||
|
int ok = 0;
|
||||||
|
uint8_t ch = 0;
|
||||||
|
uint8_t scratch[64];
|
||||||
|
BIO_MSG msg = {0};
|
||||||
|
size_t num_processed = 0;
|
||||||
|
|
||||||
|
if (!TEST_int_eq(RAND_bytes_ex(multi_libctx, &ch, 1, 64), 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
msg.data = scratch;
|
||||||
|
msg.data_len = sizeof(scratch);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We do not test for failure here as recvmmsg may fail if no sendmmsg
|
||||||
|
* has been called yet. The purpose of this code is to exercise tsan.
|
||||||
|
*/
|
||||||
|
if (ch & 2)
|
||||||
|
r = BIO_sendmmsg(ch & 1 ? multi_bio2 : multi_bio1, &msg,
|
||||||
|
sizeof(BIO_MSG), 1, 0, &num_processed);
|
||||||
|
else
|
||||||
|
r = BIO_recvmmsg(ch & 1 ? multi_bio2 : multi_bio1, &msg,
|
||||||
|
sizeof(BIO_MSG), 1, 0, &num_processed);
|
||||||
|
|
||||||
|
ok = 1;
|
||||||
|
err:
|
||||||
|
if (ok == 0)
|
||||||
|
multi_set_success(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_bio_dgram_pair(void)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
BIO *bio1 = NULL, *bio2 = NULL;
|
||||||
|
|
||||||
|
r = BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0);
|
||||||
|
if (!TEST_int_eq(r, 1))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
multi_bio1 = bio1;
|
||||||
|
multi_bio2 = bio2;
|
||||||
|
|
||||||
|
r = thread_run_test(&test_bio_dgram_pair_worker,
|
||||||
|
MAXIMUM_THREADS, &test_bio_dgram_pair_worker,
|
||||||
|
1, default_provider);
|
||||||
|
|
||||||
|
err:
|
||||||
|
BIO_free(bio1);
|
||||||
|
BIO_free(bio2);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum OPTION_choice {
|
typedef enum OPTION_choice {
|
||||||
OPT_ERR = -1,
|
OPT_ERR = -1,
|
||||||
OPT_EOF = 0,
|
OPT_EOF = 0,
|
||||||
|
@ -713,6 +787,9 @@ int setup_tests(void)
|
||||||
if (!TEST_ptr(privkey))
|
if (!TEST_ptr(privkey))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!TEST_ptr(global_lock = CRYPTO_THREAD_lock_new()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
#ifdef TSAN_REQUIRES_LOCKING
|
#ifdef TSAN_REQUIRES_LOCKING
|
||||||
if (!TEST_ptr(tsan_lock = CRYPTO_THREAD_lock_new()))
|
if (!TEST_ptr(tsan_lock = CRYPTO_THREAD_lock_new()))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -736,6 +813,9 @@ int setup_tests(void)
|
||||||
ADD_TEST(test_multi_load_unload_provider);
|
ADD_TEST(test_multi_load_unload_provider);
|
||||||
ADD_TEST(test_obj_add);
|
ADD_TEST(test_obj_add);
|
||||||
ADD_TEST(test_lib_ctx_load_config);
|
ADD_TEST(test_lib_ctx_load_config);
|
||||||
|
#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
|
||||||
|
ADD_TEST(test_bio_dgram_pair);
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,4 +825,5 @@ void cleanup_tests(void)
|
||||||
#ifdef TSAN_REQUIRES_LOCKING
|
#ifdef TSAN_REQUIRES_LOCKING
|
||||||
CRYPTO_THREAD_lock_free(tsan_lock);
|
CRYPTO_THREAD_lock_free(tsan_lock);
|
||||||
#endif
|
#endif
|
||||||
|
CRYPTO_THREAD_lock_free(global_lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5459,3 +5459,5 @@ BIO_err_is_non_fatal ? 3_1_0 EXIST::FUNCTION:SOCK
|
||||||
X509_get_default_cert_uri ? 3_1_0 EXIST::FUNCTION:
|
X509_get_default_cert_uri ? 3_1_0 EXIST::FUNCTION:
|
||||||
X509_get_default_cert_uri_env ? 3_1_0 EXIST::FUNCTION:
|
X509_get_default_cert_uri_env ? 3_1_0 EXIST::FUNCTION:
|
||||||
X509_get_default_cert_path_env ? 3_1_0 EXIST::FUNCTION:
|
X509_get_default_cert_path_env ? 3_1_0 EXIST::FUNCTION:
|
||||||
|
BIO_s_dgram_pair ? 3_1_0 EXIST::FUNCTION:DGRAM
|
||||||
|
BIO_new_bio_dgram_pair ? 3_1_0 EXIST::FUNCTION:DGRAM
|
||||||
|
|
|
@ -148,6 +148,13 @@ BIO_destroy_bio_pair define
|
||||||
BIO_dgram_get_local_addr_cap define
|
BIO_dgram_get_local_addr_cap define
|
||||||
BIO_dgram_get_local_addr_enable define
|
BIO_dgram_get_local_addr_enable define
|
||||||
BIO_dgram_set_local_addr_enable define
|
BIO_dgram_set_local_addr_enable define
|
||||||
|
BIO_dgram_set_no_trunc define
|
||||||
|
BIO_dgram_get_no_trunc define
|
||||||
|
BIO_dgram_get_caps define
|
||||||
|
BIO_dgram_set_caps define
|
||||||
|
BIO_dgram_get_effective_caps define
|
||||||
|
BIO_dgram_get_mtu define
|
||||||
|
BIO_dgram_set_mtu define
|
||||||
BIO_do_accept define
|
BIO_do_accept define
|
||||||
BIO_do_connect define
|
BIO_do_connect define
|
||||||
BIO_do_handshake define
|
BIO_do_handshake define
|
||||||
|
|
Loading…
Reference in New Issue