BUG/MINOR: quic: pad Initial pkt with CONNECTION_CLOSE on client

Currently, when connection is closing, only CONNECTION_CLOSE frame is
emitted via qc_prep_pkts()/qc_do_build_pkt(). Also, only the first
registered encryption level is considered while the others are
dismissed. This results in a single packet datagram.

This can cause issues for QUIC client support, as padding is required
for every Initial packet, contrary to server side where only
ack-eliciting packets are eligible. Thus a client must add padding to a
CONNECTION_CLOSE frame on Initial level.

This patch adjusts qc_prep_pkts() to ensure such packet will be
correctly padded on client side. It sets <final_packet> variable which
instructs that if padding is necessary it must be apply immediately on
the current encryption level instead of the last one.

It could appear as unnecessary to pad a CONNECTION_CLOSE packet, as the
peer will enter in draining state when processing it. However, RFC
mandates that a client Initial packet too small must be dropped by the
server, so there is a risk that the CONNECTION_CLOSE is simply discarded
prior to its processing if stored in a too small datagram.

No need to backport as this is a QUIC backend issue only.
This commit is contained in:
Amaury Denoyelle 2025-09-02 09:16:02 +02:00
parent e9b78e3fb1
commit 209a54d539

View file

@ -715,6 +715,12 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
*/
if (probe && (must_ack || (qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED)))
final_packet = 1;
/* If CONNECTION_CLOSE is emitted only a single QEL is considered while the others are dismissed. This
* must be taken into account if padding is required on QUIC client side. Note that this is irrelevant
* for server side as CONNECTION_CLOSE is not ack-eliciting.
*/
else if (qc_is_back(qc) && cc)
final_packet = 1;
pkt_type = quic_enc_level_pkt_type(qc, qel);
cur_pkt = qc_build_pkt(&pos, end, qel, tls_ctx, frms,