Skip to content

Commit

Permalink
QUIC PORT: Fix BIO_dgram usage under Winsock due to bind requirement
Browse files Browse the repository at this point in the history
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from #22674)
  • Loading branch information
hlandau committed Dec 21, 2023
1 parent ff3a26b commit 3051339
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 0 deletions.
1 change: 1 addition & 0 deletions ssl/quic/quic_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions ssl/quic/quic_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -365,6 +366,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.
Expand Down
6 changes: 6 additions & 0 deletions ssl/quic/quic_port_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3051339

Please sign in to comment.