diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-01-09 15:43:52 +0000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-01-13 13:20:37 +0000 |
commit | 66eab5e08e3a5c7026a3468915ef2e42a43a1479 (patch) | |
tree | 9f615f398b8fdc4ef2bd8a0616ec76ec5395f7dc /ssl/quic | |
parent | e6b653535f4a0513a1a3710e095411cd45723080 (diff) | |
download | openssl-new-66eab5e08e3a5c7026a3468915ef2e42a43a1479.tar.gz |
QUIC DEMUX: Handle network errors explicitly
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19703)
Diffstat (limited to 'ssl/quic')
-rw-r--r-- | ssl/quic/quic_demux.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/ssl/quic/quic_demux.c b/ssl/quic/quic_demux.c index 376a15244e..6d30c1c2b9 100644 --- a/ssl/quic/quic_demux.c +++ b/ssl/quic/quic_demux.c @@ -11,6 +11,7 @@ #include "internal/quic_wire_pkt.h" #include "internal/common.h" #include <openssl/lhash.h> +#include <openssl/err.h> #define URXE_DEMUX_STATE_FREE 0 /* on urx_free list */ #define URXE_DEMUX_STATE_PENDING 1 /* on urx_pending list */ @@ -375,7 +376,10 @@ static int demux_recv(QUIC_DEMUX *demux) assert(urxe->demux_state == URXE_DEMUX_STATE_FREE); if (demux->net_bio == NULL) - return 0; + /* + * If no BIO is plugged in, treat this as no datagram being available. + */ + return QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL; /* * Opportunistically receive as many messages as possible in a single @@ -386,7 +390,7 @@ static int demux_recv(QUIC_DEMUX *demux) if (urxe == NULL) { /* We need at least one URXE to receive into. */ if (!ossl_assert(i > 0)) - return 0; + return QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL; break; } @@ -395,7 +399,7 @@ static int demux_recv(QUIC_DEMUX *demux) urxe = demux_reserve_urxe(demux, urxe, demux->mtu); if (urxe == NULL) /* Allocation error, fail. */ - return 0; + return QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL; /* Ensure we zero any fields added to BIO_MSG at a later date. */ memset(&msg[i], 0, sizeof(BIO_MSG)); @@ -408,9 +412,20 @@ static int demux_recv(QUIC_DEMUX *demux) BIO_ADDR_clear(&urxe->local); } - if (!BIO_recvmmsg(demux->net_bio, msg, sizeof(BIO_MSG), i, 0, &rd)) - return 0; + ERR_set_mark(); + if (!BIO_recvmmsg(demux->net_bio, msg, sizeof(BIO_MSG), i, 0, &rd)) { + if (BIO_err_is_non_fatal(ERR_peek_last_error())) { + /* Transient error, clear the error and stop. */ + ERR_pop_to_mark(); + return QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL; + } else { + /* Non-transient error, do not clear the error. */ + ERR_clear_last_mark(); + return QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL; + } + } + ERR_clear_last_mark(); now = demux->now != NULL ? demux->now(demux->now_arg) : ossl_time_zero(); urxe = ossl_list_urxe_head(&demux->urx_free); @@ -426,7 +441,7 @@ static int demux_recv(QUIC_DEMUX *demux) urxe->demux_state = URXE_DEMUX_STATE_PENDING; } - return 1; + return QUIC_DEMUX_PUMP_RES_OK; } /* Extract destination connection ID from the first packet in a datagram. */ @@ -511,11 +526,11 @@ int ossl_quic_demux_pump(QUIC_DEMUX *demux) if (ossl_list_urxe_head(&demux->urx_pending) == NULL) { ret = demux_ensure_free_urxe(demux, DEMUX_MAX_MSGS_PER_CALL); if (ret != 1) - return 0; + return QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL; ret = demux_recv(demux); - if (ret != 1) - return 0; + if (ret != QUIC_DEMUX_PUMP_RES_OK) + return ret; /* * If demux_recv returned successfully, we should always have something. @@ -523,7 +538,10 @@ int ossl_quic_demux_pump(QUIC_DEMUX *demux) assert(ossl_list_urxe_head(&demux->urx_pending) != NULL); } - return demux_process_pending_urxl(demux); + if (!demux_process_pending_urxl(demux)) + return QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL; + + return QUIC_DEMUX_PUMP_RES_OK; } /* Artificially inject a packet into the demuxer for testing purposes. */ |