]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Make qc_dgrams_retransmit() return a status.
authorFrédéric Lécaille <flecaille@haproxy.com>
Fri, 10 Feb 2023 13:46:39 +0000 (14:46 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 17 Feb 2023 16:36:30 +0000 (17:36 +0100)
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.

src/quic_conn.c

index 0de12f3543bdc8e76cc19b87b79e8d5df8a1a691..a44c28d05778417a6c5d9ba068de211cedc2c074 100644 (file)
@@ -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;