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.
This commit is contained in:
Frédéric Lécaille 2023-02-10 14:46:39 +01:00 committed by Amaury Denoyelle
parent 2f531116ed
commit e1738df468

View File

@ -4320,9 +4320,12 @@ int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
return status; return status;
} }
/* Retransmit up to two datagrams depending on packet number space */ /* Retransmit up to two datagrams depending on packet number space.
static void qc_dgrams_retransmit(struct quic_conn *qc) * 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 *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]; struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
struct quic_enc_level *aqel = &qc->els[QUIC_TLS_ENC_LEVEL_APP]; 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; iqel->pktns->tx.pto_probe = 1;
if (!LIST_ISEMPTY(&hfrms)) if (!LIST_ISEMPTY(&hfrms))
hqel->pktns->tx.pto_probe = 1; hqel->pktns->tx.pto_probe = 1;
qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms, if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms,
QUIC_TLS_ENC_LEVEL_HANDSHAKE, &hfrms); QUIC_TLS_ENC_LEVEL_HANDSHAKE, &hfrms))
goto leave;
/* Put back unsent frames in their packet number spaces */ /* Put back unsent frames in their packet number spaces */
LIST_SPLICE(&iqel->pktns->tx.frms, &ifrms); LIST_SPLICE(&iqel->pktns->tx.frms, &ifrms);
LIST_SPLICE(&hqel->pktns->tx.frms, &hfrms); 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); TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
if (!LIST_ISEMPTY(&frms1)) { if (!LIST_ISEMPTY(&frms1)) {
hqel->pktns->tx.pto_probe = 1; hqel->pktns->tx.pto_probe = 1;
qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_HANDSHAKE, &frms1, if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_HANDSHAKE, &frms1,
QUIC_TLS_ENC_LEVEL_NONE, NULL); QUIC_TLS_ENC_LEVEL_NONE, NULL))
goto leave;
/* Put back unsent frames into their packet number spaces */ /* Put back unsent frames into their packet number spaces */
LIST_SPLICE(&hqel->pktns->tx.frms, &frms1); 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); TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms2);
if (!LIST_ISEMPTY(&frms1)) { if (!LIST_ISEMPTY(&frms1)) {
aqel->pktns->tx.pto_probe = 1; 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 */ /* Put back unsent frames into their packet number spaces */
LIST_SPLICE(&aqel->pktns->tx.frms, &frms1); LIST_SPLICE(&aqel->pktns->tx.frms, &frms1);
} }
if (!LIST_ISEMPTY(&frms2)) { if (!LIST_ISEMPTY(&frms2)) {
aqel->pktns->tx.pto_probe = 1; 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 */ /* Put back unsent frames into their packet number spaces */
LIST_SPLICE(&aqel->pktns->tx.frms, &frms2); 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; aqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
} }
} }
ret = 1;
leave:
TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc); TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
return ret;
} }
/* QUIC connection packet handler task (post handshake) */ /* 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) { if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
TRACE_STATE("retransmission needed", QUIC_EV_CONN_IO_CB, qc); TRACE_STATE("retransmission needed", QUIC_EV_CONN_IO_CB, qc);
qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED; 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)) 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) { if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
TRACE_DEVEL("retransmission needed", QUIC_EV_CONN_PHPKTS, qc); TRACE_DEVEL("retransmission needed", QUIC_EV_CONN_PHPKTS, qc);
qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED; qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED;
qc_dgrams_retransmit(qc); if (!qc_dgrams_retransmit(qc))
goto out;
} }
ssl_err = SSL_ERROR_NONE; ssl_err = SSL_ERROR_NONE;