summaryrefslogtreecommitdiff
path: root/ssl/quic
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-01-09 15:43:52 +0000
committerHugo Landau <hlandau@openssl.org>2023-01-13 13:20:37 +0000
commit66eab5e08e3a5c7026a3468915ef2e42a43a1479 (patch)
tree9f615f398b8fdc4ef2bd8a0616ec76ec5395f7dc /ssl/quic
parente6b653535f4a0513a1a3710e095411cd45723080 (diff)
downloadopenssl-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.c38
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. */