From: Amaury Denoyelle Date: Tue, 2 Sep 2025 07:16:02 +0000 (+0200) Subject: BUG/MINOR: quic: pad Initial pkt with CONNECTION_CLOSE on client X-Git-Tag: v3.3-dev8~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=209a54d5394c4104e7ebc6368baaa69869008f75;p=thirdparty%2Fhaproxy.git 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 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. --- diff --git a/src/quic_tx.c b/src/quic_tx.c index 2fd149065..ee354470d 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -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,