From: Frédéric Lécaille Date: Fri, 10 Feb 2023 13:46:39 +0000 (+0100) Subject: MINOR: quic: Make qc_dgrams_retransmit() return a status. X-Git-Tag: v2.8-dev5~177 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1738df4688b0b44aa62583f311bb1f81e151d9f;p=thirdparty%2Fhaproxy.git MINOR: quic: Make qc_dgrams_retransmit() return a status. This is very helpful during retranmission when receiving ICMP port unreachable errors after the peer has left. This is the unique case at prevent where qc_send_hdshk_pkts() or qc_send_app_probing() may fail (when they call qc_send_ppkts() which fails with ECONNREFUSED as errno). Also make the callers qc_dgrams_retransmit() stop their packet process. This is the case of quic_conn_app_io_cb() and quic_conn_io_cb(). This modifications stops definitively any packet processing when receiving ICMP port unreachable errors. Must be backported to 2.7. --- diff --git a/src/quic_conn.c b/src/quic_conn.c index 0de12f3543..a44c28d057 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -4320,9 +4320,12 @@ int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data, return status; } -/* Retransmit up to two datagrams depending on packet number space */ -static void qc_dgrams_retransmit(struct quic_conn *qc) +/* Retransmit up to two datagrams depending on packet number space. + * Return 0 when failed, 0 if not. + */ +static int qc_dgrams_retransmit(struct quic_conn *qc) { + int ret = 0; struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]; struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]; struct quic_enc_level *aqel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; @@ -4343,8 +4346,9 @@ static void qc_dgrams_retransmit(struct quic_conn *qc) iqel->pktns->tx.pto_probe = 1; if (!LIST_ISEMPTY(&hfrms)) hqel->pktns->tx.pto_probe = 1; - qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms, - QUIC_TLS_ENC_LEVEL_HANDSHAKE, &hfrms); + if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms, + QUIC_TLS_ENC_LEVEL_HANDSHAKE, &hfrms)) + goto leave; /* Put back unsent frames in their packet number spaces */ LIST_SPLICE(&iqel->pktns->tx.frms, &ifrms); LIST_SPLICE(&hqel->pktns->tx.frms, &hfrms); @@ -4367,8 +4371,10 @@ static void qc_dgrams_retransmit(struct quic_conn *qc) TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1); if (!LIST_ISEMPTY(&frms1)) { hqel->pktns->tx.pto_probe = 1; - qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_HANDSHAKE, &frms1, - QUIC_TLS_ENC_LEVEL_NONE, NULL); + if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_HANDSHAKE, &frms1, + QUIC_TLS_ENC_LEVEL_NONE, NULL)) + goto leave; + /* Put back unsent frames into their packet number spaces */ LIST_SPLICE(&hqel->pktns->tx.frms, &frms1); } @@ -4387,13 +4393,16 @@ static void qc_dgrams_retransmit(struct quic_conn *qc) TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms2); if (!LIST_ISEMPTY(&frms1)) { aqel->pktns->tx.pto_probe = 1; - qc_send_app_probing(qc, &frms1); + if (!qc_send_app_probing(qc, &frms1)) + goto leave; + /* Put back unsent frames into their packet number spaces */ LIST_SPLICE(&aqel->pktns->tx.frms, &frms1); } if (!LIST_ISEMPTY(&frms2)) { aqel->pktns->tx.pto_probe = 1; - qc_send_app_probing(qc, &frms2); + if (!qc_send_app_probing(qc, &frms2)) + goto leave; /* Put back unsent frames into their packet number spaces */ LIST_SPLICE(&aqel->pktns->tx.frms, &frms2); } @@ -4402,7 +4411,11 @@ static void qc_dgrams_retransmit(struct quic_conn *qc) aqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED; } } + + ret = 1; + leave: TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc); + return ret; } /* QUIC connection packet handler task (post handshake) */ @@ -4423,7 +4436,8 @@ struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int sta if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) { TRACE_STATE("retransmission needed", QUIC_EV_CONN_IO_CB, qc); qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED; - qc_dgrams_retransmit(qc); + if (!qc_dgrams_retransmit(qc)) + goto out; } if (!LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel)) @@ -4486,7 +4500,8 @@ struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state) if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) { TRACE_DEVEL("retransmission needed", QUIC_EV_CONN_PHPKTS, qc); qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED; - qc_dgrams_retransmit(qc); + if (!qc_dgrams_retransmit(qc)) + goto out; } ssl_err = SSL_ERROR_NONE;