diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-11-09 15:30:15 +0000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-12-21 08:12:06 +0000 |
commit | 305133988742829f49e4d552f16ef09914317bdb (patch) | |
tree | ce04adf19c05f20f00a300f1b8c8df6f45332d2e | |
parent | ff3a26b24f0bf7f0b24e97453ea138dd167adcb5 (diff) | |
download | openssl-305133988742829f49e4d552f16ef09914317bdb.tar.gz |
QUIC PORT: Fix BIO_dgram usage under Winsock due to bind requirement
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22674)
-rw-r--r-- | ssl/quic/quic_channel.c | 1 | ||||
-rw-r--r-- | ssl/quic/quic_port.c | 20 | ||||
-rw-r--r-- | ssl/quic/quic_port_local.h | 6 |
3 files changed, 27 insertions, 0 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 5bcd66c9e4..60bcc88f84 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -2255,6 +2255,7 @@ static int ch_tx(QUIC_CHANNEL *ch) res = ossl_quic_tx_packetiser_generate(ch->txp, &status); if (status.sent_pkt > 0) { ch->have_sent_any_pkt = 1; /* Packet(s) were sent */ + ch->port->have_sent_any_pkt = 1; /* * RFC 9000 s. 10.1. 'An endpoint also restarts its idle timer when diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index e6dba46bf4..46f4b34f9b 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -323,6 +323,7 @@ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) ch = port_make_channel(port, tls, /*is_server=*/1); port->tserver_ch = ch; + port->is_server = 1; return ch; } @@ -366,6 +367,25 @@ static void port_rx_pre(QUIC_PORT *port) int ret; /* + * Originally, this check (don't RX before we have sent anything if we are + * not a server, because there can't be anything) was just intended as a + * minor optimisation. However, it is actually required on Windows, and + * removing this check will cause Windows to break. + * + * The reason is that under Win32, recvfrom() does not work on a UDP socket + * which has not had bind() called (???). However, calling sendto() will + * automatically bind an unbound UDP socket. Therefore, if we call a Winsock + * recv-type function before calling a Winsock send-type function, that call + * will fail with WSAEINVAL, which we will regard as a permanent network + * error. + * + * Therefore, this check is essential as we do not require our API users to + * bind a socket first when using the API in client mode. + */ + if (!port->is_server && !port->have_sent_any_pkt) + return; + + /* * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams * to the appropriate QRX instances. */ diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 38bb0193d8..968a48ac42 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -87,6 +87,12 @@ struct quic_port_st { /* Inhibit tick for testing purposes? */ unsigned int inhibit_tick : 1; + + /* Has this port sent any packet of any kind yet? */ + unsigned int have_sent_any_pkt : 1; + + /* Does this port allow incoming connections? */ + unsigned int is_server : 1; }; # endif |