diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index 040809062..0f4ab0bad 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -467,6 +467,16 @@ static inline size_t quic_path_prep_data(struct quic_path *path) return path->cwnd - path->prep_in_flight; } +/* Return the number of bytes which may be sent from connection when + * it has not already been validated. Note that this is the responsability + * of the caller to check that the case with quic_peer_validated_addr(). + * This latter BUG_ON() if 3 * qc->rx.bytes < qc->tx.prep_bytes. + */ +static inline size_t quic_may_send_bytes(struct quic_conn *qc) +{ + return 3 * qc->rx.bytes - qc->tx.prep_bytes; +} + /* CRYPTO data buffer handling functions. */ static inline unsigned char *c_buf_getpos(struct quic_enc_level *qel, uint64_t offset) { diff --git a/src/quic_conn.c b/src/quic_conn.c index 178a14804..5a4fcfaf3 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -149,6 +149,8 @@ int quic_peer_validated_addr(struct quic_conn *qc) qc->state >= QUIC_HS_ST_COMPLETE) return 1; + BUG_ON(qc->tx.prep_bytes > 3 * qc->rx.bytes); + return 0; } diff --git a/src/quic_tx.c b/src/quic_tx.c index 3db0ac341..4f479596e 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -233,7 +233,7 @@ static void qc_prep_fast_retrans(struct quic_conn *qc, * packet size is the packet number. And the maximum increase is 4 bytes. */ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc) && - pkt->len + 4 > 3 * qc->rx.bytes - qc->tx.prep_bytes) { + pkt->len + 4 > quic_may_send_bytes(qc)) { qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED; TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt); goto leave; @@ -298,8 +298,9 @@ void qc_prep_hdshk_fast_retrans(struct quic_conn *qc, */ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) { size_t dglen = pkt->len + 4; - size_t may_send = 3 * qc->rx.bytes - qc->tx.prep_bytes; + size_t may_send; + may_send = quic_may_send_bytes(qc); dglen += pkt->next ? pkt->next->len + 4 : 0; if (dglen > may_send) { qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED; @@ -468,7 +469,7 @@ static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf, /* Leave room for the datagram header */ pos += dg_headlen; if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) { - end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes); + end = pos + QUIC_MIN((uint64_t)qc->path->mtu, quic_may_send_bytes(qc)); } else { end = pos + qc->path->mtu; @@ -1043,7 +1044,7 @@ int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf, struct list *qels) /* Leave room for the datagram header */ pos += dg_headlen; if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) { - end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes); + end = pos + QUIC_MIN((uint64_t)qc->path->mtu, quic_may_send_bytes(qc)); } else { end = pos + qc->path->mtu; @@ -1357,7 +1358,7 @@ int qc_need_sending(struct quic_conn *qc, struct quic_enc_level *qel) int qc_may_probe_ipktns(struct quic_conn *qc) { return quic_peer_validated_addr(qc) || - (int)(3 * qc->rx.bytes - qc->tx.prep_bytes) >= QUIC_INITIAL_PACKET_MINLEN; + quic_may_send_bytes(qc) >= QUIC_INITIAL_PACKET_MINLEN; } /*