blob: 5c1d64e694f9d0ddb56c23c500699e1ad177306c [file] [log] [blame]
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001/*
2 * QUIC protocol implementation. Lower layer with internal features implemented
3 * here such as QUIC encryption, idle timeout, acknowledgement and
4 * retransmission.
5 *
6 * Copyright 2020 HAProxy Technologies, Frederic Lecaille <flecaille@haproxy.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 */
14
15#include <haproxy/quic_conn.h>
16
17#define _GNU_SOURCE
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020018#include <stdio.h>
19#include <stdlib.h>
20
21#include <sys/socket.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24
25#include <netinet/tcp.h>
26
27#include <import/ebmbtree.h>
28
29#include <haproxy/buf-t.h>
30#include <haproxy/compat.h>
31#include <haproxy/api.h>
32#include <haproxy/debug.h>
33#include <haproxy/tools.h>
34#include <haproxy/ticks.h>
Amaury Denoyelle162baaf2023-04-03 18:49:39 +020035#include <haproxy/xxhash.h>
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020036
Amaury Denoyelle15c74702023-02-01 10:18:26 +010037#include <haproxy/applet-t.h>
38#include <haproxy/cli.h>
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020039#include <haproxy/connection.h>
40#include <haproxy/fd.h>
41#include <haproxy/freq_ctr.h>
42#include <haproxy/global.h>
43#include <haproxy/h3.h>
44#include <haproxy/hq_interop.h>
45#include <haproxy/log.h>
46#include <haproxy/mux_quic.h>
47#include <haproxy/ncbuf.h>
48#include <haproxy/pipe.h>
49#include <haproxy/proxy.h>
50#include <haproxy/quic_cc.h>
51#include <haproxy/quic_frame.h>
52#include <haproxy/quic_enc.h>
53#include <haproxy/quic_loss.h>
54#include <haproxy/quic_sock.h>
55#include <haproxy/quic_stats.h>
56#include <haproxy/quic_stream.h>
57#include <haproxy/quic_tp.h>
58#include <haproxy/cbuf.h>
59#include <haproxy/proto_quic.h>
60#include <haproxy/quic_tls.h>
61#include <haproxy/ssl_sock.h>
62#include <haproxy/task.h>
Amaury Denoyelle15c74702023-02-01 10:18:26 +010063#include <haproxy/thread.h>
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020064#include <haproxy/trace.h>
65
Amaury Denoyelle15c74702023-02-01 10:18:26 +010066/* incremented by each "show quic". */
67static unsigned int qc_epoch = 0;
68
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +020069/* list of supported QUIC versions by this implementation */
70const struct quic_version quic_versions[] = {
71 {
72 .num = QUIC_PROTOCOL_VERSION_DRAFT_29,
73 .initial_salt = initial_salt_draft_29,
74 .initial_salt_len = sizeof initial_salt_draft_29,
75 .key_label = (const unsigned char *)QUIC_HKDF_KEY_LABEL_V1,
76 .key_label_len = sizeof(QUIC_HKDF_KEY_LABEL_V1) - 1,
77 .iv_label = (const unsigned char *)QUIC_HKDF_IV_LABEL_V1,
78 .iv_label_len = sizeof(QUIC_HKDF_IV_LABEL_V1) - 1,
79 .hp_label = (const unsigned char *)QUIC_HKDF_HP_LABEL_V1,
80 .hp_label_len = sizeof(QUIC_HKDF_HP_LABEL_V1) - 1,
81 .ku_label = (const unsigned char *)QUIC_HKDF_KU_LABEL_V1,
82 .ku_label_len = sizeof(QUIC_HKDF_KU_LABEL_V1) - 1,
83 .retry_tag_key = (const unsigned char *)QUIC_TLS_RETRY_KEY_DRAFT,
84 .retry_tag_nonce = (const unsigned char *)QUIC_TLS_RETRY_NONCE_DRAFT,
85 },
86 {
87 .num = QUIC_PROTOCOL_VERSION_1,
88 .initial_salt = initial_salt_v1,
89 .initial_salt_len = sizeof initial_salt_v1,
90 .key_label = (const unsigned char *)QUIC_HKDF_KEY_LABEL_V1,
91 .key_label_len = sizeof(QUIC_HKDF_KEY_LABEL_V1) - 1,
92 .iv_label = (const unsigned char *)QUIC_HKDF_IV_LABEL_V1,
93 .iv_label_len = sizeof(QUIC_HKDF_IV_LABEL_V1) - 1,
94 .hp_label = (const unsigned char *)QUIC_HKDF_HP_LABEL_V1,
95 .hp_label_len = sizeof(QUIC_HKDF_HP_LABEL_V1) - 1,
96 .ku_label = (const unsigned char *)QUIC_HKDF_KU_LABEL_V1,
97 .ku_label_len = sizeof(QUIC_HKDF_KU_LABEL_V1) - 1,
98 .retry_tag_key = (const unsigned char *)QUIC_TLS_RETRY_KEY_V1,
99 .retry_tag_nonce = (const unsigned char *)QUIC_TLS_RETRY_NONCE_V1,
100 },
101 {
Frédéric Lécaille21c4c9b2023-01-13 16:37:02 +0100102 .num = QUIC_PROTOCOL_VERSION_2,
103 .initial_salt = initial_salt_v2,
104 .initial_salt_len = sizeof initial_salt_v2,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200105 .key_label = (const unsigned char *)QUIC_HKDF_KEY_LABEL_V2,
106 .key_label_len = sizeof(QUIC_HKDF_KEY_LABEL_V2) - 1,
107 .iv_label = (const unsigned char *)QUIC_HKDF_IV_LABEL_V2,
108 .iv_label_len = sizeof(QUIC_HKDF_IV_LABEL_V2) - 1,
109 .hp_label = (const unsigned char *)QUIC_HKDF_HP_LABEL_V2,
110 .hp_label_len = sizeof(QUIC_HKDF_HP_LABEL_V2) - 1,
111 .ku_label = (const unsigned char *)QUIC_HKDF_KU_LABEL_V2,
112 .ku_label_len = sizeof(QUIC_HKDF_KU_LABEL_V2) - 1,
Frédéric Lécaille21c4c9b2023-01-13 16:37:02 +0100113 .retry_tag_key = (const unsigned char *)QUIC_TLS_RETRY_KEY_V2,
114 .retry_tag_nonce = (const unsigned char *)QUIC_TLS_RETRY_NONCE_V2,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200115 },
116};
117
118/* The total number of supported versions */
119const size_t quic_versions_nb = sizeof quic_versions / sizeof *quic_versions;
120/* Listener only preferred version */
121const struct quic_version *preferred_version;
122
123/* trace source and events */
124static void quic_trace(enum trace_level level, uint64_t mask, \
125 const struct trace_source *src,
126 const struct ist where, const struct ist func,
127 const void *a1, const void *a2, const void *a3, const void *a4);
128
129static const struct trace_event quic_trace_events[] = {
130 { .mask = QUIC_EV_CONN_NEW, .name = "new_conn", .desc = "new QUIC connection" },
131 { .mask = QUIC_EV_CONN_INIT, .name = "new_conn_init", .desc = "new QUIC connection initialization" },
132 { .mask = QUIC_EV_CONN_ISEC, .name = "init_secs", .desc = "initial secrets derivation" },
133 { .mask = QUIC_EV_CONN_RSEC, .name = "read_secs", .desc = "read secrets derivation" },
134 { .mask = QUIC_EV_CONN_WSEC, .name = "write_secs", .desc = "write secrets derivation" },
135 { .mask = QUIC_EV_CONN_LPKT, .name = "lstnr_packet", .desc = "new listener received packet" },
136 { .mask = QUIC_EV_CONN_SPKT, .name = "srv_packet", .desc = "new server received packet" },
137 { .mask = QUIC_EV_CONN_ENCPKT, .name = "enc_hdshk_pkt", .desc = "handhshake packet encryption" },
138 { .mask = QUIC_EV_CONN_TXPKT, .name = "tx_pkt", .desc = "TX packet" },
139 { .mask = QUIC_EV_CONN_PAPKT, .name = "phdshk_apkt", .desc = "post handhshake application packet preparation" },
140 { .mask = QUIC_EV_CONN_PAPKTS, .name = "phdshk_apkts", .desc = "post handhshake application packets preparation" },
141 { .mask = QUIC_EV_CONN_IO_CB, .name = "qc_io_cb", .desc = "QUIC conn. I/O processing" },
142 { .mask = QUIC_EV_CONN_RMHP, .name = "rm_hp", .desc = "Remove header protection" },
143 { .mask = QUIC_EV_CONN_PRSHPKT, .name = "parse_hpkt", .desc = "parse handshake packet" },
144 { .mask = QUIC_EV_CONN_PRSAPKT, .name = "parse_apkt", .desc = "parse application packet" },
145 { .mask = QUIC_EV_CONN_PRSFRM, .name = "parse_frm", .desc = "parse frame" },
146 { .mask = QUIC_EV_CONN_PRSAFRM, .name = "parse_ack_frm", .desc = "parse ACK frame" },
147 { .mask = QUIC_EV_CONN_BFRM, .name = "build_frm", .desc = "build frame" },
148 { .mask = QUIC_EV_CONN_PHPKTS, .name = "phdshk_pkts", .desc = "handhshake packets preparation" },
149 { .mask = QUIC_EV_CONN_TRMHP, .name = "rm_hp_try", .desc = "header protection removing try" },
150 { .mask = QUIC_EV_CONN_ELRMHP, .name = "el_rm_hp", .desc = "handshake enc. level header protection removing" },
151 { .mask = QUIC_EV_CONN_RXPKT, .name = "rx_pkt", .desc = "RX packet" },
152 { .mask = QUIC_EV_CONN_SSLDATA, .name = "ssl_provide_data", .desc = "CRYPTO data provision to TLS stack" },
153 { .mask = QUIC_EV_CONN_RXCDATA, .name = "el_treat_rx_cfrms",.desc = "enc. level RX CRYPTO frames processing"},
154 { .mask = QUIC_EV_CONN_ADDDATA, .name = "add_hdshk_data", .desc = "TLS stack ->add_handshake_data() call"},
155 { .mask = QUIC_EV_CONN_FFLIGHT, .name = "flush_flight", .desc = "TLS stack ->flush_flight() call"},
156 { .mask = QUIC_EV_CONN_SSLALERT, .name = "send_alert", .desc = "TLS stack ->send_alert() call"},
157 { .mask = QUIC_EV_CONN_RTTUPDT, .name = "rtt_updt", .desc = "RTT sampling" },
158 { .mask = QUIC_EV_CONN_SPPKTS, .name = "sppkts", .desc = "send prepared packets" },
159 { .mask = QUIC_EV_CONN_PKTLOSS, .name = "pktloss", .desc = "detect packet loss" },
160 { .mask = QUIC_EV_CONN_STIMER, .name = "stimer", .desc = "set timer" },
161 { .mask = QUIC_EV_CONN_PTIMER, .name = "ptimer", .desc = "process timer" },
162 { .mask = QUIC_EV_CONN_SPTO, .name = "spto", .desc = "set PTO" },
163 { .mask = QUIC_EV_CONN_BCFRMS, .name = "bcfrms", .desc = "build CRYPTO data frames" },
164 { .mask = QUIC_EV_CONN_XPRTSEND, .name = "xprt_send", .desc = "sending XRPT subscription" },
165 { .mask = QUIC_EV_CONN_XPRTRECV, .name = "xprt_recv", .desc = "receiving XRPT subscription" },
166 { .mask = QUIC_EV_CONN_FREED, .name = "conn_freed", .desc = "releasing conn. memory" },
167 { .mask = QUIC_EV_CONN_CLOSE, .name = "conn_close", .desc = "closing conn." },
168 { .mask = QUIC_EV_CONN_ACKSTRM, .name = "ack_strm", .desc = "STREAM ack."},
169 { .mask = QUIC_EV_CONN_FRMLIST, .name = "frm_list", .desc = "frame list"},
170 { .mask = QUIC_EV_STATELESS_RST, .name = "stateless_reset", .desc = "stateless reset sent"},
171 { .mask = QUIC_EV_TRANSP_PARAMS, .name = "transport_params", .desc = "transport parameters"},
172 { .mask = QUIC_EV_CONN_IDLE_TIMER, .name = "idle_timer", .desc = "idle timer task"},
173 { .mask = QUIC_EV_CONN_SUB, .name = "xprt_sub", .desc = "RX/TX subcription or unsubscription to QUIC xprt"},
Amaury Denoyelle5b414862022-10-24 17:40:37 +0200174 { .mask = QUIC_EV_CONN_RCV, .name = "conn_recv", .desc = "RX on connection" },
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200175 { /* end */ }
176};
177
178static const struct name_desc quic_trace_lockon_args[4] = {
179 /* arg1 */ { /* already used by the connection */ },
180 /* arg2 */ { .name="quic", .desc="QUIC transport" },
181 /* arg3 */ { },
182 /* arg4 */ { }
183};
184
185static const struct name_desc quic_trace_decoding[] = {
186#define QUIC_VERB_CLEAN 1
187 { .name="clean", .desc="only user-friendly stuff, generally suitable for level \"user\"" },
188 { /* end */ }
189};
190
191
192struct trace_source trace_quic = {
193 .name = IST("quic"),
194 .desc = "QUIC xprt",
195 .arg_def = TRC_ARG1_QCON, /* TRACE()'s first argument is always a quic_conn */
196 .default_cb = quic_trace,
197 .known_events = quic_trace_events,
198 .lockon_args = quic_trace_lockon_args,
199 .decoding = quic_trace_decoding,
200 .report_events = ~0, /* report everything by default */
201};
202
203#define TRACE_SOURCE &trace_quic
204INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
205
206static BIO_METHOD *ha_quic_meth;
207
208DECLARE_POOL(pool_head_quic_tx_ring, "quic_tx_ring", QUIC_TX_RING_BUFSZ);
209DECLARE_POOL(pool_head_quic_conn_rxbuf, "quic_conn_rxbuf", QUIC_CONN_RX_BUFSZ);
210DECLARE_STATIC_POOL(pool_head_quic_conn_ctx,
211 "quic_conn_ctx", sizeof(struct ssl_sock_ctx));
212DECLARE_STATIC_POOL(pool_head_quic_conn, "quic_conn", sizeof(struct quic_conn));
213DECLARE_POOL(pool_head_quic_connection_id,
214 "quic_connnection_id", sizeof(struct quic_connection_id));
215DECLARE_POOL(pool_head_quic_dgram, "quic_dgram", sizeof(struct quic_dgram));
216DECLARE_POOL(pool_head_quic_rx_packet, "quic_rx_packet", sizeof(struct quic_rx_packet));
217DECLARE_POOL(pool_head_quic_tx_packet, "quic_tx_packet", sizeof(struct quic_tx_packet));
218DECLARE_STATIC_POOL(pool_head_quic_rx_crypto_frm, "quic_rx_crypto_frm", sizeof(struct quic_rx_crypto_frm));
219DECLARE_STATIC_POOL(pool_head_quic_crypto_buf, "quic_crypto_buf", sizeof(struct quic_crypto_buf));
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +0200220DECLARE_STATIC_POOL(pool_head_quic_cstream, "quic_cstream", sizeof(struct quic_cstream));
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200221DECLARE_POOL(pool_head_quic_frame, "quic_frame", sizeof(struct quic_frame));
222DECLARE_STATIC_POOL(pool_head_quic_arng, "quic_arng", sizeof(struct quic_arng_node));
223
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +0100224static struct quic_connection_id *new_quic_cid(struct eb_root *root,
Amaury Denoyelle162baaf2023-04-03 18:49:39 +0200225 struct quic_conn *qc,
226 const struct quic_cid *odcid,
227 const struct sockaddr_storage *saddr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200228static struct quic_tx_packet *qc_build_pkt(unsigned char **pos, const unsigned char *buf_end,
229 struct quic_enc_level *qel, struct quic_tls_ctx *ctx,
230 struct list *frms, struct quic_conn *qc,
231 const struct quic_version *ver, size_t dglen, int pkt_type,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +0200232 int must_ack, int padding, int probe, int cc, int *err);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200233struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state);
Frédéric Lécailled7215712023-03-24 18:13:37 +0100234static void qc_idle_timer_do_rearm(struct quic_conn *qc, int arm_ack);
235static void qc_idle_timer_rearm(struct quic_conn *qc, int read, int arm_ack);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200236static int qc_conn_alloc_ssl_ctx(struct quic_conn *qc);
237static int quic_conn_init_timer(struct quic_conn *qc);
238static int quic_conn_init_idle_timer_task(struct quic_conn *qc);
239
240/* Only for debug purpose */
241struct enc_debug_info {
242 unsigned char *payload;
243 size_t payload_len;
244 unsigned char *aad;
245 size_t aad_len;
246 uint64_t pn;
247};
248
249/* Initializes a enc_debug_info struct (only for debug purpose) */
250static inline void enc_debug_info_init(struct enc_debug_info *edi,
251 unsigned char *payload, size_t payload_len,
252 unsigned char *aad, size_t aad_len, uint64_t pn)
253{
254 edi->payload = payload;
255 edi->payload_len = payload_len;
256 edi->aad = aad;
257 edi->aad_len = aad_len;
258 edi->pn = pn;
259}
260
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100261/* Used only for QUIC TLS key phase traces */
262struct quic_kp_trace {
263 const unsigned char *rx_sec;
264 size_t rx_seclen;
265 const struct quic_tls_kp *rx;
266 const unsigned char *tx_sec;
267 size_t tx_seclen;
268 const struct quic_tls_kp *tx;
269};
270
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200271/* Trace callback for QUIC.
272 * These traces always expect that arg1, if non-null, is of type connection.
273 */
274static void quic_trace(enum trace_level level, uint64_t mask, const struct trace_source *src,
275 const struct ist where, const struct ist func,
276 const void *a1, const void *a2, const void *a3, const void *a4)
277{
278 const struct quic_conn *qc = a1;
279
280 if (qc) {
281 const struct quic_tls_ctx *tls_ctx;
282
Frédéric Lécailleeb3e5172023-04-12 13:41:54 +0200283 chunk_appendf(&trace_buf, " : qc@%p flags=0x%x", qc, qc->flags);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200284 if (mask & QUIC_EV_CONN_INIT) {
285 chunk_appendf(&trace_buf, "\n odcid");
286 quic_cid_dump(&trace_buf, &qc->odcid);
287 chunk_appendf(&trace_buf, "\n dcid");
288 quic_cid_dump(&trace_buf, &qc->dcid);
289 chunk_appendf(&trace_buf, "\n scid");
290 quic_cid_dump(&trace_buf, &qc->scid);
291 }
292
293 if (mask & QUIC_EV_TRANSP_PARAMS) {
294 const struct quic_transport_params *p = a2;
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100295
296 if (p)
297 quic_transport_params_dump(&trace_buf, qc, p);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200298 }
299
300 if (mask & QUIC_EV_CONN_ADDDATA) {
301 const enum ssl_encryption_level_t *level = a2;
302 const size_t *len = a3;
303
304 if (level) {
305 enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
306
307 chunk_appendf(&trace_buf, " el=%c(%d)", quic_enc_level_char(lvl), lvl);
308 }
309 if (len)
310 chunk_appendf(&trace_buf, " len=%llu", (unsigned long long)*len);
311 }
312 if ((mask & QUIC_EV_CONN_ISEC) && qc) {
313 /* Initial read & write secrets. */
314 enum quic_tls_enc_level level = QUIC_TLS_ENC_LEVEL_INITIAL;
315 const unsigned char *rx_sec = a2;
316 const unsigned char *tx_sec = a3;
317
318 tls_ctx = &qc->els[level].tls_ctx;
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200319 chunk_appendf(&trace_buf, "\n RX el=%c", quic_enc_level_char(level));
320 if (rx_sec)
321 quic_tls_secret_hexdump(&trace_buf, rx_sec, 32);
322 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->rx);
323 chunk_appendf(&trace_buf, "\n TX el=%c", quic_enc_level_char(level));
324 if (tx_sec)
325 quic_tls_secret_hexdump(&trace_buf, tx_sec, 32);
326 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->tx);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200327 }
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100328
329 if ((mask & QUIC_EV_CONN_KP) && qc) {
330 /* Initial read & write secrets. */
331 const struct quic_kp_trace *kp = a2;
332
333 if (kp) {
334 if (kp->rx) {
335 chunk_appendf(&trace_buf, "\n RX kp");
336 if (kp->rx_sec)
337 quic_tls_secret_hexdump(&trace_buf, kp->rx_sec, kp->rx_seclen);
338 quic_tls_kp_keys_hexdump(&trace_buf, kp->rx);
339 }
340 if (kp->tx) {
341 chunk_appendf(&trace_buf, "\n TX kp");
342 if (kp->tx_sec)
343 quic_tls_secret_hexdump(&trace_buf, kp->tx_sec, kp->tx_seclen);
344 quic_tls_kp_keys_hexdump(&trace_buf, kp->tx);
345 }
346 }
347 }
348
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200349 if (mask & (QUIC_EV_CONN_RSEC|QUIC_EV_CONN_RWSEC)) {
350 const enum ssl_encryption_level_t *level = a2;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200351
352 if (level) {
353 enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
354
355 chunk_appendf(&trace_buf, "\n RX el=%c", quic_enc_level_char(lvl));
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200356 if (quic_tls_has_rx_sec(&qc->els[lvl])) {
357 tls_ctx = &qc->els[lvl].tls_ctx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200358 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->rx);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200359 }
360 else
361 chunk_appendf(&trace_buf, " (none)");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200362 }
363 }
364
365 if (mask & (QUIC_EV_CONN_WSEC|QUIC_EV_CONN_RWSEC)) {
366 const enum ssl_encryption_level_t *level = a2;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200367
368 if (level) {
369 enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
370
371 chunk_appendf(&trace_buf, "\n TX el=%c", quic_enc_level_char(lvl));
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200372 if (quic_tls_has_tx_sec(&qc->els[lvl])) {
373 tls_ctx = &qc->els[lvl].tls_ctx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200374 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->tx);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200375 }
376 else
377 chunk_appendf(&trace_buf, " (none)");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200378 }
379
380 }
381
382 if (mask & QUIC_EV_CONN_FRMLIST) {
383 const struct list *l = a2;
384
385 if (l) {
386 const struct quic_frame *frm;
387 list_for_each_entry(frm, l, list) {
388 chunk_appendf(&trace_buf, " frm@%p", frm);
389 chunk_frm_appendf(&trace_buf, frm);
390 }
391 }
392 }
393
394 if (mask & (QUIC_EV_CONN_TXPKT|QUIC_EV_CONN_PAPKT)) {
395 const struct quic_tx_packet *pkt = a2;
396 const struct quic_enc_level *qel = a3;
397 const ssize_t *room = a4;
398
399 if (qel) {
400 const struct quic_pktns *pktns = qel->pktns;
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200401 chunk_appendf(&trace_buf, " qel=%c flags=0x%x pto_count=%d cwnd=%llu ppif=%lld pif=%llu "
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200402 "if=%llu pp=%u",
403 quic_enc_level_char_from_qel(qel, qc),
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200404 qel->pktns->flags,
Frédéric Lécaille45400532023-02-13 18:39:19 +0100405 qc->path->loss.pto_count,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200406 (unsigned long long)qc->path->cwnd,
407 (unsigned long long)qc->path->prep_in_flight,
408 (unsigned long long)qc->path->in_flight,
409 (unsigned long long)pktns->tx.in_flight,
410 pktns->tx.pto_probe);
411 }
412 if (pkt) {
413 const struct quic_frame *frm;
414 if (pkt->pn_node.key != (uint64_t)-1)
415 chunk_appendf(&trace_buf, " pn=%llu",(ull)pkt->pn_node.key);
416 list_for_each_entry(frm, &pkt->frms, list) {
417 chunk_appendf(&trace_buf, " frm@%p", frm);
418 chunk_frm_appendf(&trace_buf, frm);
419 }
420 }
421
422 if (room) {
423 chunk_appendf(&trace_buf, " room=%lld", (long long)*room);
424 chunk_appendf(&trace_buf, " dcid.len=%llu scid.len=%llu",
425 (unsigned long long)qc->dcid.len, (unsigned long long)qc->scid.len);
426 }
427 }
428
429 if (mask & QUIC_EV_CONN_IO_CB) {
430 const enum quic_handshake_state *state = a2;
431 const int *err = a3;
432
433 if (state)
434 chunk_appendf(&trace_buf, " state=%s", quic_hdshk_state_str(*state));
435 if (err)
436 chunk_appendf(&trace_buf, " err=%s", ssl_error_str(*err));
437 }
438
439 if (mask & (QUIC_EV_CONN_TRMHP|QUIC_EV_CONN_ELRMHP|QUIC_EV_CONN_SPKT)) {
440 const struct quic_rx_packet *pkt = a2;
441 const unsigned long *pktlen = a3;
442 const SSL *ssl = a4;
443
444 if (pkt) {
445 chunk_appendf(&trace_buf, " pkt@%p", pkt);
446 if (pkt->type == QUIC_PACKET_TYPE_SHORT && pkt->data)
447 chunk_appendf(&trace_buf, " kp=%d",
448 !!(*pkt->data & QUIC_PACKET_KEY_PHASE_BIT));
449 chunk_appendf(&trace_buf, " el=%c",
450 quic_packet_type_enc_level_char(pkt->type));
451 if (pkt->pnl)
452 chunk_appendf(&trace_buf, " pnl=%u pn=%llu", pkt->pnl,
453 (unsigned long long)pkt->pn);
454 if (pkt->token_len)
455 chunk_appendf(&trace_buf, " toklen=%llu",
456 (unsigned long long)pkt->token_len);
457 if (pkt->aad_len)
458 chunk_appendf(&trace_buf, " aadlen=%llu",
459 (unsigned long long)pkt->aad_len);
460 chunk_appendf(&trace_buf, " flags=0x%x len=%llu",
461 pkt->flags, (unsigned long long)pkt->len);
462 }
463 if (pktlen)
464 chunk_appendf(&trace_buf, " (%ld)", *pktlen);
465 if (ssl) {
466 enum ssl_encryption_level_t level = SSL_quic_read_level(ssl);
467 chunk_appendf(&trace_buf, " el=%c",
468 quic_enc_level_char(ssl_to_quic_enc_level(level)));
469 }
470 }
471
472 if (mask & (QUIC_EV_CONN_RXPKT|QUIC_EV_CONN_PRSHPKT|QUIC_EV_CONN_SSLDATA)) {
473 const struct quic_rx_packet *pkt = a2;
474 const struct quic_rx_crypto_frm *cf = a3;
475 const SSL *ssl = a4;
476
477 if (pkt)
478 chunk_appendf(&trace_buf, " pkt@%p el=%c pn=%llu", pkt,
479 quic_packet_type_enc_level_char(pkt->type),
480 (unsigned long long)pkt->pn);
481 if (cf)
482 chunk_appendf(&trace_buf, " cfoff=%llu cflen=%llu",
483 (unsigned long long)cf->offset_node.key,
484 (unsigned long long)cf->len);
485 if (ssl) {
486 enum ssl_encryption_level_t level = SSL_quic_read_level(ssl);
487 chunk_appendf(&trace_buf, " rel=%c",
488 quic_enc_level_char(ssl_to_quic_enc_level(level)));
489 }
490
491 if (qc->err.code)
492 chunk_appendf(&trace_buf, " err_code=0x%llx", (ull)qc->err.code);
493 }
494
495 if (mask & (QUIC_EV_CONN_PRSFRM|QUIC_EV_CONN_BFRM)) {
496 const struct quic_frame *frm = a2;
497
498 if (frm)
499 chunk_appendf(&trace_buf, " %s", quic_frame_type_string(frm->type));
500 }
501
502 if (mask & QUIC_EV_CONN_PHPKTS) {
503 const struct quic_enc_level *qel = a2;
504
505 if (qel) {
506 const struct quic_pktns *pktns = qel->pktns;
507 chunk_appendf(&trace_buf,
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200508 " qel=%c flags=0x%x state=%s ack?%d pto_count=%d cwnd=%llu ppif=%lld pif=%llu if=%llu pp=%u off=%llu",
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200509 quic_enc_level_char_from_qel(qel, qc),
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200510 qel->pktns->flags,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200511 quic_hdshk_state_str(qc->state),
512 !!(qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED),
Frédéric Lécaille45400532023-02-13 18:39:19 +0100513 qc->path->loss.pto_count,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200514 (unsigned long long)qc->path->cwnd,
515 (unsigned long long)qc->path->prep_in_flight,
516 (unsigned long long)qc->path->in_flight,
517 (unsigned long long)pktns->tx.in_flight,
Amaury Denoyelle2f668f02022-11-18 15:24:08 +0100518 pktns->tx.pto_probe,
519 qel->cstream ? (unsigned long long)qel->cstream->rx.offset : 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200520 }
521 }
522
523 if (mask & QUIC_EV_CONN_ENCPKT) {
524 const struct enc_debug_info *edi = a2;
525
526 if (edi)
527 chunk_appendf(&trace_buf,
528 " payload=@%p payload_len=%llu"
529 " aad=@%p aad_len=%llu pn=%llu",
530 edi->payload, (unsigned long long)edi->payload_len,
531 edi->aad, (unsigned long long)edi->aad_len,
532 (unsigned long long)edi->pn);
533 }
534
535 if (mask & QUIC_EV_CONN_RMHP) {
536 const struct quic_rx_packet *pkt = a2;
537
538 if (pkt) {
539 const int *ret = a3;
540
541 chunk_appendf(&trace_buf, " pkt@%p", pkt);
542 if (ret && *ret)
543 chunk_appendf(&trace_buf, " pnl=%u pn=%llu",
544 pkt->pnl, (unsigned long long)pkt->pn);
545 }
546 }
547
548 if (mask & QUIC_EV_CONN_PRSAFRM) {
549 const struct quic_frame *frm = a2;
550 const unsigned long *val1 = a3;
551 const unsigned long *val2 = a4;
552
553 if (frm) {
554 chunk_appendf(&trace_buf, " frm@%p", frm);
555 chunk_frm_appendf(&trace_buf, frm);
556 }
557 if (val1)
558 chunk_appendf(&trace_buf, " %lu", *val1);
559 if (val2)
560 chunk_appendf(&trace_buf, "..%lu", *val2);
561 }
562
563 if (mask & QUIC_EV_CONN_ACKSTRM) {
564 const struct quic_stream *s = a2;
565 const struct qc_stream_desc *stream = a3;
566
567 if (s)
568 chunk_appendf(&trace_buf, " off=%llu len=%llu", (ull)s->offset.key, (ull)s->len);
569 if (stream)
570 chunk_appendf(&trace_buf, " ack_offset=%llu", (ull)stream->ack_offset);
571 }
572
573 if (mask & QUIC_EV_CONN_RTTUPDT) {
574 const unsigned int *rtt_sample = a2;
575 const unsigned int *ack_delay = a3;
576 const struct quic_loss *ql = a4;
577
578 if (rtt_sample)
579 chunk_appendf(&trace_buf, " rtt_sample=%ums", *rtt_sample);
580 if (ack_delay)
581 chunk_appendf(&trace_buf, " ack_delay=%ums", *ack_delay);
582 if (ql)
583 chunk_appendf(&trace_buf,
584 " srtt=%ums rttvar=%ums min_rtt=%ums",
585 ql->srtt >> 3, ql->rtt_var >> 2, ql->rtt_min);
586 }
587 if (mask & QUIC_EV_CONN_CC) {
588 const struct quic_cc_event *ev = a2;
589 const struct quic_cc *cc = a3;
590
591 if (a2)
592 quic_cc_event_trace(&trace_buf, ev);
593 if (a3)
594 quic_cc_state_trace(&trace_buf, cc);
595 }
596
597 if (mask & QUIC_EV_CONN_PKTLOSS) {
598 const struct quic_pktns *pktns = a2;
599 const struct list *lost_pkts = a3;
600
601 if (pktns) {
602 chunk_appendf(&trace_buf, " pktns=%s",
603 pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL] ? "I" :
604 pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT] ? "01RTT": "H");
605 if (pktns->tx.loss_time)
606 chunk_appendf(&trace_buf, " loss_time=%dms",
607 TICKS_TO_MS(tick_remain(now_ms, pktns->tx.loss_time)));
608 }
609 if (lost_pkts && !LIST_ISEMPTY(lost_pkts)) {
610 struct quic_tx_packet *pkt;
611
612 chunk_appendf(&trace_buf, " lost_pkts:");
613 list_for_each_entry(pkt, lost_pkts, list)
614 chunk_appendf(&trace_buf, " %lu", (unsigned long)pkt->pn_node.key);
615 }
616 }
617
618 if (mask & (QUIC_EV_CONN_STIMER|QUIC_EV_CONN_PTIMER|QUIC_EV_CONN_SPTO)) {
619 const struct quic_pktns *pktns = a2;
620 const int *duration = a3;
621 const uint64_t *ifae_pkts = a4;
622
623 if (ifae_pkts)
624 chunk_appendf(&trace_buf, " ifae_pkts=%llu",
625 (unsigned long long)*ifae_pkts);
626 if (pktns) {
627 chunk_appendf(&trace_buf, " pktns=%s pp=%d",
628 pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL] ? "I" :
629 pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT] ? "01RTT": "H",
630 pktns->tx.pto_probe);
631 if (mask & (QUIC_EV_CONN_STIMER|QUIC_EV_CONN_SPTO)) {
632 if (pktns->tx.in_flight)
633 chunk_appendf(&trace_buf, " if=%llu", (ull)pktns->tx.in_flight);
634 if (pktns->tx.loss_time)
635 chunk_appendf(&trace_buf, " loss_time=%dms",
636 TICKS_TO_MS(pktns->tx.loss_time - now_ms));
637 }
638 if (mask & QUIC_EV_CONN_SPTO) {
639 if (pktns->tx.time_of_last_eliciting)
640 chunk_appendf(&trace_buf, " tole=%dms",
641 TICKS_TO_MS(pktns->tx.time_of_last_eliciting - now_ms));
642 if (duration)
643 chunk_appendf(&trace_buf, " dur=%dms", TICKS_TO_MS(*duration));
644 }
645 }
646
647 if (!(mask & (QUIC_EV_CONN_SPTO|QUIC_EV_CONN_PTIMER)) && qc->timer_task) {
648 chunk_appendf(&trace_buf,
649 " expire=%dms", TICKS_TO_MS(qc->timer - now_ms));
650 }
651 }
652
653 if (mask & QUIC_EV_CONN_SPPKTS) {
654 const struct quic_tx_packet *pkt = a2;
655
Frédéric Lécaille45400532023-02-13 18:39:19 +0100656 chunk_appendf(&trace_buf, " pto_count=%d cwnd=%llu ppif=%llu pif=%llu",
657 qc->path->loss.pto_count,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200658 (unsigned long long)qc->path->cwnd,
659 (unsigned long long)qc->path->prep_in_flight,
660 (unsigned long long)qc->path->in_flight);
661 if (pkt) {
662 const struct quic_frame *frm;
Frédéric Lécaille6fd25762023-04-07 19:01:33 +0200663 if (pkt->flags & QUIC_FL_TX_PACKET_ACK)
664 chunk_appendf(&trace_buf, " ack");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200665 chunk_appendf(&trace_buf, " pn=%lu(%s) iflen=%llu",
666 (unsigned long)pkt->pn_node.key,
667 pkt->pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL] ? "I" :
668 pkt->pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT] ? "01RTT": "H",
669 (unsigned long long)pkt->in_flight_len);
670 chunk_appendf(&trace_buf, " rx.bytes=%llu tx.bytes=%llu",
671 (unsigned long long)qc->rx.bytes,
672 (unsigned long long)qc->tx.bytes);
673 list_for_each_entry(frm, &pkt->frms, list) {
674 chunk_appendf(&trace_buf, " frm@%p", frm);
675 chunk_frm_appendf(&trace_buf, frm);
676 }
Frédéric Lécaillebc09f742023-02-13 17:45:36 +0100677
678 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
679 chunk_appendf(&trace_buf, " with scid");
680 quic_cid_dump(&trace_buf, &qc->scid);
681 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200682 }
683 }
684
685 if (mask & QUIC_EV_CONN_SSLALERT) {
686 const uint8_t *alert = a2;
687 const enum ssl_encryption_level_t *level = a3;
688
689 if (alert)
690 chunk_appendf(&trace_buf, " alert=0x%02x", *alert);
691 if (level)
692 chunk_appendf(&trace_buf, " el=%c",
693 quic_enc_level_char(ssl_to_quic_enc_level(*level)));
694 }
695
696 if (mask & QUIC_EV_CONN_BCFRMS) {
697 const size_t *sz1 = a2;
698 const size_t *sz2 = a3;
699 const size_t *sz3 = a4;
700
701 if (sz1)
702 chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz1);
703 if (sz2)
704 chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz2);
705 if (sz3)
706 chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz3);
707 }
708
709 if (mask & QUIC_EV_CONN_PSTRM) {
710 const struct quic_frame *frm = a2;
711
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100712 if (frm)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200713 chunk_frm_appendf(&trace_buf, frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200714 }
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +0200715
716 if (mask & QUIC_EV_CONN_ELEVELSEL) {
717 const enum quic_handshake_state *state = a2;
718 const enum quic_tls_enc_level *level = a3;
719 const enum quic_tls_enc_level *next_level = a4;
720
721 if (state)
722 chunk_appendf(&trace_buf, " state=%s", quic_hdshk_state_str(qc->state));
723 if (level)
724 chunk_appendf(&trace_buf, " level=%c", quic_enc_level_char(*level));
725 if (next_level)
726 chunk_appendf(&trace_buf, " next_level=%c", quic_enc_level_char(*next_level));
727
728 }
Amaury Denoyelle5b414862022-10-24 17:40:37 +0200729
730 if (mask & QUIC_EV_CONN_RCV) {
731 const struct quic_dgram *dgram = a2;
732
733 if (dgram)
734 chunk_appendf(&trace_buf, " dgram.len=%zu", dgram->len);
735 }
Frédéric Lécaille495968e2023-04-03 17:42:05 +0200736
737 if (mask & QUIC_EV_CONN_IDLE_TIMER) {
738 if (tick_isset(qc->ack_expire))
739 chunk_appendf(&trace_buf, " ack_expire=%ums",
740 TICKS_TO_MS(tick_remain(now_ms, qc->ack_expire)));
741 if (tick_isset(qc->idle_expire))
742 chunk_appendf(&trace_buf, " idle_expire=%ums",
743 TICKS_TO_MS(tick_remain(now_ms, qc->idle_expire)));
Frédéric Lécaillece5c1452023-04-05 09:44:21 +0200744 if (qc->idle_timer_task && tick_isset(qc->idle_timer_task->expire))
Frédéric Lécaille495968e2023-04-03 17:42:05 +0200745 chunk_appendf(&trace_buf, " expire=%ums",
746 TICKS_TO_MS(tick_remain(now_ms, qc->idle_timer_task->expire)));
747 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200748 }
749 if (mask & QUIC_EV_CONN_LPKT) {
750 const struct quic_rx_packet *pkt = a2;
751 const uint64_t *len = a3;
752 const struct quic_version *ver = a4;
753
754 if (pkt) {
755 chunk_appendf(&trace_buf, " pkt@%p type=0x%02x %s",
756 pkt, pkt->type, qc_pkt_long(pkt) ? "long" : "short");
757 if (pkt->pn_node.key != (uint64_t)-1)
758 chunk_appendf(&trace_buf, " pn=%llu", pkt->pn_node.key);
759 }
760
761 if (len)
762 chunk_appendf(&trace_buf, " len=%llu", (ull)*len);
763
764 if (ver)
765 chunk_appendf(&trace_buf, " ver=0x%08x", ver->num);
766 }
767
768 if (mask & QUIC_EV_STATELESS_RST) {
769 const struct quic_cid *cid = a2;
770
771 if (cid)
772 quic_cid_dump(&trace_buf, cid);
773 }
774
775}
776
777/* Returns 1 if the peer has validated <qc> QUIC connection address, 0 if not. */
778static inline int quic_peer_validated_addr(struct quic_conn *qc)
779{
780 struct quic_pktns *hdshk_pktns, *app_pktns;
781
782 if (!qc_is_listener(qc))
783 return 1;
784
785 hdshk_pktns = qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns;
786 app_pktns = qc->els[QUIC_TLS_ENC_LEVEL_APP].pktns;
787 if ((hdshk_pktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED) ||
788 (app_pktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED) ||
789 qc->state >= QUIC_HS_ST_COMPLETE)
790 return 1;
791
792 return 0;
793}
794
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100795/* To be called to kill a connection as soon as possible (without sending any packet). */
796void qc_kill_conn(struct quic_conn *qc)
797{
Frédéric Lécaille2f531112023-02-10 14:44:51 +0100798 TRACE_ENTER(QUIC_EV_CONN_KILL, qc);
Frédéric Lécaille495968e2023-04-03 17:42:05 +0200799 TRACE_PROTO("killing the connection", QUIC_EV_CONN_KILL, qc);
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100800 qc->flags |= QUIC_FL_CONN_TO_KILL;
801 task_wakeup(qc->idle_timer_task, TASK_WOKEN_OTHER);
Frédéric Lécaille2f531112023-02-10 14:44:51 +0100802 TRACE_LEAVE(QUIC_EV_CONN_KILL, qc);
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100803}
804
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200805/* Set the timer attached to the QUIC connection with <ctx> as I/O handler and used for
806 * both loss detection and PTO and schedule the task assiated to this timer if needed.
807 */
808static inline void qc_set_timer(struct quic_conn *qc)
809{
810 struct quic_pktns *pktns;
811 unsigned int pto;
Frédéric Lécailleb75eecc2023-01-26 15:18:17 +0100812 int handshake_confirmed;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200813
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100814 TRACE_ENTER(QUIC_EV_CONN_STIMER, qc);
815 TRACE_PROTO("set timer", QUIC_EV_CONN_STIMER, qc, NULL, NULL, &qc->path->ifae_pkts);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200816
Frédéric Lécailledd41a452023-02-09 07:48:33 +0100817 pktns = NULL;
818 if (!qc->timer_task) {
819 TRACE_PROTO("already released timer task", QUIC_EV_CONN_STIMER, qc);
820 goto leave;
821 }
822
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200823 pktns = quic_loss_pktns(qc);
824 if (tick_isset(pktns->tx.loss_time)) {
825 qc->timer = pktns->tx.loss_time;
826 goto out;
827 }
828
829 /* anti-amplification: the timer must be
830 * cancelled for a server which reached the anti-amplification limit.
831 */
832 if (!quic_peer_validated_addr(qc) &&
833 (qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED)) {
834 TRACE_PROTO("anti-amplification reached", QUIC_EV_CONN_STIMER, qc);
835 qc->timer = TICK_ETERNITY;
836 goto out;
837 }
838
839 if (!qc->path->ifae_pkts && quic_peer_validated_addr(qc)) {
840 TRACE_PROTO("timer cancellation", QUIC_EV_CONN_STIMER, qc);
841 /* Timer cancellation. */
842 qc->timer = TICK_ETERNITY;
843 goto out;
844 }
845
Frédéric Lécailleb75eecc2023-01-26 15:18:17 +0100846 handshake_confirmed = qc->state >= QUIC_HS_ST_CONFIRMED;
847 pktns = quic_pto_pktns(qc, handshake_confirmed, &pto);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200848 if (tick_isset(pto))
849 qc->timer = pto;
850 out:
Frédéric Lécailledd41a452023-02-09 07:48:33 +0100851 if (qc->timer == TICK_ETERNITY) {
852 qc->timer_task->expire = TICK_ETERNITY;
853 }
854 else if (tick_is_expired(qc->timer, now_ms)) {
855 TRACE_DEVEL("wakeup asap timer task", QUIC_EV_CONN_STIMER, qc);
856 task_wakeup(qc->timer_task, TASK_WOKEN_MSG);
857 }
858 else {
859 TRACE_DEVEL("timer task scheduling", QUIC_EV_CONN_STIMER, qc);
860 task_schedule(qc->timer_task, qc->timer);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200861 }
Frédéric Lécailledd41a452023-02-09 07:48:33 +0100862 leave:
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100863 TRACE_PROTO("set timer", QUIC_EV_CONN_STIMER, qc, pktns);
864 TRACE_LEAVE(QUIC_EV_CONN_STIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200865}
866
867/* Derive new keys and ivs required for Key Update feature for <qc> QUIC
868 * connection.
869 * Return 1 if succeeded, 0 if not.
870 */
871static int quic_tls_key_update(struct quic_conn *qc)
872{
873 struct quic_tls_ctx *tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100874 struct quic_tls_secrets *rx = &tls_ctx->rx;
875 struct quic_tls_secrets *tx = &tls_ctx->tx;
876 /* Used only for the traces */
877 struct quic_kp_trace kp_trace = {
878 .rx_sec = rx->secret,
879 .rx_seclen = rx->secretlen,
880 .tx_sec = tx->secret,
881 .tx_seclen = tx->secretlen,
882 };
883 /* The next key phase secrets to be derived */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200884 struct quic_tls_kp *nxt_rx = &qc->ku.nxt_rx;
885 struct quic_tls_kp *nxt_tx = &qc->ku.nxt_tx;
886 const struct quic_version *ver =
887 qc->negotiated_version ? qc->negotiated_version : qc->original_version;
888 int ret = 0;
889
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100890 TRACE_ENTER(QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200891
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200892 nxt_rx = &qc->ku.nxt_rx;
893 nxt_tx = &qc->ku.nxt_tx;
894
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100895 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
896 "nxt_rx->secretlen=%llu rx->secretlen=%llu",
897 (ull)nxt_rx->secretlen, (ull)rx->secretlen);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200898 /* Prepare new RX secrets */
899 if (!quic_tls_sec_update(rx->md, ver, nxt_rx->secret, nxt_rx->secretlen,
900 rx->secret, rx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100901 TRACE_ERROR("New RX secret update failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200902 goto leave;
903 }
904
905 if (!quic_tls_derive_keys(rx->aead, NULL, rx->md, ver,
906 nxt_rx->key, nxt_rx->keylen,
907 nxt_rx->iv, nxt_rx->ivlen, NULL, 0,
908 nxt_rx->secret, nxt_rx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100909 TRACE_ERROR("New RX key derivation failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200910 goto leave;
911 }
912
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100913 kp_trace.rx = nxt_rx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200914 /* Prepare new TX secrets */
915 if (!quic_tls_sec_update(tx->md, ver, nxt_tx->secret, nxt_tx->secretlen,
916 tx->secret, tx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100917 TRACE_ERROR("New TX secret update failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200918 goto leave;
919 }
920
921 if (!quic_tls_derive_keys(tx->aead, NULL, tx->md, ver,
922 nxt_tx->key, nxt_tx->keylen,
923 nxt_tx->iv, nxt_tx->ivlen, NULL, 0,
924 nxt_tx->secret, nxt_tx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100925 TRACE_ERROR("New TX key derivation failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200926 goto leave;
927 }
928
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100929 kp_trace.tx = nxt_tx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200930 if (nxt_rx->ctx) {
931 EVP_CIPHER_CTX_free(nxt_rx->ctx);
932 nxt_rx->ctx = NULL;
933 }
934
935 if (!quic_tls_rx_ctx_init(&nxt_rx->ctx, tls_ctx->rx.aead, nxt_rx->key)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100936 TRACE_ERROR("could not initial RX TLS cipher context", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200937 goto leave;
938 }
939
940 if (nxt_tx->ctx) {
941 EVP_CIPHER_CTX_free(nxt_tx->ctx);
942 nxt_tx->ctx = NULL;
943 }
944
945 if (!quic_tls_rx_ctx_init(&nxt_tx->ctx, tls_ctx->tx.aead, nxt_tx->key)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100946 TRACE_ERROR("could not initial RX TLS cipher context", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200947 goto leave;
948 }
949
950 ret = 1;
951 leave:
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100952 TRACE_PROTO("key update", QUIC_EV_CONN_KP, qc, &kp_trace);
953 TRACE_LEAVE(QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200954 return ret;
955}
956
957/* Rotate the Key Update information for <qc> QUIC connection.
958 * Must be used after having updated them.
959 * Always succeeds.
960 */
961static void quic_tls_rotate_keys(struct quic_conn *qc)
962{
963 struct quic_tls_ctx *tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
964 unsigned char *curr_secret, *curr_iv, *curr_key;
965 EVP_CIPHER_CTX *curr_ctx;
966
967 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
968
969 /* Rotate the RX secrets */
970 curr_ctx = tls_ctx->rx.ctx;
971 curr_secret = tls_ctx->rx.secret;
972 curr_iv = tls_ctx->rx.iv;
973 curr_key = tls_ctx->rx.key;
974
975 tls_ctx->rx.ctx = qc->ku.nxt_rx.ctx;
976 tls_ctx->rx.secret = qc->ku.nxt_rx.secret;
977 tls_ctx->rx.iv = qc->ku.nxt_rx.iv;
978 tls_ctx->rx.key = qc->ku.nxt_rx.key;
979
980 qc->ku.nxt_rx.ctx = qc->ku.prv_rx.ctx;
981 qc->ku.nxt_rx.secret = qc->ku.prv_rx.secret;
982 qc->ku.nxt_rx.iv = qc->ku.prv_rx.iv;
983 qc->ku.nxt_rx.key = qc->ku.prv_rx.key;
984
985 qc->ku.prv_rx.ctx = curr_ctx;
986 qc->ku.prv_rx.secret = curr_secret;
987 qc->ku.prv_rx.iv = curr_iv;
988 qc->ku.prv_rx.key = curr_key;
989 qc->ku.prv_rx.pn = tls_ctx->rx.pn;
990
991 /* Update the TX secrets */
992 curr_ctx = tls_ctx->tx.ctx;
993 curr_secret = tls_ctx->tx.secret;
994 curr_iv = tls_ctx->tx.iv;
995 curr_key = tls_ctx->tx.key;
996
997 tls_ctx->tx.ctx = qc->ku.nxt_tx.ctx;
998 tls_ctx->tx.secret = qc->ku.nxt_tx.secret;
999 tls_ctx->tx.iv = qc->ku.nxt_tx.iv;
1000 tls_ctx->tx.key = qc->ku.nxt_tx.key;
1001
1002 qc->ku.nxt_tx.ctx = curr_ctx;
1003 qc->ku.nxt_tx.secret = curr_secret;
1004 qc->ku.nxt_tx.iv = curr_iv;
1005 qc->ku.nxt_tx.key = curr_key;
1006
1007 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
1008}
1009
1010/* returns 0 on error, 1 on success */
1011int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
1012 const uint8_t *read_secret,
1013 const uint8_t *write_secret, size_t secret_len)
1014{
1015 struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1016 struct quic_tls_ctx *tls_ctx = &qc->els[ssl_to_quic_enc_level(level)].tls_ctx;
1017 const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001018 struct quic_tls_secrets *rx = NULL, *tx = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001019 const struct quic_version *ver =
1020 qc->negotiated_version ? qc->negotiated_version : qc->original_version;
1021 int ret = 0;
1022
1023 TRACE_ENTER(QUIC_EV_CONN_RWSEC, qc);
1024 BUG_ON(secret_len > QUIC_TLS_SECRET_LEN);
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01001025
1026 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
1027 TRACE_PROTO("connection to be killed", QUIC_EV_CONN_ADDDATA, qc);
1028 goto out;
1029 }
1030
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001031 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) {
1032 TRACE_PROTO("CC required", QUIC_EV_CONN_RWSEC, qc);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001033 goto out;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001034 }
1035
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001036 if (!read_secret)
1037 goto write;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001038
1039 rx = &tls_ctx->rx;
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001040 if (!quic_tls_secrets_keys_alloc(rx)) {
1041 TRACE_ERROR("RX keys allocation failed", QUIC_EV_CONN_RWSEC, qc);
1042 goto leave;
1043 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001044
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001045 rx->aead = tls_aead(cipher);
1046 rx->md = tls_md(cipher);
1047 rx->hp = tls_hp(cipher);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001048
1049 if (!quic_tls_derive_keys(rx->aead, rx->hp, rx->md, ver, rx->key, rx->keylen,
1050 rx->iv, rx->ivlen, rx->hp_key, sizeof rx->hp_key,
1051 read_secret, secret_len)) {
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001052 TRACE_ERROR("TX key derivation failed", QUIC_EV_CONN_RWSEC, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001053 goto leave;
1054 }
1055
1056 if (!quic_tls_rx_ctx_init(&rx->ctx, rx->aead, rx->key)) {
1057 TRACE_ERROR("could not initial RX TLS cipher context", QUIC_EV_CONN_RWSEC, qc);
1058 goto leave;
1059 }
1060
1061 if (!quic_tls_dec_aes_ctx_init(&rx->hp_ctx, rx->hp, rx->hp_key)) {
1062 TRACE_ERROR("could not initial RX TLS cipher context for HP", QUIC_EV_CONN_RWSEC, qc);
1063 goto leave;
1064 }
1065
1066 /* Enqueue this connection asap if we could derive O-RTT secrets as
1067 * listener. Note that a listener derives only RX secrets for this
1068 * level.
1069 */
1070 if (qc_is_listener(qc) && level == ssl_encryption_early_data) {
1071 TRACE_DEVEL("pushing connection into accept queue", QUIC_EV_CONN_RWSEC, qc);
1072 quic_accept_push_qc(qc);
1073 }
1074
1075write:
1076
1077 if (!write_secret)
1078 goto out;
1079
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001080 tx = &tls_ctx->tx;
1081 if (!quic_tls_secrets_keys_alloc(tx)) {
1082 TRACE_ERROR("TX keys allocation failed", QUIC_EV_CONN_RWSEC, qc);
1083 goto leave;
1084 }
1085
1086 tx->aead = tls_aead(cipher);
1087 tx->md = tls_md(cipher);
1088 tx->hp = tls_hp(cipher);
1089
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001090 if (!quic_tls_derive_keys(tx->aead, tx->hp, tx->md, ver, tx->key, tx->keylen,
1091 tx->iv, tx->ivlen, tx->hp_key, sizeof tx->hp_key,
1092 write_secret, secret_len)) {
1093 TRACE_ERROR("TX key derivation failed", QUIC_EV_CONN_RWSEC, qc);
1094 goto leave;
1095 }
1096
1097 if (!quic_tls_tx_ctx_init(&tx->ctx, tx->aead, tx->key)) {
1098 TRACE_ERROR("could not initial RX TLS cipher context", QUIC_EV_CONN_RWSEC, qc);
1099 goto leave;
1100 }
1101
1102 if (!quic_tls_enc_aes_ctx_init(&tx->hp_ctx, tx->hp, tx->hp_key)) {
1103 TRACE_ERROR("could not initial TX TLS cipher context for HP", QUIC_EV_CONN_RWSEC, qc);
1104 goto leave;
1105 }
1106
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01001107 if (level == ssl_encryption_handshake && qc_is_listener(qc)) {
1108 qc->enc_params_len =
1109 quic_transport_params_encode(qc->enc_params,
1110 qc->enc_params + sizeof qc->enc_params,
1111 &qc->rx.params, ver, 1);
1112 if (!qc->enc_params_len) {
1113 TRACE_ERROR("quic_transport_params_encode() failed", QUIC_EV_CONN_RWSEC);
1114 goto leave;
1115 }
1116
1117 if (!SSL_set_quic_transport_params(qc->xprt_ctx->ssl, qc->enc_params, qc->enc_params_len)) {
1118 TRACE_ERROR("SSL_set_quic_transport_params() failed", QUIC_EV_CONN_RWSEC);
1119 goto leave;
1120 }
1121 }
1122
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001123 if (level == ssl_encryption_application) {
1124 struct quic_tls_kp *prv_rx = &qc->ku.prv_rx;
1125 struct quic_tls_kp *nxt_rx = &qc->ku.nxt_rx;
1126 struct quic_tls_kp *nxt_tx = &qc->ku.nxt_tx;
1127
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001128 if (rx) {
1129 if (!(rx->secret = pool_alloc(pool_head_quic_tls_secret))) {
1130 TRACE_ERROR("Could not allocate RX Application secrete keys", QUIC_EV_CONN_RWSEC, qc);
1131 goto leave;
1132 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001133
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001134 memcpy(rx->secret, read_secret, secret_len);
1135 rx->secretlen = secret_len;
1136 }
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001137
1138 if (tx) {
1139 if (!(tx->secret = pool_alloc(pool_head_quic_tls_secret))) {
1140 TRACE_ERROR("Could not allocate TX Application secrete keys", QUIC_EV_CONN_RWSEC, qc);
1141 goto leave;
1142 }
1143
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001144 memcpy(tx->secret, write_secret, secret_len);
1145 tx->secretlen = secret_len;
1146 }
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001147
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001148 /* Initialize all the secret keys lengths */
1149 prv_rx->secretlen = nxt_rx->secretlen = nxt_tx->secretlen = secret_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001150 }
1151
1152 out:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001153 ret = 1;
1154 leave:
1155 TRACE_LEAVE(QUIC_EV_CONN_RWSEC, qc, &level);
1156 return ret;
1157}
1158
1159/* This function copies the CRYPTO data provided by the TLS stack found at <data>
1160 * with <len> as size in CRYPTO buffers dedicated to store the information about
1161 * outgoing CRYPTO frames so that to be able to replay the CRYPTO data streams.
1162 * It fails (returns 0) only if it could not managed to allocate enough CRYPTO
1163 * buffers to store all the data.
1164 * Note that CRYPTO data may exist at any encryption level except at 0-RTT.
1165 */
1166static int quic_crypto_data_cpy(struct quic_conn *qc, struct quic_enc_level *qel,
1167 const unsigned char *data, size_t len)
1168{
1169 struct quic_crypto_buf **qcb;
1170 /* The remaining byte to store in CRYPTO buffers. */
1171 size_t cf_offset, cf_len, *nb_buf;
1172 unsigned char *pos;
1173 int ret = 0;
1174
1175 nb_buf = &qel->tx.crypto.nb_buf;
1176 qcb = &qel->tx.crypto.bufs[*nb_buf - 1];
1177 cf_offset = (*nb_buf - 1) * QUIC_CRYPTO_BUF_SZ + (*qcb)->sz;
1178 cf_len = len;
1179
1180 TRACE_ENTER(QUIC_EV_CONN_ADDDATA, qc);
1181
1182 while (len) {
1183 size_t to_copy, room;
1184
1185 pos = (*qcb)->data + (*qcb)->sz;
1186 room = QUIC_CRYPTO_BUF_SZ - (*qcb)->sz;
1187 to_copy = len > room ? room : len;
1188 if (to_copy) {
1189 memcpy(pos, data, to_copy);
1190 /* Increment the total size of this CRYPTO buffers by <to_copy>. */
1191 qel->tx.crypto.sz += to_copy;
1192 (*qcb)->sz += to_copy;
1193 len -= to_copy;
1194 data += to_copy;
1195 }
1196 else {
1197 struct quic_crypto_buf **tmp;
1198
1199 // FIXME: realloc!
1200 tmp = realloc(qel->tx.crypto.bufs,
1201 (*nb_buf + 1) * sizeof *qel->tx.crypto.bufs);
1202 if (tmp) {
1203 qel->tx.crypto.bufs = tmp;
1204 qcb = &qel->tx.crypto.bufs[*nb_buf];
1205 *qcb = pool_alloc(pool_head_quic_crypto_buf);
1206 if (!*qcb) {
1207 TRACE_ERROR("Could not allocate crypto buf", QUIC_EV_CONN_ADDDATA, qc);
1208 goto leave;
1209 }
1210
1211 (*qcb)->sz = 0;
1212 ++*nb_buf;
1213 }
1214 else {
1215 break;
1216 }
1217 }
1218 }
1219
1220 /* Allocate a TX CRYPTO frame only if all the CRYPTO data
1221 * have been buffered.
1222 */
1223 if (!len) {
1224 struct quic_frame *frm;
1225 struct quic_frame *found = NULL;
1226
1227 /* There is at most one CRYPTO frame in this packet number
1228 * space. Let's look for it.
1229 */
1230 list_for_each_entry(frm, &qel->pktns->tx.frms, list) {
1231 if (frm->type != QUIC_FT_CRYPTO)
1232 continue;
1233
1234 /* Found */
1235 found = frm;
1236 break;
1237 }
1238
1239 if (found) {
1240 found->crypto.len += cf_len;
1241 }
1242 else {
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01001243 frm = qc_frm_alloc(QUIC_FT_CRYPTO);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001244 if (!frm) {
1245 TRACE_ERROR("Could not allocate quic frame", QUIC_EV_CONN_ADDDATA, qc);
1246 goto leave;
1247 }
1248
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001249 frm->crypto.offset = cf_offset;
1250 frm->crypto.len = cf_len;
1251 frm->crypto.qel = qel;
1252 LIST_APPEND(&qel->pktns->tx.frms, &frm->list);
1253 }
1254 }
1255 ret = len == 0;
1256 leave:
1257 TRACE_LEAVE(QUIC_EV_CONN_ADDDATA, qc);
1258 return ret;
1259}
1260
1261/* Prepare the emission of CONNECTION_CLOSE with error <err>. All send/receive
1262 * activity for <qc> will be interrupted.
1263 */
1264void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err)
1265{
1266 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
1267 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)
1268 goto leave;
1269
1270 TRACE_STATE("setting immediate close", QUIC_EV_CONN_CLOSE, qc);
1271 qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
1272 qc->err.code = err.code;
1273 qc->err.app = err.app;
1274 leave:
1275 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
1276}
1277
1278/* Set <alert> TLS alert as QUIC CRYPTO_ERROR error */
1279void quic_set_tls_alert(struct quic_conn *qc, int alert)
1280{
1281 TRACE_ENTER(QUIC_EV_CONN_SSLALERT, qc);
1282
1283 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
1284 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
1285 TRACE_DEVEL("dec half open counter", QUIC_EV_CONN_SSLALERT, qc);
1286 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
1287 }
1288 quic_set_connection_close(qc, quic_err_tls(alert));
1289 qc->flags |= QUIC_FL_CONN_TLS_ALERT;
1290 TRACE_STATE("Alert set", QUIC_EV_CONN_SSLALERT, qc);
1291
1292 TRACE_LEAVE(QUIC_EV_CONN_SSLALERT, qc);
1293}
1294
1295/* Set the application for <qc> QUIC connection.
1296 * Return 1 if succeeded, 0 if not.
1297 */
1298int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len)
1299{
1300 if (alpn_len >= 2 && memcmp(alpn, "h3", 2) == 0)
1301 qc->app_ops = &h3_ops;
1302 else if (alpn_len >= 10 && memcmp(alpn, "hq-interop", 10) == 0)
1303 qc->app_ops = &hq_interop_ops;
1304 else
1305 return 0;
1306
1307 return 1;
1308}
1309
1310/* ->add_handshake_data QUIC TLS callback used by the QUIC TLS stack when it
1311 * wants to provide the QUIC layer with CRYPTO data.
1312 * Returns 1 if succeeded, 0 if not.
1313 */
1314int ha_quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level,
1315 const uint8_t *data, size_t len)
1316{
1317 struct quic_conn *qc;
1318 enum quic_tls_enc_level tel;
1319 struct quic_enc_level *qel;
1320 int ret = 0;
1321
1322 qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1323 TRACE_ENTER(QUIC_EV_CONN_ADDDATA, qc);
1324
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01001325 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
1326 TRACE_PROTO("connection to be killed", QUIC_EV_CONN_ADDDATA, qc);
1327 goto out;
1328 }
1329
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001330 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) {
1331 TRACE_PROTO("CC required", QUIC_EV_CONN_ADDDATA, qc);
1332 goto out;
1333 }
1334
1335 tel = ssl_to_quic_enc_level(level);
1336 if (tel == -1) {
1337 TRACE_ERROR("Wrong encryption level", QUIC_EV_CONN_ADDDATA, qc);
1338 goto leave;
1339 }
1340
1341 qel = &qc->els[tel];
1342 if (!quic_crypto_data_cpy(qc, qel, data, len)) {
1343 TRACE_ERROR("Could not bufferize", QUIC_EV_CONN_ADDDATA, qc);
1344 goto leave;
1345 }
1346
1347 TRACE_DEVEL("CRYPTO data buffered", QUIC_EV_CONN_ADDDATA,
1348 qc, &level, &len);
1349 out:
1350 ret = 1;
1351 leave:
1352 TRACE_LEAVE(QUIC_EV_CONN_ADDDATA, qc);
1353 return ret;
1354}
1355
1356int ha_quic_flush_flight(SSL *ssl)
1357{
1358 struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1359
1360 TRACE_ENTER(QUIC_EV_CONN_FFLIGHT, qc);
1361 TRACE_LEAVE(QUIC_EV_CONN_FFLIGHT, qc);
1362
1363 return 1;
1364}
1365
1366int ha_quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert)
1367{
1368 struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1369
1370 TRACE_ENTER(QUIC_EV_CONN_SSLALERT, qc);
1371
1372 TRACE_PROTO("Received TLS alert", QUIC_EV_CONN_SSLALERT, qc, &alert, &level);
1373
1374 quic_set_tls_alert(qc, alert);
1375 TRACE_LEAVE(QUIC_EV_CONN_SSLALERT, qc);
1376 return 1;
1377}
1378
1379/* QUIC TLS methods */
1380static SSL_QUIC_METHOD ha_quic_method = {
1381 .set_encryption_secrets = ha_quic_set_encryption_secrets,
1382 .add_handshake_data = ha_quic_add_handshake_data,
1383 .flush_flight = ha_quic_flush_flight,
1384 .send_alert = ha_quic_send_alert,
1385};
1386
1387/* Initialize the TLS context of a listener with <bind_conf> as configuration.
1388 * Returns an error count.
1389 */
1390int ssl_quic_initial_ctx(struct bind_conf *bind_conf)
1391{
1392 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
1393 int cfgerr = 0;
1394
1395 long options =
1396 (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
1397 SSL_OP_SINGLE_ECDH_USE |
1398 SSL_OP_CIPHER_SERVER_PREFERENCE;
1399 SSL_CTX *ctx;
1400
1401 ctx = SSL_CTX_new(TLS_server_method());
1402 bind_conf->initial_ctx = ctx;
1403
1404 SSL_CTX_set_options(ctx, options);
1405 SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
1406 SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
1407 SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
1408
1409#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1410# if defined(HAVE_SSL_CLIENT_HELLO_CB)
1411# if defined(SSL_OP_NO_ANTI_REPLAY)
1412 if (bind_conf->ssl_conf.early_data) {
1413 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
1414 SSL_CTX_set_max_early_data(ctx, 0xffffffff);
1415 }
1416# endif /* !SSL_OP_NO_ANTI_REPLAY */
1417 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
1418 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
1419# else /* ! HAVE_SSL_CLIENT_HELLO_CB */
1420 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
1421# endif
1422 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
1423#endif
1424 SSL_CTX_set_quic_method(ctx, &ha_quic_method);
1425
1426 return cfgerr;
1427}
1428
1429/* Decode an expected packet number from <truncated_on> its truncated value,
1430 * depending on <largest_pn> the largest received packet number, and <pn_nbits>
1431 * the number of bits used to encode this packet number (its length in bytes * 8).
1432 * See https://quicwg.org/base-drafts/draft-ietf-quic-transport.html#packet-encoding
1433 */
1434static uint64_t decode_packet_number(uint64_t largest_pn,
1435 uint32_t truncated_pn, unsigned int pn_nbits)
1436{
1437 uint64_t expected_pn = largest_pn + 1;
1438 uint64_t pn_win = (uint64_t)1 << pn_nbits;
1439 uint64_t pn_hwin = pn_win / 2;
1440 uint64_t pn_mask = pn_win - 1;
1441 uint64_t candidate_pn;
1442
1443
1444 candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;
1445 /* Note that <pn_win> > <pn_hwin>. */
1446 if (candidate_pn < QUIC_MAX_PACKET_NUM - pn_win &&
1447 candidate_pn + pn_hwin <= expected_pn)
1448 return candidate_pn + pn_win;
1449
1450 if (candidate_pn > expected_pn + pn_hwin && candidate_pn >= pn_win)
1451 return candidate_pn - pn_win;
1452
1453 return candidate_pn;
1454}
1455
1456/* Remove the header protection of <pkt> QUIC packet using <tls_ctx> as QUIC TLS
1457 * cryptographic context.
1458 * <largest_pn> is the largest received packet number and <pn> the address of
1459 * the packet number field for this packet with <byte0> address of its first byte.
1460 * <end> points to one byte past the end of this packet.
1461 * Returns 1 if succeeded, 0 if not.
1462 */
1463static int qc_do_rm_hp(struct quic_conn *qc,
1464 struct quic_rx_packet *pkt, struct quic_tls_ctx *tls_ctx,
1465 int64_t largest_pn, unsigned char *pn, unsigned char *byte0)
1466{
1467 int ret, i, pnlen;
1468 uint64_t packet_number;
1469 uint32_t truncated_pn = 0;
1470 unsigned char mask[5] = {0};
1471 unsigned char *sample;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001472
1473 TRACE_ENTER(QUIC_EV_CONN_RMHP, qc);
1474
1475 ret = 0;
1476
1477 /* Check there is enough data in this packet. */
1478 if (pkt->len - (pn - byte0) < QUIC_PACKET_PN_MAXLEN + sizeof mask) {
1479 TRACE_PROTO("too short packet", QUIC_EV_CONN_RMHP, qc, pkt);
1480 goto leave;
1481 }
1482
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001483 sample = pn + QUIC_PACKET_PN_MAXLEN;
1484
1485 if (!quic_tls_aes_decrypt(mask, sample, sizeof mask, tls_ctx->rx.hp_ctx)) {
1486 TRACE_ERROR("HP removing failed", QUIC_EV_CONN_RMHP, qc, pkt);
1487 goto leave;
1488 }
1489
1490 *byte0 ^= mask[0] & (*byte0 & QUIC_PACKET_LONG_HEADER_BIT ? 0xf : 0x1f);
1491 pnlen = (*byte0 & QUIC_PACKET_PNL_BITMASK) + 1;
1492 for (i = 0; i < pnlen; i++) {
1493 pn[i] ^= mask[i + 1];
1494 truncated_pn = (truncated_pn << 8) | pn[i];
1495 }
1496
1497 packet_number = decode_packet_number(largest_pn, truncated_pn, pnlen * 8);
1498 /* Store remaining information for this unprotected header */
1499 pkt->pn = packet_number;
1500 pkt->pnl = pnlen;
1501
1502 ret = 1;
1503 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001504 TRACE_LEAVE(QUIC_EV_CONN_RMHP, qc);
1505 return ret;
1506}
1507
1508/* Encrypt the payload of a QUIC packet with <pn> as number found at <payload>
1509 * address, with <payload_len> as payload length, <aad> as address of
1510 * the ADD and <aad_len> as AAD length depending on the <tls_ctx> QUIC TLS
1511 * context.
1512 * Returns 1 if succeeded, 0 if not.
1513 */
1514static int quic_packet_encrypt(unsigned char *payload, size_t payload_len,
1515 unsigned char *aad, size_t aad_len, uint64_t pn,
1516 struct quic_tls_ctx *tls_ctx, struct quic_conn *qc)
1517{
1518 int ret = 0;
1519 unsigned char iv[QUIC_TLS_IV_LEN];
1520 unsigned char *tx_iv = tls_ctx->tx.iv;
1521 size_t tx_iv_sz = tls_ctx->tx.ivlen;
1522 struct enc_debug_info edi;
1523
1524 TRACE_ENTER(QUIC_EV_CONN_ENCPKT, qc);
1525
1526 if (!quic_aead_iv_build(iv, sizeof iv, tx_iv, tx_iv_sz, pn)) {
1527 TRACE_ERROR("AEAD IV building for encryption failed", QUIC_EV_CONN_ENCPKT, qc);
1528 goto err;
1529 }
1530
1531 if (!quic_tls_encrypt(payload, payload_len, aad, aad_len,
1532 tls_ctx->tx.ctx, tls_ctx->tx.aead, tls_ctx->tx.key, iv)) {
1533 TRACE_ERROR("QUIC packet encryption failed", QUIC_EV_CONN_ENCPKT, qc);
1534 goto err;
1535 }
1536
1537 ret = 1;
1538 leave:
1539 TRACE_LEAVE(QUIC_EV_CONN_ENCPKT, qc);
1540 return ret;
1541
1542 err:
1543 enc_debug_info_init(&edi, payload, payload_len, aad, aad_len, pn);
1544 goto leave;
1545}
1546
Frédéric Lécaille72027782023-02-22 16:20:09 +01001547/* Select the correct TLS cipher context to used to decipher <pkt> packet
1548 * attached to <qc> connection from <qel> encryption level.
1549 */
1550static inline struct quic_tls_ctx *qc_select_tls_ctx(struct quic_conn *qc,
1551 struct quic_enc_level *qel,
1552 struct quic_rx_packet *pkt)
1553{
1554 return pkt->type != QUIC_PACKET_TYPE_INITIAL ? &qel->tls_ctx :
1555 pkt->version == qc->negotiated_version ? &qc->negotiated_ictx : &qel->tls_ctx;
1556}
1557
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001558/* Decrypt <pkt> packet using encryption level <qel> for <qc> connection.
1559 * Decryption is done in place in packet buffer.
1560 *
Ilya Shipitsin5fa29b82022-12-07 09:46:19 +05001561 * Returns 1 on success else 0.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001562 */
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001563static int qc_pkt_decrypt(struct quic_conn *qc, struct quic_enc_level *qel,
1564 struct quic_rx_packet *pkt)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001565{
1566 int ret, kp_changed;
1567 unsigned char iv[QUIC_TLS_IV_LEN];
Frédéric Lécaille72027782023-02-22 16:20:09 +01001568 struct quic_tls_ctx *tls_ctx = qc_select_tls_ctx(qc, qel, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001569 EVP_CIPHER_CTX *rx_ctx = tls_ctx->rx.ctx;
1570 unsigned char *rx_iv = tls_ctx->rx.iv;
1571 size_t rx_iv_sz = tls_ctx->rx.ivlen;
1572 unsigned char *rx_key = tls_ctx->rx.key;
1573
1574 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
1575
1576 ret = 0;
1577 kp_changed = 0;
1578
1579 if (pkt->type == QUIC_PACKET_TYPE_SHORT) {
1580 /* The two tested bits are not at the same position,
1581 * this is why they are first both inversed.
1582 */
1583 if (!(*pkt->data & QUIC_PACKET_KEY_PHASE_BIT) ^ !(tls_ctx->flags & QUIC_FL_TLS_KP_BIT_SET)) {
1584 if (pkt->pn < tls_ctx->rx.pn) {
1585 /* The lowest packet number of a previous key phase
1586 * cannot be null if it really stores previous key phase
1587 * secrets.
1588 */
1589 // TODO: check if BUG_ON() more suitable
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001590 if (!qc->ku.prv_rx.pn) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001591 TRACE_ERROR("null previous packet number", QUIC_EV_CONN_RXPKT, qc);
1592 goto leave;
1593 }
1594
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001595 rx_ctx = qc->ku.prv_rx.ctx;
1596 rx_iv = qc->ku.prv_rx.iv;
1597 rx_key = qc->ku.prv_rx.key;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001598 }
1599 else if (pkt->pn > qel->pktns->rx.largest_pn) {
1600 /* Next key phase */
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +01001601 TRACE_PROTO("Key phase changed", QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001602 kp_changed = 1;
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001603 rx_ctx = qc->ku.nxt_rx.ctx;
1604 rx_iv = qc->ku.nxt_rx.iv;
1605 rx_key = qc->ku.nxt_rx.key;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001606 }
1607 }
1608 }
1609
1610 if (!quic_aead_iv_build(iv, sizeof iv, rx_iv, rx_iv_sz, pkt->pn)) {
1611 TRACE_ERROR("quic_aead_iv_build() failed", QUIC_EV_CONN_RXPKT, qc);
1612 goto leave;
1613 }
1614
1615 ret = quic_tls_decrypt(pkt->data + pkt->aad_len, pkt->len - pkt->aad_len,
1616 pkt->data, pkt->aad_len,
1617 rx_ctx, tls_ctx->rx.aead, rx_key, iv);
1618 if (!ret) {
1619 TRACE_ERROR("quic_tls_decrypt() failed", QUIC_EV_CONN_RXPKT, qc);
1620 goto leave;
1621 }
1622
1623 /* Update the keys only if the packet decryption succeeded. */
1624 if (kp_changed) {
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001625 quic_tls_rotate_keys(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001626 /* Toggle the Key Phase bit */
1627 tls_ctx->flags ^= QUIC_FL_TLS_KP_BIT_SET;
1628 /* Store the lowest packet number received for the current key phase */
1629 tls_ctx->rx.pn = pkt->pn;
1630 /* Prepare the next key update */
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001631 if (!quic_tls_key_update(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001632 TRACE_ERROR("quic_tls_key_update() failed", QUIC_EV_CONN_RXPKT, qc);
1633 goto leave;
1634 }
1635 }
1636
1637 /* Update the packet length (required to parse the frames). */
1638 pkt->len -= QUIC_TLS_TAG_LEN;
1639 ret = 1;
1640 leave:
1641 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
1642 return ret;
1643}
1644
1645
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001646/* Release <frm> frame and mark its copies as acknowledged */
1647void qc_release_frm(struct quic_conn *qc, struct quic_frame *frm)
1648{
1649 uint64_t pn;
1650 struct quic_frame *origin, *f, *tmp;
1651
1652 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1653
1654 /* Identify this frame: a frame copy or one of its copies */
1655 origin = frm->origin ? frm->origin : frm;
1656 /* Ensure the source of the copies is flagged as acked, <frm> being
1657 * possibly a copy of <origin>
1658 */
1659 origin->flags |= QUIC_FL_TX_FRAME_ACKED;
1660 /* Mark all the copy of <origin> as acknowledged. We must
1661 * not release the packets (releasing the frames) at this time as
1662 * they are possibly also to be acknowledged alongside the
1663 * the current one.
1664 */
1665 list_for_each_entry_safe(f, tmp, &origin->reflist, ref) {
1666 if (f->pkt) {
1667 f->flags |= QUIC_FL_TX_FRAME_ACKED;
1668 f->origin = NULL;
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001669 LIST_DEL_INIT(&f->ref);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001670 pn = f->pkt->pn_node.key;
1671 TRACE_DEVEL("mark frame as acked from packet",
1672 QUIC_EV_CONN_PRSAFRM, qc, f, &pn);
1673 }
1674 else {
1675 TRACE_DEVEL("freeing unsent frame",
1676 QUIC_EV_CONN_PRSAFRM, qc, f);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001677 LIST_DEL_INIT(&f->ref);
1678 qc_frm_free(&f);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001679 }
1680 }
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001681 LIST_DEL_INIT(&frm->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001682 pn = frm->pkt->pn_node.key;
1683 quic_tx_packet_refdec(frm->pkt);
1684 TRACE_DEVEL("freeing frame from packet",
1685 QUIC_EV_CONN_PRSAFRM, qc, frm, &pn);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001686 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001687
1688 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1689}
1690
1691/* Schedule a CONNECTION_CLOSE emission on <qc> if the MUX has been released
1692 * and all STREAM data are acknowledged. The MUX is responsible to have set
1693 * <qc.err> before as it is reused for the CONNECTION_CLOSE frame.
1694 *
1695 * TODO this should also be called on lost packet detection
1696 */
1697void qc_check_close_on_released_mux(struct quic_conn *qc)
1698{
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001699 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
1700
1701 if (qc->mux_state == QC_MUX_RELEASED && eb_is_empty(&qc->streams_by_id)) {
1702 /* Reuse errcode which should have been previously set by the MUX on release. */
1703 quic_set_connection_close(qc, qc->err);
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02001704 tasklet_wakeup(qc->wait_event.tasklet);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001705 }
1706
1707 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
1708}
1709
1710/* Remove from <stream> the acknowledged frames.
1711 *
1712 * Returns 1 if at least one frame was removed else 0.
1713 */
1714static int quic_stream_try_to_consume(struct quic_conn *qc,
1715 struct qc_stream_desc *stream)
1716{
1717 int ret;
1718 struct eb64_node *frm_node;
1719
1720 TRACE_ENTER(QUIC_EV_CONN_ACKSTRM, qc);
1721
1722 ret = 0;
1723 frm_node = eb64_first(&stream->acked_frms);
1724 while (frm_node) {
1725 struct quic_stream *strm;
1726 struct quic_frame *frm;
1727 size_t offset, len;
1728
1729 strm = eb64_entry(frm_node, struct quic_stream, offset);
1730 offset = strm->offset.key;
1731 len = strm->len;
1732
1733 if (offset > stream->ack_offset)
1734 break;
1735
1736 if (qc_stream_desc_ack(&stream, offset, len)) {
1737 /* cf. next comment : frame may be freed at this stage. */
1738 TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
1739 qc, stream ? strm : NULL, stream);
1740 ret = 1;
1741 }
1742
1743 /* If stream is NULL after qc_stream_desc_ack(), it means frame
1744 * has been freed. with the stream frames tree. Nothing to do
1745 * anymore in here.
1746 */
1747 if (!stream) {
1748 qc_check_close_on_released_mux(qc);
1749 ret = 1;
1750 goto leave;
1751 }
1752
1753 frm_node = eb64_next(frm_node);
1754 eb64_delete(&strm->offset);
1755
1756 frm = container_of(strm, struct quic_frame, stream);
1757 qc_release_frm(qc, frm);
1758 }
1759
1760 leave:
1761 TRACE_LEAVE(QUIC_EV_CONN_ACKSTRM, qc);
1762 return ret;
1763}
1764
1765/* Treat <frm> frame whose packet it is attached to has just been acknowledged. */
1766static inline void qc_treat_acked_tx_frm(struct quic_conn *qc,
1767 struct quic_frame *frm)
1768{
Frédéric Lécaille8f991942023-03-24 15:14:45 +01001769 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1770 TRACE_PROTO("RX ack TX frm", QUIC_EV_CONN_PRSAFRM, qc, frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001771
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001772 switch (frm->type) {
1773 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
1774 {
1775 struct quic_stream *strm_frm = &frm->stream;
1776 struct eb64_node *node = NULL;
1777 struct qc_stream_desc *stream = NULL;
1778 const size_t offset = strm_frm->offset.key;
1779 const size_t len = strm_frm->len;
1780
1781 /* do not use strm_frm->stream as the qc_stream_desc instance
1782 * might be freed at this stage. Use the id to do a proper
1783 * lookup.
1784 *
1785 * TODO if lookup operation impact on the perf is noticeable,
1786 * implement a refcount on qc_stream_desc instances.
1787 */
1788 node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
1789 if (!node) {
1790 TRACE_DEVEL("acked stream for released stream", QUIC_EV_CONN_ACKSTRM, qc, strm_frm);
1791 qc_release_frm(qc, frm);
1792 /* early return */
1793 goto leave;
1794 }
1795 stream = eb64_entry(node, struct qc_stream_desc, by_id);
1796
1797 TRACE_DEVEL("acked stream", QUIC_EV_CONN_ACKSTRM, qc, strm_frm, stream);
1798 if (offset <= stream->ack_offset) {
1799 if (qc_stream_desc_ack(&stream, offset, len)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001800 TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
1801 qc, strm_frm, stream);
1802 }
1803
1804 if (!stream) {
1805 /* no need to continue if stream freed. */
1806 TRACE_DEVEL("stream released and freed", QUIC_EV_CONN_ACKSTRM, qc);
1807 qc_release_frm(qc, frm);
1808 qc_check_close_on_released_mux(qc);
1809 break;
1810 }
1811
1812 TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
1813 qc, strm_frm, stream);
1814 qc_release_frm(qc, frm);
1815 }
1816 else {
1817 eb64_insert(&stream->acked_frms, &strm_frm->offset);
1818 }
1819
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01001820 quic_stream_try_to_consume(qc, stream);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001821 }
1822 break;
1823 default:
1824 qc_release_frm(qc, frm);
1825 }
1826
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001827 leave:
1828 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1829}
1830
1831/* Remove <largest> down to <smallest> node entries from <pkts> tree of TX packet,
1832 * deallocating them, and their TX frames.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001833 * May be NULL if <largest> node could not be found.
1834 */
Frédéric Lécaillec664e642023-03-15 17:21:13 +01001835static inline void qc_ackrng_pkts(struct quic_conn *qc,
1836 struct eb_root *pkts,
1837 unsigned int *pkt_flags,
1838 struct list *newly_acked_pkts,
1839 struct eb64_node *largest_node,
1840 uint64_t largest, uint64_t smallest)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001841{
1842 struct eb64_node *node;
1843 struct quic_tx_packet *pkt;
1844
1845 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1846
Frédéric Lécaillec664e642023-03-15 17:21:13 +01001847 node = eb64_lookup_ge(pkts, smallest);
1848 if (!node)
1849 goto leave;
1850
1851 largest_node = largest_node ? largest_node : eb64_lookup_le(pkts, largest);
1852 if (!largest_node)
1853 goto leave;
1854
1855 while (node && node->key <= largest_node->key) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001856 struct quic_frame *frm, *frmbak;
1857
1858 pkt = eb64_entry(node, struct quic_tx_packet, pn_node);
1859 *pkt_flags |= pkt->flags;
1860 LIST_INSERT(newly_acked_pkts, &pkt->list);
1861 TRACE_DEVEL("Removing packet #", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
1862 list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
1863 qc_treat_acked_tx_frm(qc, frm);
Frédéric Lécaille814645f2022-11-18 18:15:28 +01001864 /* If there are others packet in the same datagram <pkt> is attached to,
1865 * detach the previous one and the next one from <pkt>.
1866 */
Frédéric Lécaille74b5f7b2022-11-20 18:35:35 +01001867 quic_tx_packet_dgram_detach(pkt);
Frédéric Lécaillec664e642023-03-15 17:21:13 +01001868 node = eb64_next(node);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001869 eb64_delete(&pkt->pn_node);
1870 }
1871
Frédéric Lécaillec664e642023-03-15 17:21:13 +01001872 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001873 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001874}
1875
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001876/* Remove all frames from <pkt_frm_list> and reinsert them in the same order
1877 * they have been sent into <pktns_frm_list>. The loss counter of each frame is
1878 * incremented and checked if it does not exceed retransmission limit.
1879 *
1880 * Returns 1 on success, 0 if a frame loss limit is exceeded. A
1881 * CONNECTION_CLOSE is scheduled in this case.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001882 */
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001883static inline int qc_requeue_nacked_pkt_tx_frms(struct quic_conn *qc,
1884 struct quic_tx_packet *pkt,
1885 struct list *pktns_frm_list)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001886{
1887 struct quic_frame *frm, *frmbak;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001888 struct list *pkt_frm_list = &pkt->frms;
1889 uint64_t pn = pkt->pn_node.key;
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001890 int close = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001891
1892 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1893
1894 list_for_each_entry_safe(frm, frmbak, pkt_frm_list, list) {
1895 /* First remove this frame from the packet it was attached to */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001896 LIST_DEL_INIT(&frm->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001897 quic_tx_packet_refdec(pkt);
1898 /* At this time, this frame is not freed but removed from its packet */
1899 frm->pkt = NULL;
1900 /* Remove any reference to this frame */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001901 qc_frm_unref(frm, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001902 switch (frm->type) {
1903 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
1904 {
1905 struct quic_stream *strm_frm = &frm->stream;
1906 struct eb64_node *node = NULL;
1907 struct qc_stream_desc *stream_desc;
1908
1909 node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
1910 if (!node) {
1911 TRACE_DEVEL("released stream", QUIC_EV_CONN_PRSAFRM, qc, frm);
1912 TRACE_DEVEL("freeing frame from packet", QUIC_EV_CONN_PRSAFRM,
1913 qc, frm, &pn);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001914 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001915 continue;
1916 }
1917
1918 stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
1919 /* Do not resend this frame if in the "already acked range" */
1920 if (strm_frm->offset.key + strm_frm->len <= stream_desc->ack_offset) {
1921 TRACE_DEVEL("ignored frame in already acked range",
1922 QUIC_EV_CONN_PRSAFRM, qc, frm);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001923 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001924 continue;
1925 }
1926 else if (strm_frm->offset.key < stream_desc->ack_offset) {
Frédéric Lécailleca079792023-03-17 08:56:50 +01001927 uint64_t diff = stream_desc->ack_offset - strm_frm->offset.key;
1928
Frédéric Lécaillec425e032023-03-20 14:32:59 +01001929 qc_stream_frm_mv_fwd(frm, diff);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001930 TRACE_DEVEL("updated partially acked frame",
1931 QUIC_EV_CONN_PRSAFRM, qc, frm);
1932 }
1933 break;
1934 }
1935
1936 default:
1937 break;
1938 }
1939
1940 /* Do not resend probing packet with old data */
1941 if (pkt->flags & QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA) {
1942 TRACE_DEVEL("ignored frame with old data from packet", QUIC_EV_CONN_PRSAFRM,
1943 qc, frm, &pn);
1944 if (frm->origin)
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001945 LIST_DEL_INIT(&frm->ref);
1946 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001947 continue;
1948 }
1949
1950 if (frm->flags & QUIC_FL_TX_FRAME_ACKED) {
1951 TRACE_DEVEL("already acked frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
1952 TRACE_DEVEL("freeing frame from packet", QUIC_EV_CONN_PRSAFRM,
1953 qc, frm, &pn);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001954 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001955 }
1956 else {
Amaury Denoyelle24d5b722023-01-31 11:44:50 +01001957 if (++frm->loss_count >= global.tune.quic_max_frame_loss) {
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001958 TRACE_ERROR("retransmission limit reached, closing the connection", QUIC_EV_CONN_PRSAFRM, qc);
1959 quic_set_connection_close(qc, quic_err_transport(QC_ERR_INTERNAL_ERROR));
1960 close = 1;
1961 }
1962
Frédéric Lécaillebe795ce2023-03-08 18:23:13 +01001963 LIST_APPEND(pktns_frm_list, &frm->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001964 TRACE_DEVEL("frame requeued", QUIC_EV_CONN_PRSAFRM, qc, frm);
1965 }
1966 }
1967
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001968 end:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001969 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001970 return !close;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001971}
1972
1973/* Free <pkt> TX packet and its attached frames.
1974 * This is the responsibility of the caller to remove this packet of
1975 * any data structure it was possibly attached to.
1976 */
1977static inline void free_quic_tx_packet(struct quic_conn *qc,
1978 struct quic_tx_packet *pkt)
1979{
1980 struct quic_frame *frm, *frmbak;
1981
1982 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
1983
1984 if (!pkt)
1985 goto leave;
1986
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001987 list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
1988 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001989 pool_free(pool_head_quic_tx_packet, pkt);
1990
1991 leave:
1992 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
1993}
1994
1995/* Free the TX packets of <pkts> list */
1996static inline void free_quic_tx_pkts(struct quic_conn *qc, struct list *pkts)
1997{
1998 struct quic_tx_packet *pkt, *tmp;
1999
2000 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
2001
2002 list_for_each_entry_safe(pkt, tmp, pkts, list) {
2003 LIST_DELETE(&pkt->list);
2004 eb64_delete(&pkt->pn_node);
2005 free_quic_tx_packet(qc, pkt);
2006 }
2007
2008 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
2009}
2010
2011/* Remove already sent ranges of acknowledged packet numbers from
2012 * <pktns> packet number space tree below <largest_acked_pn> possibly
2013 * updating the range which contains <largest_acked_pn>.
2014 * Never fails.
2015 */
2016static void qc_treat_ack_of_ack(struct quic_conn *qc,
2017 struct quic_pktns *pktns,
2018 int64_t largest_acked_pn)
2019{
2020 struct eb64_node *ar, *next_ar;
2021 struct quic_arngs *arngs = &pktns->rx.arngs;
2022
2023 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2024
2025 ar = eb64_first(&arngs->root);
2026 while (ar) {
2027 struct quic_arng_node *ar_node;
2028
2029 next_ar = eb64_next(ar);
2030 ar_node = eb64_entry(ar, struct quic_arng_node, first);
2031
2032 if ((int64_t)ar_node->first.key > largest_acked_pn) {
2033 TRACE_DEVEL("first.key > largest", QUIC_EV_CONN_PRSAFRM, qc);
2034 break;
2035 }
2036
2037 if (largest_acked_pn < ar_node->last) {
2038 eb64_delete(ar);
2039 ar_node->first.key = largest_acked_pn + 1;
2040 eb64_insert(&arngs->root, ar);
2041 break;
2042 }
2043
2044 eb64_delete(ar);
2045 pool_free(pool_head_quic_arng, ar_node);
2046 arngs->sz--;
2047 ar = next_ar;
2048 }
2049
2050 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2051}
2052
2053/* Send a packet ack event nofication for each newly acked packet of
2054 * <newly_acked_pkts> list and free them.
2055 * Always succeeds.
2056 */
2057static inline void qc_treat_newly_acked_pkts(struct quic_conn *qc,
2058 struct list *newly_acked_pkts)
2059{
2060 struct quic_tx_packet *pkt, *tmp;
2061 struct quic_cc_event ev = { .type = QUIC_CC_EVT_ACK, };
2062
2063 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2064
2065 list_for_each_entry_safe(pkt, tmp, newly_acked_pkts, list) {
2066 pkt->pktns->tx.in_flight -= pkt->in_flight_len;
2067 qc->path->prep_in_flight -= pkt->in_flight_len;
2068 qc->path->in_flight -= pkt->in_flight_len;
2069 if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
2070 qc->path->ifae_pkts--;
2071 /* If this packet contained an ACK frame, proceed to the
2072 * acknowledging of range of acks from the largest acknowledged
2073 * packet number which was sent in an ACK frame by this packet.
2074 */
2075 if (pkt->largest_acked_pn != -1)
2076 qc_treat_ack_of_ack(qc, pkt->pktns, pkt->largest_acked_pn);
2077 ev.ack.acked = pkt->in_flight_len;
2078 ev.ack.time_sent = pkt->time_sent;
2079 quic_cc_event(&qc->path->cc, &ev);
2080 LIST_DELETE(&pkt->list);
2081 eb64_delete(&pkt->pn_node);
2082 quic_tx_packet_refdec(pkt);
2083 }
2084
2085 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2086
2087}
2088
2089/* Release all the frames attached to <pktns> packet number space */
2090static inline void qc_release_pktns_frms(struct quic_conn *qc,
2091 struct quic_pktns *pktns)
2092{
2093 struct quic_frame *frm, *frmbak;
2094
2095 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
2096
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01002097 list_for_each_entry_safe(frm, frmbak, &pktns->tx.frms, list)
2098 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002099
2100 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
2101}
2102
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002103/* Handle <pkts> list of lost packets detected at <now_us> handling their TX
2104 * frames. Send a packet loss event to the congestion controller if in flight
2105 * packet have been lost. Also frees the packet in <pkts> list.
2106 *
2107 * Returns 1 on success else 0 if loss limit has been exceeded. A
2108 * CONNECTION_CLOSE was prepared to close the connection ASAP.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002109 */
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002110static inline int qc_release_lost_pkts(struct quic_conn *qc,
2111 struct quic_pktns *pktns,
2112 struct list *pkts,
2113 uint64_t now_us)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002114{
2115 struct quic_tx_packet *pkt, *tmp, *oldest_lost, *newest_lost;
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002116 int close = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002117
2118 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2119
2120 if (LIST_ISEMPTY(pkts))
2121 goto leave;
2122
2123 oldest_lost = newest_lost = NULL;
2124 list_for_each_entry_safe(pkt, tmp, pkts, list) {
2125 struct list tmp = LIST_HEAD_INIT(tmp);
2126
2127 pkt->pktns->tx.in_flight -= pkt->in_flight_len;
2128 qc->path->prep_in_flight -= pkt->in_flight_len;
2129 qc->path->in_flight -= pkt->in_flight_len;
2130 if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
2131 qc->path->ifae_pkts--;
2132 /* Treat the frames of this lost packet. */
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002133 if (!qc_requeue_nacked_pkt_tx_frms(qc, pkt, &pktns->tx.frms))
2134 close = 1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002135 LIST_DELETE(&pkt->list);
2136 if (!oldest_lost) {
2137 oldest_lost = newest_lost = pkt;
2138 }
2139 else {
2140 if (newest_lost != oldest_lost)
2141 quic_tx_packet_refdec(newest_lost);
2142 newest_lost = pkt;
2143 }
2144 }
2145
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002146 if (!close) {
2147 if (newest_lost) {
2148 /* Sent a congestion event to the controller */
2149 struct quic_cc_event ev = { };
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002150
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002151 ev.type = QUIC_CC_EVT_LOSS;
2152 ev.loss.time_sent = newest_lost->time_sent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002153
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002154 quic_cc_event(&qc->path->cc, &ev);
2155 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002156
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002157 /* If an RTT have been already sampled, <rtt_min> has been set.
2158 * We must check if we are experiencing a persistent congestion.
2159 * If this is the case, the congestion controller must re-enter
2160 * slow start state.
2161 */
2162 if (qc->path->loss.rtt_min && newest_lost != oldest_lost) {
2163 unsigned int period = newest_lost->time_sent - oldest_lost->time_sent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002164
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002165 if (quic_loss_persistent_congestion(&qc->path->loss, period,
2166 now_ms, qc->max_ack_delay))
2167 qc->path->cc.algo->slow_start(&qc->path->cc);
2168 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002169 }
2170
Amaury Denoyelle3a72ba22022-11-14 11:41:34 +01002171 /* <oldest_lost> cannot be NULL at this stage because we have ensured
2172 * that <pkts> list is not empty. Without this, GCC 12.2.0 reports a
2173 * possible overflow on a 0 byte region with O2 optimization.
2174 */
2175 ALREADY_CHECKED(oldest_lost);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002176 quic_tx_packet_refdec(oldest_lost);
2177 if (newest_lost != oldest_lost)
2178 quic_tx_packet_refdec(newest_lost);
2179
2180 leave:
2181 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002182 return !close;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002183}
2184
2185/* Parse ACK frame into <frm> from a buffer at <buf> address with <end> being at
2186 * one byte past the end of this buffer. Also update <rtt_sample> if needed, i.e.
2187 * if the largest acked packet was newly acked and if there was at least one newly
2188 * acked ack-eliciting packet.
2189 * Return 1, if succeeded, 0 if not.
2190 */
2191static inline int qc_parse_ack_frm(struct quic_conn *qc,
2192 struct quic_frame *frm,
2193 struct quic_enc_level *qel,
2194 unsigned int *rtt_sample,
2195 const unsigned char **pos, const unsigned char *end)
2196{
2197 struct quic_ack *ack = &frm->ack;
2198 uint64_t smallest, largest;
2199 struct eb_root *pkts;
2200 struct eb64_node *largest_node;
2201 unsigned int time_sent, pkt_flags;
2202 struct list newly_acked_pkts = LIST_HEAD_INIT(newly_acked_pkts);
2203 struct list lost_pkts = LIST_HEAD_INIT(lost_pkts);
2204 int ret = 0;
2205
2206 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2207
2208 if (ack->largest_ack > qel->pktns->tx.next_pn) {
2209 TRACE_DEVEL("ACK for not sent packet", QUIC_EV_CONN_PRSAFRM,
2210 qc, NULL, &ack->largest_ack);
2211 goto err;
2212 }
2213
2214 if (ack->first_ack_range > ack->largest_ack) {
2215 TRACE_DEVEL("too big first ACK range", QUIC_EV_CONN_PRSAFRM,
2216 qc, NULL, &ack->first_ack_range);
2217 goto err;
2218 }
2219
2220 largest = ack->largest_ack;
2221 smallest = largest - ack->first_ack_range;
2222 pkts = &qel->pktns->tx.pkts;
2223 pkt_flags = 0;
2224 largest_node = NULL;
2225 time_sent = 0;
2226
2227 if ((int64_t)ack->largest_ack > qel->pktns->rx.largest_acked_pn) {
2228 largest_node = eb64_lookup(pkts, largest);
2229 if (!largest_node) {
2230 TRACE_DEVEL("Largest acked packet not found",
2231 QUIC_EV_CONN_PRSAFRM, qc);
2232 }
2233 else {
2234 time_sent = eb64_entry(largest_node,
2235 struct quic_tx_packet, pn_node)->time_sent;
2236 }
2237 }
2238
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002239 TRACE_PROTO("RX ack range", QUIC_EV_CONN_PRSAFRM,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002240 qc, NULL, &largest, &smallest);
2241 do {
2242 uint64_t gap, ack_range;
2243
2244 qc_ackrng_pkts(qc, pkts, &pkt_flags, &newly_acked_pkts,
2245 largest_node, largest, smallest);
2246 if (!ack->ack_range_num--)
2247 break;
2248
2249 if (!quic_dec_int(&gap, pos, end)) {
2250 TRACE_ERROR("quic_dec_int(gap) failed", QUIC_EV_CONN_PRSAFRM, qc);
2251 goto err;
2252 }
2253
2254 if (smallest < gap + 2) {
2255 TRACE_DEVEL("wrong gap value", QUIC_EV_CONN_PRSAFRM,
2256 qc, NULL, &gap, &smallest);
2257 goto err;
2258 }
2259
2260 largest = smallest - gap - 2;
2261 if (!quic_dec_int(&ack_range, pos, end)) {
2262 TRACE_ERROR("quic_dec_int(ack_range) failed", QUIC_EV_CONN_PRSAFRM, qc);
2263 goto err;
2264 }
2265
2266 if (largest < ack_range) {
2267 TRACE_DEVEL("wrong ack range value", QUIC_EV_CONN_PRSAFRM,
2268 qc, NULL, &largest, &ack_range);
2269 goto err;
2270 }
2271
2272 /* Do not use this node anymore. */
2273 largest_node = NULL;
2274 /* Next range */
2275 smallest = largest - ack_range;
2276
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002277 TRACE_PROTO("RX next ack range", QUIC_EV_CONN_PRSAFRM,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002278 qc, NULL, &largest, &smallest);
2279 } while (1);
2280
2281 if (time_sent && (pkt_flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
2282 *rtt_sample = tick_remain(time_sent, now_ms);
2283 qel->pktns->rx.largest_acked_pn = ack->largest_ack;
2284 }
2285
2286 if (!LIST_ISEMPTY(&newly_acked_pkts)) {
2287 if (!eb_is_empty(&qel->pktns->tx.pkts)) {
2288 qc_packet_loss_lookup(qel->pktns, qc, &lost_pkts);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002289 if (!qc_release_lost_pkts(qc, qel->pktns, &lost_pkts, now_ms))
2290 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002291 }
2292 qc_treat_newly_acked_pkts(qc, &newly_acked_pkts);
2293 if (quic_peer_validated_addr(qc))
2294 qc->path->loss.pto_count = 0;
2295 qc_set_timer(qc);
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01002296 qc_notify_send(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002297 }
2298
2299 ret = 1;
2300 leave:
2301 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2302 return ret;
2303
2304 err:
2305 free_quic_tx_pkts(qc, &newly_acked_pkts);
2306 goto leave;
2307}
2308
2309/* This function gives the detail of the SSL error. It is used only
2310 * if the debug mode and the verbose mode are activated. It dump all
2311 * the SSL error until the stack was empty.
2312 */
2313static forceinline void qc_ssl_dump_errors(struct connection *conn)
2314{
2315 if (unlikely(global.mode & MODE_DEBUG)) {
2316 while (1) {
2317 const char *func = NULL;
2318 unsigned long ret;
2319
2320 ERR_peek_error_func(&func);
2321 ret = ERR_get_error();
2322 if (!ret)
2323 return;
2324
2325 fprintf(stderr, "conn. @%p OpenSSL error[0x%lx] %s: %s\n", conn, ret,
2326 func, ERR_reason_error_string(ret));
2327 }
2328 }
2329}
2330
2331int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx,
2332 const char **str, int *len);
2333
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002334/* Finalize <qc> QUIC connection:
2335 * - initialize the Initial QUIC TLS context for negotiated version,
2336 * - derive the secrets for this context,
2337 * - set them into the TLS stack,
2338 *
2339 * MUST be called after having received the remote transport parameters which
2340 * are parsed when the TLS callback for the ClientHello message is called upon
2341 * SSL_do_handshake() calls, not necessarily at the first time as this TLS
Ilya Shipitsin07be66d2023-04-01 12:26:42 +02002342 * message may be split between packets
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002343 * Return 1 if succeeded, 0 if not.
2344 */
2345static int qc_conn_finalize(struct quic_conn *qc, int server)
2346{
2347 int ret = 0;
2348
2349 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
2350
2351 if (qc->flags & QUIC_FL_CONN_FINALIZED)
2352 goto finalized;
2353
2354 if (qc->negotiated_version &&
2355 !qc_new_isecs(qc, &qc->negotiated_ictx, qc->negotiated_version,
2356 qc->odcid.data, qc->odcid.len, server))
2357 goto out;
2358
2359 /* This connection is functional (ready to send/receive) */
2360 qc->flags |= QUIC_FL_CONN_FINALIZED;
2361
2362 finalized:
2363 ret = 1;
2364 out:
2365 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
2366 return ret;
2367}
2368
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002369/* Provide CRYPTO data to the TLS stack found at <data> with <len> as length
2370 * from <qel> encryption level with <ctx> as QUIC connection context.
2371 * Remaining parameter are there for debugging purposes.
2372 * Return 1 if succeeded, 0 if not.
2373 */
2374static inline int qc_provide_cdata(struct quic_enc_level *el,
2375 struct ssl_sock_ctx *ctx,
2376 const unsigned char *data, size_t len,
2377 struct quic_rx_packet *pkt,
2378 struct quic_rx_crypto_frm *cf)
2379{
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01002380#ifdef DEBUG_STRICT
2381 enum ncb_ret ncb_ret;
2382#endif
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002383 int ssl_err, state;
2384 struct quic_conn *qc;
2385 int ret = 0;
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002386 struct ncbuf *ncbuf = &el->cstream->rx.ncbuf;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002387
2388 ssl_err = SSL_ERROR_NONE;
2389 qc = ctx->qc;
2390
2391 TRACE_ENTER(QUIC_EV_CONN_SSLDATA, qc);
2392
2393 if (SSL_provide_quic_data(ctx->ssl, el->level, data, len) != 1) {
2394 TRACE_ERROR("SSL_provide_quic_data() error",
2395 QUIC_EV_CONN_SSLDATA, qc, pkt, cf, ctx->ssl);
2396 goto leave;
2397 }
2398
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002399 TRACE_PROTO("in order CRYPTO data",
2400 QUIC_EV_CONN_SSLDATA, qc, NULL, cf, ctx->ssl);
2401
2402 state = qc->state;
2403 if (state < QUIC_HS_ST_COMPLETE) {
2404 ssl_err = SSL_do_handshake(ctx->ssl);
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002405
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01002406 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
2407 TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_IO_CB, qc);
2408 goto leave;
2409 }
2410
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002411 /* Finalize the connection as soon as possible if the peer transport parameters
2412 * have been received. This may be useful to send packets even if this
2413 * handshake fails.
2414 */
2415 if ((qc->flags & QUIC_FL_CONN_TX_TP_RECEIVED) && !qc_conn_finalize(qc, 1)) {
2416 TRACE_ERROR("connection finalization failed", QUIC_EV_CONN_IO_CB, qc, &state);
2417 goto leave;
2418 }
2419
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002420 if (ssl_err != 1) {
2421 ssl_err = SSL_get_error(ctx->ssl, ssl_err);
2422 if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
2423 TRACE_PROTO("SSL handshake in progress",
2424 QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2425 goto out;
2426 }
2427
2428 /* TODO: Should close the connection asap */
2429 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
2430 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
2431 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
2432 HA_ATOMIC_INC(&qc->prx_counters->hdshk_fail);
2433 }
2434 TRACE_ERROR("SSL handshake error", QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2435 qc_ssl_dump_errors(ctx->conn);
2436 ERR_clear_error();
2437 goto leave;
2438 }
2439
2440 TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
2441
2442 /* Check the alpn could be negotiated */
2443 if (!qc->app_ops) {
2444 TRACE_ERROR("No negotiated ALPN", QUIC_EV_CONN_IO_CB, qc, &state);
2445 quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL);
2446 goto leave;
2447 }
2448
2449 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
2450 TRACE_DEVEL("dec half open counter", QUIC_EV_CONN_IO_CB, qc, &state);
2451 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
2452 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
2453 }
2454 /* I/O callback switch */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02002455 qc->wait_event.tasklet->process = quic_conn_app_io_cb;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002456 if (qc_is_listener(ctx->qc)) {
2457 qc->state = QUIC_HS_ST_CONFIRMED;
2458 /* The connection is ready to be accepted. */
2459 quic_accept_push_qc(qc);
2460 }
2461 else {
2462 qc->state = QUIC_HS_ST_COMPLETE;
2463 }
2464
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02002465 /* Prepare the next key update */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002466 if (!quic_tls_key_update(qc)) {
2467 TRACE_ERROR("quic_tls_key_update() failed", QUIC_EV_CONN_IO_CB, qc);
2468 goto leave;
2469 }
2470 } else {
2471 ssl_err = SSL_process_quic_post_handshake(ctx->ssl);
2472 if (ssl_err != 1) {
2473 ssl_err = SSL_get_error(ctx->ssl, ssl_err);
2474 if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
2475 TRACE_PROTO("SSL post handshake in progress",
2476 QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2477 goto out;
2478 }
2479
2480 TRACE_ERROR("SSL post handshake error",
2481 QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2482 goto leave;
2483 }
2484
2485 TRACE_STATE("SSL post handshake succeeded", QUIC_EV_CONN_IO_CB, qc, &state);
2486 }
2487
2488 out:
2489 ret = 1;
2490 leave:
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002491 /* The CRYPTO data are consumed even in case of an error to release
2492 * the memory asap.
2493 */
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01002494 if (!ncb_is_null(ncbuf)) {
2495#ifdef DEBUG_STRICT
2496 ncb_ret = ncb_advance(ncbuf, len);
2497 /* ncb_advance() must always succeed. This is guaranteed as
2498 * this is only done inside a data block. If false, this will
2499 * lead to handshake failure with quic_enc_level offset shifted
2500 * from buffer data.
2501 */
2502 BUG_ON(ncb_ret != NCB_RET_OK);
2503#else
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002504 ncb_advance(ncbuf, len);
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01002505#endif
2506 }
2507
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002508 TRACE_LEAVE(QUIC_EV_CONN_SSLDATA, qc);
2509 return ret;
2510}
2511
Amaury Denoyelle2216b082023-02-02 14:59:36 +01002512/* Parse a STREAM frame <strm_frm> received in <pkt> packet for <qc>
2513 * connection. <fin> is true if FIN bit is set on frame type.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002514 *
2515 * Return 1 on success. On error, 0 is returned. In this case, the packet
2516 * containing the frame must not be acknowledged.
2517 */
2518static inline int qc_handle_strm_frm(struct quic_rx_packet *pkt,
2519 struct quic_stream *strm_frm,
Amaury Denoyelle2216b082023-02-02 14:59:36 +01002520 struct quic_conn *qc, char fin)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002521{
2522 int ret;
2523
2524 /* RFC9000 13.1. Packet Processing
2525 *
2526 * A packet MUST NOT be acknowledged until packet protection has been
2527 * successfully removed and all frames contained in the packet have
2528 * been processed. For STREAM frames, this means the data has been
2529 * enqueued in preparation to be received by the application protocol,
2530 * but it does not require that data be delivered and consumed.
2531 */
2532 TRACE_ENTER(QUIC_EV_CONN_PRSFRM, qc);
2533
2534 ret = qcc_recv(qc->qcc, strm_frm->id, strm_frm->len,
Amaury Denoyelle2216b082023-02-02 14:59:36 +01002535 strm_frm->offset.key, fin, (char *)strm_frm->data);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002536
2537 /* frame rejected - packet must not be acknowledeged */
2538 TRACE_LEAVE(QUIC_EV_CONN_PRSFRM, qc);
2539 return !ret;
2540}
2541
2542/* Duplicate all frames from <pkt_frm_list> list into <out_frm_list> list
2543 * for <qc> QUIC connection.
2544 * This is a best effort function which never fails even if no memory could be
2545 * allocated to duplicate these frames.
2546 */
2547static void qc_dup_pkt_frms(struct quic_conn *qc,
2548 struct list *pkt_frm_list, struct list *out_frm_list)
2549{
2550 struct quic_frame *frm, *frmbak;
2551 struct list tmp = LIST_HEAD_INIT(tmp);
2552
2553 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2554
2555 list_for_each_entry_safe(frm, frmbak, pkt_frm_list, list) {
2556 struct quic_frame *dup_frm, *origin;
2557
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002558 if (frm->flags & QUIC_FL_TX_FRAME_ACKED) {
2559 TRACE_DEVEL("already acknowledged frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
2560 continue;
2561 }
2562
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002563 switch (frm->type) {
2564 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
2565 {
2566 struct quic_stream *strm_frm = &frm->stream;
2567 struct eb64_node *node = NULL;
2568 struct qc_stream_desc *stream_desc;
2569
2570 node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
2571 if (!node) {
2572 TRACE_DEVEL("ignored frame for a released stream", QUIC_EV_CONN_PRSAFRM, qc, frm);
2573 continue;
2574 }
2575
2576 stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
2577 /* Do not resend this frame if in the "already acked range" */
2578 if (strm_frm->offset.key + strm_frm->len <= stream_desc->ack_offset) {
2579 TRACE_DEVEL("ignored frame in already acked range",
2580 QUIC_EV_CONN_PRSAFRM, qc, frm);
2581 continue;
2582 }
2583 else if (strm_frm->offset.key < stream_desc->ack_offset) {
Frédéric Lécailleca079792023-03-17 08:56:50 +01002584 uint64_t diff = stream_desc->ack_offset - strm_frm->offset.key;
2585
Frédéric Lécaillec425e032023-03-20 14:32:59 +01002586 qc_stream_frm_mv_fwd(frm, diff);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002587 TRACE_DEVEL("updated partially acked frame",
2588 QUIC_EV_CONN_PRSAFRM, qc, frm);
2589 }
Amaury Denoyellec8a0efb2023-02-22 10:44:27 +01002590
2591 strm_frm->dup = 1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002592 break;
2593 }
2594
2595 default:
2596 break;
2597 }
2598
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002599 /* If <frm> is already a copy of another frame, we must take
2600 * its original frame as source for the copy.
2601 */
2602 origin = frm->origin ? frm->origin : frm;
2603 dup_frm = qc_frm_dup(origin);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002604 if (!dup_frm) {
2605 TRACE_ERROR("could not duplicate frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
2606 break;
2607 }
2608
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002609 TRACE_DEVEL("built probing frame", QUIC_EV_CONN_PRSAFRM, qc, origin);
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002610 if (origin->pkt) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002611 TRACE_DEVEL("duplicated from packet", QUIC_EV_CONN_PRSAFRM,
2612 qc, NULL, &origin->pkt->pn_node.key);
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002613 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002614 else {
2615 /* <origin> is a frame which was sent from a packet detected as lost. */
2616 TRACE_DEVEL("duplicated from lost packet", QUIC_EV_CONN_PRSAFRM, qc);
2617 }
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002618
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002619 LIST_APPEND(&tmp, &dup_frm->list);
2620 }
2621
2622 LIST_SPLICE(out_frm_list, &tmp);
2623
2624 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2625}
2626
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002627/* Boolean function which return 1 if <pkt> TX packet is only made of
2628 * already acknowledged frame.
2629 */
2630static inline int qc_pkt_with_only_acked_frms(struct quic_tx_packet *pkt)
2631{
2632 struct quic_frame *frm;
2633
2634 list_for_each_entry(frm, &pkt->frms, list)
2635 if (!(frm->flags & QUIC_FL_TX_FRAME_ACKED))
2636 return 0;
2637
2638 return 1;
2639}
2640
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002641/* Prepare a fast retransmission from <qel> encryption level */
2642static void qc_prep_fast_retrans(struct quic_conn *qc,
2643 struct quic_enc_level *qel,
2644 struct list *frms1, struct list *frms2)
2645{
2646 struct eb_root *pkts = &qel->pktns->tx.pkts;
2647 struct list *frms = frms1;
2648 struct eb64_node *node;
2649 struct quic_tx_packet *pkt;
2650
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002651 TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002652
2653 BUG_ON(frms1 == frms2);
2654
2655 pkt = NULL;
2656 node = eb64_first(pkts);
2657 start:
2658 while (node) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002659 struct quic_tx_packet *p;
2660
2661 p = eb64_entry(node, struct quic_tx_packet, pn_node);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002662 node = eb64_next(node);
2663 /* Skip the empty and coalesced packets */
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002664 TRACE_PRINTF(TRACE_LEVEL_PROTO, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002665 "--> pn=%llu (%d %d %d)", (ull)p->pn_node.key,
2666 LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED),
2667 qc_pkt_with_only_acked_frms(p));
2668 if (!LIST_ISEMPTY(&p->frms) && !qc_pkt_with_only_acked_frms(p)) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002669 pkt = p;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002670 break;
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002671 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002672 }
2673
2674 if (!pkt)
2675 goto leave;
2676
2677 /* When building a packet from another one, the field which may increase the
2678 * packet size is the packet number. And the maximum increase is 4 bytes.
2679 */
2680 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc) &&
2681 pkt->len + 4 > 3 * qc->rx.bytes - qc->tx.prep_bytes) {
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01002682 qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002683 TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt);
2684 goto leave;
2685 }
2686
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002687 TRACE_PROTO("duplicating packet", QUIC_EV_CONN_SPPKTS, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002688 qc_dup_pkt_frms(qc, &pkt->frms, frms);
2689 if (frms == frms1 && frms2) {
2690 frms = frms2;
2691 goto start;
2692 }
2693 leave:
2694 TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
2695}
2696
2697/* Prepare a fast retransmission during a handshake after a client
2698 * has resent Initial packets. According to the RFC a server may retransmit
2699 * Initial packets send them coalescing with others (Handshake here).
2700 * (Listener only function).
2701 */
2702static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc,
2703 struct list *ifrms, struct list *hfrms)
2704{
2705 struct list itmp = LIST_HEAD_INIT(itmp);
2706 struct list htmp = LIST_HEAD_INIT(htmp);
2707
2708 struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
2709 struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
2710 struct quic_enc_level *qel = iqel;
2711 struct eb_root *pkts;
2712 struct eb64_node *node;
2713 struct quic_tx_packet *pkt;
2714 struct list *tmp = &itmp;
2715
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002716 TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002717 start:
2718 pkt = NULL;
2719 pkts = &qel->pktns->tx.pkts;
2720 node = eb64_first(pkts);
2721 /* Skip the empty packet (they have already been retransmitted) */
2722 while (node) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002723 struct quic_tx_packet *p;
2724
2725 p = eb64_entry(node, struct quic_tx_packet, pn_node);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002726 TRACE_PRINTF(TRACE_LEVEL_PROTO, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002727 "--> pn=%llu (%d %d)", (ull)p->pn_node.key,
2728 LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED));
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002729 if (!LIST_ISEMPTY(&p->frms) && !(p->flags & QUIC_FL_TX_PACKET_COALESCED) &&
2730 !qc_pkt_with_only_acked_frms(p)) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002731 pkt = p;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002732 break;
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002733 }
2734
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002735 node = eb64_next(node);
2736 }
2737
2738 if (!pkt)
2739 goto end;
2740
2741 /* When building a packet from another one, the field which may increase the
2742 * packet size is the packet number. And the maximum increase is 4 bytes.
2743 */
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002744 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
2745 size_t dglen = pkt->len + 4;
2746
2747 dglen += pkt->next ? pkt->next->len + 4 : 0;
2748 if (dglen > 3 * qc->rx.bytes - qc->tx.prep_bytes) {
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01002749 qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002750 TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt);
2751 if (pkt->next)
2752 TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt->next);
2753 goto end;
2754 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002755 }
2756
2757 qel->pktns->tx.pto_probe += 1;
2758
2759 /* No risk to loop here, #packet per datagram is bounded */
2760 requeue:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002761 TRACE_PROTO("duplicating packet", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002762 qc_dup_pkt_frms(qc, &pkt->frms, tmp);
2763 if (qel == iqel) {
2764 if (pkt->next && pkt->next->type == QUIC_PACKET_TYPE_HANDSHAKE) {
2765 pkt = pkt->next;
2766 tmp = &htmp;
2767 hqel->pktns->tx.pto_probe += 1;
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002768 TRACE_DEVEL("looping for next packet", QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002769 goto requeue;
2770 }
2771 }
2772
2773 end:
2774 LIST_SPLICE(ifrms, &itmp);
2775 LIST_SPLICE(hfrms, &htmp);
2776
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002777 TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002778}
2779
2780static void qc_cc_err_count_inc(struct quic_conn *qc, struct quic_frame *frm)
2781{
2782 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
2783
2784 if (frm->type == QUIC_FT_CONNECTION_CLOSE)
2785 quic_stats_transp_err_count_inc(qc->prx_counters, frm->connection_close.error_code);
2786 else if (frm->type == QUIC_FT_CONNECTION_CLOSE_APP) {
2787 if (qc->mux_state != QC_MUX_READY || !qc->qcc->app_ops->inc_err_cnt)
2788 goto out;
2789
2790 qc->qcc->app_ops->inc_err_cnt(qc->qcc->ctx, frm->connection_close_app.error_code);
2791 }
2792
2793 out:
2794 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
2795}
2796
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002797/* Cancel a request on connection <qc> for stream id <id>. This is useful when
2798 * the client opens a new stream but the MUX has already been released. A
Amaury Denoyelle75463012023-02-20 10:31:27 +01002799 * STOP_SENDING + RESET_STREAM frames are prepared for emission.
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002800 *
2801 * TODO this function is closely related to H3. Its place should be in H3 layer
2802 * instead of quic-conn but this requires an architecture adjustment.
2803 *
Ilya Shipitsin07be66d2023-04-01 12:26:42 +02002804 * Returns 1 on success else 0.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002805 */
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002806static int qc_h3_request_reject(struct quic_conn *qc, uint64_t id)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002807{
2808 int ret = 0;
Amaury Denoyelle75463012023-02-20 10:31:27 +01002809 struct quic_frame *ss, *rs;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002810 struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002811 const uint64_t app_error_code = H3_REQUEST_REJECTED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002812
2813 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2814
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002815 /* Do not emit rejection for unknown unidirectional stream as it is
2816 * forbidden to close some of them (H3 control stream and QPACK
2817 * encoder/decoder streams).
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002818 */
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002819 if (quic_stream_is_uni(id)) {
2820 ret = 1;
2821 goto out;
2822 }
2823
Amaury Denoyelle75463012023-02-20 10:31:27 +01002824 ss = qc_frm_alloc(QUIC_FT_STOP_SENDING);
2825 if (!ss) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002826 TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
2827 goto out;
2828 }
2829
Amaury Denoyelle75463012023-02-20 10:31:27 +01002830 ss->stop_sending.id = id;
2831 ss->stop_sending.app_error_code = app_error_code;
2832
2833 rs = qc_frm_alloc(QUIC_FT_RESET_STREAM);
2834 if (!rs) {
2835 TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
2836 qc_frm_free(&ss);
2837 goto out;
2838 }
2839
2840 rs->reset_stream.id = id;
2841 rs->reset_stream.app_error_code = app_error_code;
2842 rs->reset_stream.final_size = 0;
2843
2844 LIST_APPEND(&qel->pktns->tx.frms, &ss->list);
2845 LIST_APPEND(&qel->pktns->tx.frms, &rs->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002846 ret = 1;
2847 out:
2848 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2849 return ret;
2850}
2851
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002852/* Release the underlying memory use by <ncbuf> non-contiguous buffer */
2853static void quic_free_ncbuf(struct ncbuf *ncbuf)
2854{
2855 struct buffer buf;
2856
2857 if (ncb_is_null(ncbuf))
2858 return;
2859
2860 buf = b_make(ncbuf->area, ncbuf->size, 0, 0);
2861 b_free(&buf);
2862 offer_buffers(NULL, 1);
2863
2864 *ncbuf = NCBUF_NULL;
2865}
2866
2867/* Allocate the underlying required memory for <ncbuf> non-contiguous buffer */
2868static struct ncbuf *quic_get_ncbuf(struct ncbuf *ncbuf)
2869{
2870 struct buffer buf = BUF_NULL;
2871
2872 if (!ncb_is_null(ncbuf))
2873 return ncbuf;
2874
2875 b_alloc(&buf);
2876 BUG_ON(b_is_null(&buf));
2877
2878 *ncbuf = ncb_make(buf.area, buf.size, 0);
2879 ncb_init(ncbuf, 0);
2880
2881 return ncbuf;
2882}
2883
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002884/* Parse <frm> CRYPTO frame coming with <pkt> packet at <qel> <qc> connectionn.
2885 * Returns 1 if succeeded, 0 if not. Also set <*fast_retrans> to 1 if the
2886 * speed up handshake completion may be run after having received duplicated
2887 * CRYPTO data.
2888 */
2889static int qc_handle_crypto_frm(struct quic_conn *qc,
2890 struct quic_crypto *frm, struct quic_rx_packet *pkt,
2891 struct quic_enc_level *qel, int *fast_retrans)
2892{
2893 int ret = 0;
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002894 enum ncb_ret ncb_ret;
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002895 /* XXX TO DO: <cfdebug> is used only for the traces. */
2896 struct quic_rx_crypto_frm cfdebug = {
2897 .offset_node.key = frm->offset,
2898 .len = frm->len,
2899 };
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002900 struct quic_cstream *cstream = qel->cstream;
2901 struct ncbuf *ncbuf = &qel->cstream->rx.ncbuf;
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002902
2903 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2904 if (unlikely(qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD)) {
2905 TRACE_PROTO("CRYPTO data discarded",
2906 QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2907 goto done;
2908 }
2909
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002910 if (unlikely(frm->offset < cstream->rx.offset)) {
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002911 size_t diff;
2912
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002913 if (frm->offset + frm->len <= cstream->rx.offset) {
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002914 /* Nothing to do */
2915 TRACE_PROTO("Already received CRYPTO data",
2916 QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2917 if (qc_is_listener(qc) && qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] &&
2918 !(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP))
2919 *fast_retrans = 1;
2920 goto done;
2921 }
2922
2923 TRACE_PROTO("Partially already received CRYPTO data",
2924 QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2925
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002926 diff = cstream->rx.offset - frm->offset;
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002927 frm->len -= diff;
2928 frm->data += diff;
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002929 frm->offset = cstream->rx.offset;
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002930 }
2931
Amaury Denoyelleff95f2d2022-11-18 14:50:06 +01002932 if (frm->offset == cstream->rx.offset && ncb_is_empty(ncbuf)) {
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002933 if (!qc_provide_cdata(qel, qc->xprt_ctx, frm->data, frm->len,
2934 pkt, &cfdebug)) {
2935 // trace already emitted by function above
2936 goto leave;
2937 }
2938
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002939 cstream->rx.offset += frm->len;
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01002940 TRACE_DEVEL("increment crypto level offset", QUIC_EV_CONN_PHPKTS, qc, qel);
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002941 goto done;
2942 }
2943
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002944 if (!quic_get_ncbuf(ncbuf) ||
2945 ncb_is_null(ncbuf)) {
2946 TRACE_ERROR("CRYPTO ncbuf allocation failed", QUIC_EV_CONN_PRSHPKT, qc);
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002947 goto leave;
2948 }
2949
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002950 /* frm->offset > cstream-trx.offset */
2951 ncb_ret = ncb_add(ncbuf, frm->offset - cstream->rx.offset,
2952 (const char *)frm->data, frm->len, NCB_ADD_COMPARE);
2953 if (ncb_ret != NCB_RET_OK) {
2954 if (ncb_ret == NCB_RET_DATA_REJ) {
2955 TRACE_ERROR("overlapping data rejected", QUIC_EV_CONN_PRSHPKT, qc);
2956 quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
2957 }
2958 else if (ncb_ret == NCB_RET_GAP_SIZE) {
2959 TRACE_ERROR("cannot bufferize frame due to gap size limit",
2960 QUIC_EV_CONN_PRSHPKT, qc);
2961 }
2962 goto leave;
2963 }
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002964
2965 done:
2966 ret = 1;
2967 leave:
2968 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2969 return ret;
2970}
2971
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01002972/* Allocate a new connection ID for <qc> connection and build a NEW_CONNECTION_ID
2973 * frame to be sent.
2974 * Return 1 if succeeded, 0 if not.
2975 */
2976static int qc_build_new_connection_id_frm(struct quic_conn *qc,
2977 struct quic_connection_id *cid)
2978{
2979 int ret = 0;
2980 struct quic_frame *frm;
2981 struct quic_enc_level *qel;
2982
2983 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2984
2985 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
2986 frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID);
2987 if (!frm) {
2988 TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
2989 goto leave;
2990 }
2991
2992 quic_connection_id_to_frm_cpy(frm, cid);
2993 LIST_APPEND(&qel->pktns->tx.frms, &frm->list);
2994 ret = 1;
2995 leave:
2996 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2997 return ret;
2998}
2999
3000
3001/* Handle RETIRE_CONNECTION_ID frame from <frm> frame.
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003002 * Return 1 if succeeded, 0 if not. If succeeded, also set <cid_to_retire>
3003 * to the CID to be retired if not already retired.
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003004 */
3005static int qc_handle_retire_connection_id_frm(struct quic_conn *qc,
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003006 struct quic_frame *frm,
3007 struct quic_cid *dcid,
3008 struct quic_connection_id **cid_to_retire)
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003009{
3010 int ret = 0;
3011 struct quic_retire_connection_id *rcid = &frm->retire_connection_id;
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003012 struct eb64_node *node;
3013 struct quic_connection_id *cid;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003014
3015 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
3016
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003017 /* RFC 9000 19.16. RETIRE_CONNECTION_ID Frames:
3018 * Receipt of a RETIRE_CONNECTION_ID frame containing a sequence number greater
3019 * than any previously sent to the peer MUST be treated as a connection error
3020 * of type PROTOCOL_VIOLATION.
3021 */
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003022 if (rcid->seq_num >= qc->next_cid_seq_num) {
3023 TRACE_PROTO("CID seq. number too big", QUIC_EV_CONN_PSTRM, qc, frm);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003024 goto protocol_violation;
3025 }
3026
3027 /* RFC 9000 19.16. RETIRE_CONNECTION_ID Frames:
3028 * The sequence number specified in a RETIRE_CONNECTION_ID frame MUST NOT refer to
3029 * the Destination Connection ID field of the packet in which the frame is contained.
3030 * The peer MAY treat this as a connection error of type PROTOCOL_VIOLATION.
3031 */
3032 node = eb64_lookup(&qc->cids, rcid->seq_num);
3033 if (!node) {
3034 TRACE_PROTO("CID already retired", QUIC_EV_CONN_PSTRM, qc, frm);
3035 goto out;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003036 }
3037
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003038 cid = eb64_entry(node, struct quic_connection_id, seq_num);
3039 /* Note that the length of <dcid> has already been checked. It must match the
3040 * length of the CIDs which have been provided to the peer.
3041 */
3042 if (!memcmp(dcid->data, cid->cid.data, QUIC_HAP_CID_LEN)) {
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003043 TRACE_PROTO("cannot retire the current CID", QUIC_EV_CONN_PSTRM, qc, frm);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003044 goto protocol_violation;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003045 }
3046
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003047 *cid_to_retire = cid;
3048 out:
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003049 ret = 1;
3050 leave:
3051 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
3052 return ret;
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003053 protocol_violation:
3054 quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
3055 goto leave;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003056}
3057
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01003058/* Remove a <qc> quic-conn from its ha_thread_ctx list. If <closing> is true,
3059 * it will immediately be reinserted in the ha_thread_ctx quic_conns_clo list.
3060 */
3061static void qc_detach_th_ctx_list(struct quic_conn *qc, int closing)
3062{
3063 struct bref *bref, *back;
3064
3065 /* Detach CLI context watchers currently dumping this connection.
3066 * Reattach them to the next quic_conn instance.
3067 */
3068 list_for_each_entry_safe(bref, back, &qc->back_refs, users) {
3069 /* Remove watcher from this quic_conn instance. */
3070 LIST_DEL_INIT(&bref->users);
3071
3072 /* Attach it to next instance unless it was the last list element. */
3073 if (qc->el_th_ctx.n != &th_ctx->quic_conns &&
3074 qc->el_th_ctx.n != &th_ctx->quic_conns_clo) {
3075 struct quic_conn *next = LIST_NEXT(&qc->el_th_ctx,
3076 struct quic_conn *,
3077 el_th_ctx);
3078 LIST_APPEND(&next->back_refs, &bref->users);
3079 }
3080 bref->ref = qc->el_th_ctx.n;
3081 __ha_barrier_store();
3082 }
3083
3084 /* Remove quic_conn from global ha_thread_ctx list. */
3085 LIST_DEL_INIT(&qc->el_th_ctx);
3086
3087 if (closing)
3088 LIST_APPEND(&th_ctx->quic_conns_clo, &qc->el_th_ctx);
3089}
3090
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003091/* Parse all the frames of <pkt> QUIC packet for QUIC connection <qc> and <qel>
3092 * as encryption level.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003093 * Returns 1 if succeeded, 0 if failed.
3094 */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003095static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003096 struct quic_enc_level *qel)
3097{
3098 struct quic_frame frm;
3099 const unsigned char *pos, *end;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003100 int fast_retrans = 0, ret = 0;
3101
3102 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
3103 /* Skip the AAD */
3104 pos = pkt->data + pkt->aad_len;
3105 end = pkt->data + pkt->len;
3106
3107 while (pos < end) {
3108 if (!qc_parse_frm(&frm, pkt, &pos, end, qc)) {
3109 // trace already emitted by function above
3110 goto leave;
3111 }
3112
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003113 switch (frm.type) {
3114 case QUIC_FT_PADDING:
3115 break;
3116 case QUIC_FT_PING:
3117 break;
3118 case QUIC_FT_ACK:
3119 {
3120 unsigned int rtt_sample;
3121
Frédéric Lécaille809bd9f2023-04-06 13:13:08 +02003122 rtt_sample = UINT_MAX;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003123 if (!qc_parse_ack_frm(qc, &frm, qel, &rtt_sample, &pos, end)) {
3124 // trace already emitted by function above
3125 goto leave;
3126 }
3127
Frédéric Lécaille809bd9f2023-04-06 13:13:08 +02003128 if (rtt_sample != UINT_MAX) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003129 unsigned int ack_delay;
3130
3131 ack_delay = !quic_application_pktns(qel->pktns, qc) ? 0 :
3132 qc->state >= QUIC_HS_ST_CONFIRMED ?
3133 MS_TO_TICKS(QUIC_MIN(quic_ack_delay_ms(&frm.ack, qc), qc->max_ack_delay)) :
3134 MS_TO_TICKS(quic_ack_delay_ms(&frm.ack, qc));
3135 quic_loss_srtt_update(&qc->path->loss, rtt_sample, ack_delay, qc);
3136 }
3137 break;
3138 }
3139 case QUIC_FT_RESET_STREAM:
Amaury Denoyelle5854fc02022-12-09 16:25:48 +01003140 if (qc->mux_state == QC_MUX_READY) {
3141 struct quic_reset_stream *rs = &frm.reset_stream;
3142 qcc_recv_reset_stream(qc->qcc, rs->id, rs->app_error_code, rs->final_size);
3143 }
3144 break;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003145 case QUIC_FT_STOP_SENDING:
3146 {
3147 struct quic_stop_sending *stop_sending = &frm.stop_sending;
3148 if (qc->mux_state == QC_MUX_READY) {
3149 if (qcc_recv_stop_sending(qc->qcc, stop_sending->id,
3150 stop_sending->app_error_code)) {
3151 TRACE_ERROR("qcc_recv_stop_sending() failed", QUIC_EV_CONN_PRSHPKT, qc);
3152 goto leave;
3153 }
3154 }
3155 break;
3156 }
3157 case QUIC_FT_CRYPTO:
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02003158 if (!qc_handle_crypto_frm(qc, &frm.crypto, pkt, qel, &fast_retrans))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003159 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003160 break;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003161 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
3162 {
3163 struct quic_stream *stream = &frm.stream;
3164 unsigned nb_streams = qc->rx.strms[qcs_id_type(stream->id)].nb_streams;
Amaury Denoyelle2216b082023-02-02 14:59:36 +01003165 const char fin = frm.type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003166
3167 /* The upper layer may not be allocated. */
3168 if (qc->mux_state != QC_MUX_READY) {
3169 if ((stream->id >> QCS_ID_TYPE_SHIFT) < nb_streams) {
3170 TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003171 }
3172 else {
3173 TRACE_DEVEL("No mux for new stream", QUIC_EV_CONN_PRSHPKT, qc);
Amaury Denoyelle38836b62023-02-07 14:24:54 +01003174 if (qc->app_ops == &h3_ops) {
Amaury Denoyelle156a89a2023-02-20 10:32:16 +01003175 if (!qc_h3_request_reject(qc, stream->id)) {
3176 TRACE_ERROR("error on request rejection", QUIC_EV_CONN_PRSHPKT, qc);
3177 /* This packet will not be acknowledged */
3178 goto leave;
3179 }
3180 }
3181 else {
3182 /* This packet will not be acknowledged */
3183 goto leave;
Frédéric Lécailled18025e2023-01-20 15:33:50 +01003184 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003185 }
Amaury Denoyelle315a4f62023-03-06 09:10:53 +01003186
3187 break;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003188 }
3189
Amaury Denoyelle2216b082023-02-02 14:59:36 +01003190 if (!qc_handle_strm_frm(pkt, stream, qc, fin)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003191 TRACE_ERROR("qc_handle_strm_frm() failed", QUIC_EV_CONN_PRSHPKT, qc);
3192 goto leave;
3193 }
3194
3195 break;
3196 }
3197 case QUIC_FT_MAX_DATA:
3198 if (qc->mux_state == QC_MUX_READY) {
3199 struct quic_max_data *data = &frm.max_data;
3200 qcc_recv_max_data(qc->qcc, data->max_data);
3201 }
3202 break;
3203 case QUIC_FT_MAX_STREAM_DATA:
3204 if (qc->mux_state == QC_MUX_READY) {
3205 struct quic_max_stream_data *data = &frm.max_stream_data;
3206 if (qcc_recv_max_stream_data(qc->qcc, data->id,
3207 data->max_stream_data)) {
3208 TRACE_ERROR("qcc_recv_max_stream_data() failed", QUIC_EV_CONN_PRSHPKT, qc);
3209 goto leave;
3210 }
3211 }
3212 break;
3213 case QUIC_FT_MAX_STREAMS_BIDI:
3214 case QUIC_FT_MAX_STREAMS_UNI:
3215 break;
3216 case QUIC_FT_DATA_BLOCKED:
3217 HA_ATOMIC_INC(&qc->prx_counters->data_blocked);
3218 break;
3219 case QUIC_FT_STREAM_DATA_BLOCKED:
3220 HA_ATOMIC_INC(&qc->prx_counters->stream_data_blocked);
3221 break;
3222 case QUIC_FT_STREAMS_BLOCKED_BIDI:
3223 HA_ATOMIC_INC(&qc->prx_counters->streams_data_blocked_bidi);
3224 break;
3225 case QUIC_FT_STREAMS_BLOCKED_UNI:
3226 HA_ATOMIC_INC(&qc->prx_counters->streams_data_blocked_uni);
3227 break;
3228 case QUIC_FT_NEW_CONNECTION_ID:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003229 /* XXX TO DO XXX */
3230 break;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003231 case QUIC_FT_RETIRE_CONNECTION_ID:
3232 {
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003233 struct quic_connection_id *cid = NULL;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003234
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003235 if (!qc_handle_retire_connection_id_frm(qc, &frm, &pkt->dcid, &cid))
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003236 goto leave;
3237
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003238 if (!cid)
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003239 break;
3240
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003241 ebmb_delete(&cid->node);
3242 eb64_delete(&cid->seq_num);
3243 pool_free(pool_head_quic_connection_id, cid);
3244 TRACE_PROTO("CID retired", QUIC_EV_CONN_PSTRM, qc);
3245
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003246 cid = new_quic_cid(&qc->cids, qc, NULL, NULL);
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003247 if (!cid) {
3248 TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc);
3249 }
3250 else {
3251 /* insert the allocated CID in the receiver datagram handler tree */
3252 ebmb_insert(&quic_dghdlrs[tid].cids, &cid->node, cid->cid.len);
3253 qc_build_new_connection_id_frm(qc, cid);
3254 }
3255 break;
3256 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003257 case QUIC_FT_CONNECTION_CLOSE:
3258 case QUIC_FT_CONNECTION_CLOSE_APP:
3259 /* Increment the error counters */
3260 qc_cc_err_count_inc(qc, &frm);
3261 if (!(qc->flags & QUIC_FL_CONN_DRAINING)) {
3262 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
3263 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
3264 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
3265 }
3266 TRACE_STATE("Entering draining state", QUIC_EV_CONN_PRSHPKT, qc);
3267 /* RFC 9000 10.2. Immediate Close:
3268 * The closing and draining connection states exist to ensure
3269 * that connections close cleanly and that delayed or reordered
3270 * packets are properly discarded. These states SHOULD persist
3271 * for at least three times the current PTO interval...
3272 *
3273 * Rearm the idle timeout only one time when entering draining
3274 * state.
3275 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003276 qc->flags |= QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_IMMEDIATE_CLOSE;
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01003277 qc_detach_th_ctx_list(qc, 1);
Frédéric Lécailled7215712023-03-24 18:13:37 +01003278 qc_idle_timer_do_rearm(qc, 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003279 qc_notify_close(qc);
3280 }
3281 break;
3282 case QUIC_FT_HANDSHAKE_DONE:
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003283 if (qc_is_listener(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003284 TRACE_ERROR("non accepted QUIC_FT_HANDSHAKE_DONE frame",
3285 QUIC_EV_CONN_PRSHPKT, qc);
3286 goto leave;
3287 }
3288
3289 qc->state = QUIC_HS_ST_CONFIRMED;
3290 break;
3291 default:
3292 TRACE_ERROR("unknosw frame type", QUIC_EV_CONN_PRSHPKT, qc);
3293 goto leave;
3294 }
3295 }
3296
3297 /* Flag this packet number space as having received a packet. */
3298 qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED;
3299
3300 if (fast_retrans) {
3301 struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
3302 struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
3303
3304 TRACE_PROTO("speeding up handshake completion", QUIC_EV_CONN_PRSHPKT, qc);
3305 qc_prep_hdshk_fast_retrans(qc, &iqel->pktns->tx.frms, &hqel->pktns->tx.frms);
3306 qc->flags |= QUIC_FL_CONN_HANDSHAKE_SPEED_UP;
3307 }
3308
3309 /* The server must switch from INITIAL to HANDSHAKE handshake state when it
3310 * has successfully parse a Handshake packet. The Initial encryption must also
3311 * be discarded.
3312 */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003313 if (pkt->type == QUIC_PACKET_TYPE_HANDSHAKE && qc_is_listener(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003314 if (qc->state >= QUIC_HS_ST_SERVER_INITIAL) {
3315 if (!(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx.flags &
3316 QUIC_FL_TLS_SECRETS_DCD)) {
3317 quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
3318 TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PRSHPKT, qc);
3319 quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, qc);
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003320 qc_set_timer(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003321 qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
3322 qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns);
3323 }
3324 if (qc->state < QUIC_HS_ST_SERVER_HANDSHAKE)
3325 qc->state = QUIC_HS_ST_SERVER_HANDSHAKE;
3326 }
3327 }
3328
3329 ret = 1;
3330 leave:
3331 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
3332 return ret;
3333}
3334
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003335
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003336/* Allocate Tx buffer from <qc> quic-conn if needed.
3337 *
3338 * Returns allocated buffer or NULL on error.
3339 */
3340static struct buffer *qc_txb_alloc(struct quic_conn *qc)
3341{
3342 struct buffer *buf = &qc->tx.buf;
3343 if (!b_alloc(buf))
3344 return NULL;
3345
3346 return buf;
3347}
3348
3349/* Free Tx buffer from <qc> if it is empty. */
3350static void qc_txb_release(struct quic_conn *qc)
3351{
3352 struct buffer *buf = &qc->tx.buf;
3353
3354 /* For the moment sending function is responsible to purge the buffer
3355 * entirely. It may change in the future but this requires to be able
3356 * to reuse old data.
Frédéric Lécaillebbf86be2023-02-20 09:28:58 +01003357 * For the momemt we do not care to leave data in the buffer for
3358 * a connection which is supposed to be killed asap.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003359 */
3360 BUG_ON_HOT(buf && b_data(buf));
3361
3362 if (!b_data(buf)) {
3363 b_free(buf);
3364 offer_buffers(NULL, 1);
3365 }
3366}
3367
3368/* Commit a datagram payload written into <buf> of length <length>. <first_pkt>
3369 * must contains the address of the first packet stored in the payload.
3370 *
3371 * Caller is responsible that there is enough space in the buffer.
3372 */
3373static void qc_txb_store(struct buffer *buf, uint16_t length,
3374 struct quic_tx_packet *first_pkt)
3375{
3376 const size_t hdlen = sizeof(uint16_t) + sizeof(void *);
3377 BUG_ON_HOT(b_contig_space(buf) < hdlen); /* this must not happen */
3378
3379 write_u16(b_tail(buf), length);
3380 write_ptr(b_tail(buf) + sizeof(length), first_pkt);
3381 b_add(buf, hdlen + length);
3382}
3383
3384/* Returns 1 if a packet may be built for <qc> from <qel> encryption level
3385 * with <frms> as ack-eliciting frame list to send, 0 if not.
3386 * <cc> must equal to 1 if an immediate close was asked, 0 if not.
3387 * <probe> must equalt to 1 if a probing packet is required, 0 if not.
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003388 * Also set <*must_ack> to inform the caller if an acknowledgement should be sent.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003389 */
3390static int qc_may_build_pkt(struct quic_conn *qc, struct list *frms,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003391 struct quic_enc_level *qel, int cc, int probe,
3392 int *must_ack)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003393{
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003394 int force_ack =
3395 qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] ||
3396 qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
3397 int nb_aepkts_since_last_ack = qel->pktns->rx.nb_aepkts_since_last_ack;
3398
3399 /* An acknowledgement must be sent if this has been forced by the caller,
3400 * typically during the handshake when the packets must be acknowledged as
3401 * soon as possible. This is also the case when the ack delay timer has been
3402 * triggered, or at least every QUIC_MAX_RX_AEPKTS_SINCE_LAST_ACK packets.
3403 */
3404 *must_ack = (qc->flags & QUIC_FL_CONN_ACK_TIMER_FIRED) ||
3405 ((qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) &&
3406 (force_ack || nb_aepkts_since_last_ack >= QUIC_MAX_RX_AEPKTS_SINCE_LAST_ACK));
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003407
3408 /* Do not build any more packet if the TX secrets are not available or
3409 * if there is nothing to send, i.e. if no CONNECTION_CLOSE or ACK are required
3410 * and if there is no more packets to send upon PTO expiration
3411 * and if there is no more ack-eliciting frames to send or in flight
3412 * congestion control limit is reached for prepared data
3413 */
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02003414 if (!quic_tls_has_tx_sec(qel) ||
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003415 (!cc && !probe && !*must_ack &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003416 (LIST_ISEMPTY(frms) || qc->path->prep_in_flight >= qc->path->cwnd))) {
3417 return 0;
3418 }
3419
3420 return 1;
3421}
3422
3423/* Prepare as much as possible QUIC packets for sending from prebuilt frames
3424 * <frms>. Each packet is stored in a distinct datagram written to <buf>.
3425 *
3426 * Each datagram is prepended by a two fields header : the datagram length and
3427 * the address of the packet contained in the datagram.
3428 *
3429 * Returns the number of bytes prepared in packets if succeeded (may be 0), or
3430 * -1 if something wrong happened.
3431 */
3432static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf,
3433 struct list *frms)
3434{
3435 int ret = -1;
3436 struct quic_enc_level *qel;
3437 unsigned char *end, *pos;
3438 struct quic_tx_packet *pkt;
3439 size_t total;
3440 /* Each datagram is prepended with its length followed by the address
3441 * of the first packet in the datagram.
3442 */
3443 const size_t dg_headlen = sizeof(uint16_t) + sizeof(pkt);
3444
3445 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
3446
3447 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
3448 total = 0;
3449 pos = (unsigned char *)b_tail(buf);
3450 while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen) {
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003451 int err, probe, cc, must_ack;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003452
Frédéric Lécaillee47adca2023-04-07 18:12:00 +02003453 TRACE_PROTO("TX prep app pkts", QUIC_EV_CONN_PHPKTS, qc, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003454 probe = 0;
3455 cc = qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE;
3456 /* We do not probe if an immediate close was asked */
3457 if (!cc)
3458 probe = qel->pktns->tx.pto_probe;
3459
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003460 if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003461 break;
3462
3463 /* Leave room for the datagram header */
3464 pos += dg_headlen;
3465 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
3466 end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
3467 }
3468 else {
3469 end = pos + qc->path->mtu;
3470 }
3471
3472 pkt = qc_build_pkt(&pos, end, qel, &qel->tls_ctx, frms, qc, NULL, 0,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003473 QUIC_PACKET_TYPE_SHORT, must_ack, 0, probe, cc, &err);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003474 switch (err) {
3475 case -2:
3476 // trace already emitted by function above
3477 goto leave;
3478 case -1:
3479 /* As we provide qc_build_pkt() with an enough big buffer to fulfill an
3480 * MTU, we are here because of the congestion control window. There is
3481 * no need to try to reuse this buffer.
3482 */
Frédéric Lécaillee47adca2023-04-07 18:12:00 +02003483 TRACE_PROTO("could not prepare anymore packet", QUIC_EV_CONN_PHPKTS, qc, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003484 goto out;
3485 default:
3486 break;
3487 }
3488
3489 /* This is to please to GCC. We cannot have (err >= 0 && !pkt) */
3490 BUG_ON(!pkt);
3491
3492 if (qc->flags & QUIC_FL_CONN_RETRANS_OLD_DATA)
3493 pkt->flags |= QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA;
3494
3495 total += pkt->len;
3496
3497 /* Write datagram header. */
3498 qc_txb_store(buf, pkt->len, pkt);
3499 }
3500
3501 out:
3502 ret = total;
3503 leave:
3504 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
3505 return ret;
3506}
3507
3508/* Prepare as much as possible QUIC packets for sending from prebuilt frames
3509 * <frms>. Several packets can be regrouped in a single datagram. The result is
3510 * written into <buf>.
3511 *
3512 * Each datagram is prepended by a two fields header : the datagram length and
3513 * the address of first packet in the datagram.
3514 *
3515 * Returns the number of bytes prepared in packets if succeeded (may be 0), or
3516 * -1 if something wrong happened.
3517 */
3518static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
3519 enum quic_tls_enc_level tel, struct list *tel_frms,
3520 enum quic_tls_enc_level next_tel, struct list *next_tel_frms)
3521{
3522 struct quic_enc_level *qel;
3523 unsigned char *end, *pos;
3524 struct quic_tx_packet *first_pkt, *cur_pkt, *prv_pkt;
3525 /* length of datagrams */
3526 uint16_t dglen;
3527 size_t total;
3528 int ret = -1, padding;
3529 /* Each datagram is prepended with its length followed by the address
3530 * of the first packet in the datagram.
3531 */
3532 const size_t dg_headlen = sizeof(uint16_t) + sizeof(first_pkt);
3533 struct list *frms;
3534
3535 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
3536
3537 /* Currently qc_prep_pkts() does not handle buffer wrapping so the
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05003538 * caller must ensure that buf is reset.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003539 */
3540 BUG_ON_HOT(buf->head || buf->data);
3541
3542 total = 0;
3543 qel = &qc->els[tel];
3544 frms = tel_frms;
3545 dglen = 0;
3546 padding = 0;
3547 pos = (unsigned char *)b_head(buf);
3548 first_pkt = prv_pkt = NULL;
3549 while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen || prv_pkt) {
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003550 int err, probe, cc, must_ack;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003551 enum quic_pkt_type pkt_type;
3552 struct quic_tls_ctx *tls_ctx;
3553 const struct quic_version *ver;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003554
Frédéric Lécaillee47adca2023-04-07 18:12:00 +02003555 TRACE_PROTO("TX prep pkts", QUIC_EV_CONN_PHPKTS, qc, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003556 probe = 0;
3557 cc = qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE;
3558 /* We do not probe if an immediate close was asked */
3559 if (!cc)
3560 probe = qel->pktns->tx.pto_probe;
3561
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003562 if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003563 if (prv_pkt)
3564 qc_txb_store(buf, dglen, first_pkt);
3565 /* Let's select the next encryption level */
3566 if (tel != next_tel && next_tel != QUIC_TLS_ENC_LEVEL_NONE) {
3567 tel = next_tel;
3568 frms = next_tel_frms;
3569 qel = &qc->els[tel];
3570 /* Build a new datagram */
3571 prv_pkt = NULL;
3572 TRACE_DEVEL("next encryption level selected", QUIC_EV_CONN_PHPKTS, qc);
3573 continue;
3574 }
3575 break;
3576 }
3577
3578 pkt_type = quic_tls_level_pkt_type(tel);
3579 if (!prv_pkt) {
3580 /* Leave room for the datagram header */
3581 pos += dg_headlen;
3582 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
3583 end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
3584 }
3585 else {
3586 end = pos + qc->path->mtu;
3587 }
3588 }
3589
Frédéric Lécaille69e71182023-02-20 14:39:41 +01003590 /* RFC 9000 14.1 Initial datagram size
3591 * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
3592 * Initial packets to at least the smallest allowed maximum datagram size of
3593 * 1200 bytes.
3594 *
3595 * Ensure that no ack-eliciting packets are sent into too small datagrams
3596 */
3597 if (pkt_type == QUIC_PACKET_TYPE_INITIAL && !LIST_ISEMPTY(tel_frms)) {
3598 if (end - pos < QUIC_INITIAL_PACKET_MINLEN) {
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01003599 TRACE_PROTO("No more enough room to build an Initial packet",
Frédéric Lécaille69e71182023-02-20 14:39:41 +01003600 QUIC_EV_CONN_PHPKTS, qc);
3601 goto out;
3602 }
3603
3604 /* Pad this Initial packet if there is no ack-eliciting frames to send from
3605 * the next packet number space.
3606 */
Frédéric Lécailleec937212023-03-03 17:34:41 +01003607 if (!next_tel_frms || LIST_ISEMPTY(next_tel_frms))
Frédéric Lécaille69e71182023-02-20 14:39:41 +01003608 padding = 1;
3609 }
3610
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003611 if (qc->negotiated_version) {
3612 ver = qc->negotiated_version;
3613 if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL])
3614 tls_ctx = &qc->negotiated_ictx;
3615 else
3616 tls_ctx = &qel->tls_ctx;
3617 }
3618 else {
3619 ver = qc->original_version;
3620 tls_ctx = &qel->tls_ctx;
3621 }
3622
3623 cur_pkt = qc_build_pkt(&pos, end, qel, tls_ctx, frms,
3624 qc, ver, dglen, pkt_type,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003625 must_ack, padding, probe, cc, &err);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003626 switch (err) {
3627 case -2:
3628 // trace already emitted by function above
3629 goto leave;
3630 case -1:
3631 /* If there was already a correct packet present, set the
3632 * current datagram as prepared into <cbuf>.
3633 */
3634 if (prv_pkt)
3635 qc_txb_store(buf, dglen, first_pkt);
Frédéric Lécaillee47adca2023-04-07 18:12:00 +02003636 TRACE_PROTO("could not prepare anymore packet", QUIC_EV_CONN_PHPKTS, qc, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003637 goto out;
3638 default:
3639 break;
3640 }
3641
3642 /* This is to please to GCC. We cannot have (err >= 0 && !cur_pkt) */
3643 BUG_ON(!cur_pkt);
3644
3645 if (qc->flags & QUIC_FL_CONN_RETRANS_OLD_DATA)
3646 cur_pkt->flags |= QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA;
3647
3648 total += cur_pkt->len;
3649 /* keep trace of the first packet in the datagram */
3650 if (!first_pkt)
3651 first_pkt = cur_pkt;
Frédéric Lécaille74b5f7b2022-11-20 18:35:35 +01003652 /* Attach the current one to the previous one and vice versa */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003653 if (prv_pkt) {
3654 prv_pkt->next = cur_pkt;
Frédéric Lécaille814645f2022-11-18 18:15:28 +01003655 cur_pkt->prev = prv_pkt;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003656 cur_pkt->flags |= QUIC_FL_TX_PACKET_COALESCED;
3657 }
3658 /* Let's say we have to build a new dgram */
3659 prv_pkt = NULL;
3660 dglen += cur_pkt->len;
3661 /* Client: discard the Initial encryption keys as soon as
3662 * a handshake packet could be built.
3663 */
3664 if (qc->state == QUIC_HS_ST_CLIENT_INITIAL &&
3665 pkt_type == QUIC_PACKET_TYPE_HANDSHAKE) {
3666 quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
3667 TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PHPKTS, qc);
3668 quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, qc);
3669 qc_set_timer(qc);
3670 qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
3671 qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns);
3672 qc->state = QUIC_HS_ST_CLIENT_HANDSHAKE;
3673 }
3674 /* If the data for the current encryption level have all been sent,
3675 * select the next level.
3676 */
3677 if ((tel == QUIC_TLS_ENC_LEVEL_INITIAL || tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE) &&
Frédéric Lécaillea576c1b2023-04-13 15:59:02 +02003678 next_tel != QUIC_TLS_ENC_LEVEL_NONE && (LIST_ISEMPTY(frms))) {
Frédéric Lécaille895700b2023-04-13 18:30:16 +02003679 /* If QUIC_TLS_ENC_LEVEL_HANDSHAKE was already reached let's try
3680 * QUIC_TLS_ENC_LEVEL_APP except if the connection was probing.
3681 */
3682 if (tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE && next_tel == tel) {
3683 if ((qc->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED)) {
3684 TRACE_PROTO("skip APP enc. level", QUIC_EV_CONN_PHPKTS, qc);
3685 qc_txb_store(buf, dglen, first_pkt);
3686 goto out;
3687 }
3688
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003689 next_tel = QUIC_TLS_ENC_LEVEL_APP;
Frédéric Lécaille895700b2023-04-13 18:30:16 +02003690 }
3691
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003692 tel = next_tel;
3693 if (tel == QUIC_TLS_ENC_LEVEL_APP)
3694 frms = &qc->els[tel].pktns->tx.frms;
3695 else
3696 frms = next_tel_frms;
3697 qel = &qc->els[tel];
3698 if (!LIST_ISEMPTY(frms)) {
3699 /* If there is data for the next level, do not
3700 * consume a datagram.
3701 */
3702 prv_pkt = cur_pkt;
3703 }
3704 }
3705
3706 /* If we have to build a new datagram, set the current datagram as
3707 * prepared into <cbuf>.
3708 */
3709 if (!prv_pkt) {
3710 qc_txb_store(buf, dglen, first_pkt);
3711 first_pkt = NULL;
3712 dglen = 0;
3713 padding = 0;
3714 }
3715 else if (prv_pkt->type == QUIC_TLS_ENC_LEVEL_INITIAL &&
3716 (!qc_is_listener(qc) ||
3717 prv_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
3718 padding = 1;
3719 }
3720 }
3721
3722 out:
3723 ret = total;
3724 leave:
3725 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
3726 return ret;
3727}
3728
3729/* Send datagrams stored in <buf>.
3730 *
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003731 * This function returns 1 for success. On error, there is several behavior
3732 * depending on underlying sendto() error :
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01003733 * - for an unrecoverable error, 0 is returned and connection is killed.
3734 * - a transient error is handled differently if connection has its owned
3735 * socket. If this is the case, 0 is returned and socket is subscribed on the
3736 * poller. The other case is assimilated to a success case with 1 returned.
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003737 * Remaining data are purged from the buffer and will eventually be detected
3738 * as lost which gives the opportunity to retry sending.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003739 */
3740int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
3741{
Frédéric Lécaillea2c62c32023-02-10 14:13:43 +01003742 int ret = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003743 struct quic_conn *qc;
3744 char skip_sendto = 0;
3745
3746 qc = ctx->qc;
3747 TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
3748 while (b_contig_data(buf, 0)) {
3749 unsigned char *pos;
3750 struct buffer tmpbuf = { };
3751 struct quic_tx_packet *first_pkt, *pkt, *next_pkt;
3752 uint16_t dglen;
3753 size_t headlen = sizeof dglen + sizeof first_pkt;
3754 unsigned int time_sent;
3755
3756 pos = (unsigned char *)b_head(buf);
3757 dglen = read_u16(pos);
3758 BUG_ON_HOT(!dglen); /* this should not happen */
3759
3760 pos += sizeof dglen;
3761 first_pkt = read_ptr(pos);
3762 pos += sizeof first_pkt;
3763 tmpbuf.area = (char *)pos;
3764 tmpbuf.size = tmpbuf.data = dglen;
3765
Frédéric Lécaille8f991942023-03-24 15:14:45 +01003766 TRACE_PROTO("TX dgram", QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003767 /* If sendto is on error just skip the call to it for the rest
3768 * of the loop but continue to purge the buffer. Data will be
3769 * transmitted when QUIC packets are detected as lost on our
3770 * side.
3771 *
3772 * TODO use fd-monitoring to detect when send operation can be
3773 * retry. This should improve the bandwidth without relying on
3774 * retransmission timer. However, it requires a major rework on
3775 * quic-conn fd management.
3776 */
3777 if (!skip_sendto) {
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003778 int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0);
3779 if (ret < 0) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01003780 TRACE_ERROR("sendto fatal error", QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003781 qc_kill_conn(qc);
3782 b_del(buf, buf->data);
3783 goto leave;
3784 }
3785 else if (!ret) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01003786 /* Connection owned socket : poller will wake us up when transient error is cleared. */
3787 if (qc_test_fd(qc)) {
3788 TRACE_ERROR("sendto error, subscribe to poller", QUIC_EV_CONN_SPPKTS, qc);
3789 goto leave;
3790 }
3791
3792 /* No connection owned-socket : rely on retransmission to retry sending. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003793 skip_sendto = 1;
3794 TRACE_ERROR("sendto error, simulate sending for the rest of data", QUIC_EV_CONN_SPPKTS, qc);
3795 }
3796 }
3797
3798 b_del(buf, dglen + headlen);
3799 qc->tx.bytes += tmpbuf.data;
3800 time_sent = now_ms;
3801
3802 for (pkt = first_pkt; pkt; pkt = next_pkt) {
Frédéric Lécailleceb88b82023-02-20 14:43:55 +01003803 /* RFC 9000 14.1 Initial datagram size
3804 * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
3805 * Initial packets to at least the smallest allowed maximum datagram size of
3806 * 1200 bytes.
3807 */
3808 BUG_ON_HOT(pkt->type == QUIC_PACKET_TYPE_INITIAL &&
3809 (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) &&
3810 dglen < QUIC_INITIAL_PACKET_MINLEN);
3811
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003812 pkt->time_sent = time_sent;
3813 if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) {
3814 pkt->pktns->tx.time_of_last_eliciting = time_sent;
3815 qc->path->ifae_pkts++;
3816 if (qc->flags & QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ)
Frédéric Lécailled7215712023-03-24 18:13:37 +01003817 qc_idle_timer_rearm(qc, 0, 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003818 }
3819 if (!(qc->flags & QUIC_FL_CONN_CLOSING) &&
3820 (pkt->flags & QUIC_FL_TX_PACKET_CC)) {
3821 qc->flags |= QUIC_FL_CONN_CLOSING;
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01003822 qc_detach_th_ctx_list(qc, 1);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003823 qc_notify_close(qc);
3824
3825 /* RFC 9000 10.2. Immediate Close:
3826 * The closing and draining connection states exist to ensure
3827 * that connections close cleanly and that delayed or reordered
3828 * packets are properly discarded. These states SHOULD persist
3829 * for at least three times the current PTO interval...
3830 *
3831 * Rearm the idle timeout only one time when entering closing
3832 * state.
3833 */
Frédéric Lécailled7215712023-03-24 18:13:37 +01003834 qc_idle_timer_do_rearm(qc, 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003835 if (qc->timer_task) {
3836 task_destroy(qc->timer_task);
3837 qc->timer_task = NULL;
3838 }
3839 }
3840 qc->path->in_flight += pkt->in_flight_len;
3841 pkt->pktns->tx.in_flight += pkt->in_flight_len;
3842 if (pkt->in_flight_len)
3843 qc_set_timer(qc);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01003844 TRACE_PROTO("TX pkt", QUIC_EV_CONN_SPPKTS, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003845 next_pkt = pkt->next;
3846 quic_tx_packet_refinc(pkt);
3847 eb64_insert(&pkt->pktns->tx.pkts, &pkt->pn_node);
3848 }
3849 }
3850
Frédéric Lécaillea2c62c32023-02-10 14:13:43 +01003851 ret = 1;
3852leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003853 TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
3854
Frédéric Lécaillea2c62c32023-02-10 14:13:43 +01003855 return ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003856}
3857
3858/* Copy into <buf> buffer a stateless reset token depending on the
3859 * <salt> salt input. This is the cluster secret which will be derived
3860 * as HKDF input secret to generate this token.
3861 * Return 1 if succeeded, 0 if not.
3862 */
3863static int quic_stateless_reset_token_cpy(struct quic_conn *qc,
3864 unsigned char *buf, size_t len,
3865 const unsigned char *salt, size_t saltlen)
3866{
3867 /* Input secret */
3868 const unsigned char *key = (const unsigned char *)global.cluster_secret;
3869 size_t keylen = strlen(global.cluster_secret);
3870 /* Info */
3871 const unsigned char label[] = "stateless token";
3872 size_t labellen = sizeof label - 1;
3873 int ret;
3874
3875 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3876
3877 ret = quic_hkdf_extract_and_expand(EVP_sha256(), buf, len,
3878 key, keylen, salt, saltlen, label, labellen);
3879 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3880 return ret;
3881}
3882
3883/* Initialize the stateless reset token attached to <cid> connection ID.
3884 * Returns 1 if succeeded, 0 if not.
3885 */
3886static int quic_stateless_reset_token_init(struct quic_conn *qc,
3887 struct quic_connection_id *quic_cid)
3888{
3889 int ret;
3890
3891 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3892
3893 if (global.cluster_secret) {
3894 /* Output secret */
3895 unsigned char *token = quic_cid->stateless_reset_token;
3896 size_t tokenlen = sizeof quic_cid->stateless_reset_token;
3897 /* Salt */
3898 const unsigned char *cid = quic_cid->cid.data;
3899 size_t cidlen = quic_cid->cid.len;
3900
3901 ret = quic_stateless_reset_token_cpy(qc, token, tokenlen, cid, cidlen);
3902 }
3903 else {
3904 /* TODO: RAND_bytes() should be replaced */
3905 ret = RAND_bytes(quic_cid->stateless_reset_token,
3906 sizeof quic_cid->stateless_reset_token) == 1;
3907 }
3908
3909 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3910 return ret;
3911}
3912
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003913/* Generate a CID directly derived from <orig> CID and <addr> address. The CID
3914 * is then marked with the current thread ID.
3915 *
3916 * Returns a new 64-bits CID value.
3917 */
3918static uint64_t quic_derive_cid(const struct quic_cid *orig,
3919 const struct sockaddr_storage *addr)
3920{
3921 const struct sockaddr_in *in;
3922 const struct sockaddr_in6 *in6;
3923 char *buf = trash.area;
3924 size_t idx = 0;
3925 uint64_t hash;
3926
3927 /* Prepare buffer for hash using original CID first. */
3928 memcpy(buf, orig->data, orig->len);
3929 idx += orig->len;
3930
3931 /* Concatenate client address. */
3932 switch (addr->ss_family) {
3933 case AF_INET:
3934 in = (struct sockaddr_in *)addr;
3935
3936 memcpy(&buf[idx], &in->sin_addr, sizeof(in->sin_addr));
3937 idx += sizeof(in->sin_addr);
3938 memcpy(&buf[idx], &in->sin_port, sizeof(in->sin_port));
3939 idx += sizeof(in->sin_port);
3940 break;
3941
3942 case AF_INET6:
3943 in6 = (struct sockaddr_in6 *)addr;
3944
3945 memcpy(&buf[idx], &in6->sin6_addr, sizeof(in6->sin6_addr));
3946 idx += sizeof(in6->sin6_addr);
3947 memcpy(&buf[idx], &in6->sin6_port, sizeof(in6->sin6_port));
3948 idx += sizeof(in6->sin6_port);
3949 break;
3950
3951 default:
3952 /* TODO to implement */
3953 ABORT_NOW();
3954 return 0;
3955 }
3956
3957 /* Avoid similar values between multiple haproxy process. */
3958 memcpy(&buf[idx], boot_seed, sizeof(boot_seed));
3959 idx += sizeof(boot_seed);
3960
3961 /* Hash the final buffer content. */
3962 hash = XXH64(buf, idx, 0);
3963
3964 /* Mark the current thread id in the CID. */
3965 quic_pin_cid_to_tid((uchar *)&hash, tid);
3966
3967 return hash;
3968}
3969
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01003970/* Allocate a new CID and attach it to <root> ebtree.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003971 *
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003972 * If <orig> and <addr> params are non null, the new CID value is directly
3973 * derived from them. Else a random value is generated. The CID is then marked
3974 * with the current thread ID.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003975 *
3976 * Returns the new CID if succeeded, NULL if not.
3977 */
3978static struct quic_connection_id *new_quic_cid(struct eb_root *root,
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003979 struct quic_conn *qc,
3980 const struct quic_cid *orig,
3981 const struct sockaddr_storage *addr)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003982{
3983 struct quic_connection_id *cid;
3984
3985 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3986
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003987 /* Caller must set either none or both values. */
3988 BUG_ON(!!orig != !!addr);
3989
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003990 cid = pool_alloc(pool_head_quic_connection_id);
3991 if (!cid) {
3992 TRACE_ERROR("cid allocation failed", QUIC_EV_CONN_TXPKT, qc);
3993 goto err;
3994 }
3995
3996 cid->cid.len = QUIC_HAP_CID_LEN;
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003997
3998 if (!orig) {
3999 /* TODO: RAND_bytes() should be replaced */
4000 if (RAND_bytes(cid->cid.data, cid->cid.len) != 1) {
4001 TRACE_ERROR("RAND_bytes() failed", QUIC_EV_CONN_TXPKT, qc);
4002 goto err;
4003 }
4004 quic_pin_cid_to_tid(cid->cid.data, tid);
4005 }
4006 else {
4007 /* Derive the new CID value from original CID. */
4008 const uint64_t hash = quic_derive_cid(orig, addr);
4009 memcpy(cid->cid.data, &hash, sizeof(hash));
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004010 }
4011
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004012 if (quic_stateless_reset_token_init(qc, cid) != 1) {
4013 TRACE_ERROR("quic_stateless_reset_token_init() failed", QUIC_EV_CONN_TXPKT, qc);
4014 goto err;
4015 }
4016
4017 cid->qc = qc;
4018
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004019 cid->seq_num.key = qc->next_cid_seq_num++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004020 cid->retire_prior_to = 0;
4021 /* insert the allocated CID in the quic_conn tree */
4022 eb64_insert(root, &cid->seq_num);
4023
4024 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4025 return cid;
4026
4027 err:
4028 pool_free(pool_head_quic_connection_id, cid);
4029 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4030 return NULL;
4031}
4032
4033/* Build all the frames which must be sent just after the handshake have succeeded.
4034 * This is essentially NEW_CONNECTION_ID frames. A QUIC server must also send
4035 * a HANDSHAKE_DONE frame.
4036 * Return 1 if succeeded, 0 if not.
4037 */
4038static int quic_build_post_handshake_frames(struct quic_conn *qc)
4039{
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004040 int ret = 0, max;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004041 struct quic_enc_level *qel;
4042 struct quic_frame *frm, *frmbak;
4043 struct list frm_list = LIST_HEAD_INIT(frm_list);
4044 struct eb64_node *node;
4045
4046 TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
4047
4048 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4049 /* Only servers must send a HANDSHAKE_DONE frame. */
4050 if (qc_is_listener(qc)) {
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01004051 frm = qc_frm_alloc(QUIC_FT_HANDSHAKE_DONE);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004052 if (!frm) {
4053 TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
4054 goto leave;
4055 }
4056
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004057 LIST_APPEND(&frm_list, &frm->list);
4058 }
4059
4060 /* Initialize <max> connection IDs minus one: there is
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004061 * already one connection ID used for the current connection. Also limit
4062 * the number of connection IDs sent to the peer to 4 (3 from this function
4063 * plus 1 for the current connection.
4064 * Note that active_connection_id_limit >= 2: this has been already checked
4065 * when receiving this parameter.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004066 */
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004067 max = QUIC_MIN(qc->tx.params.active_connection_id_limit - 1, (uint64_t)3);
4068 while (max--) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004069 struct quic_connection_id *cid;
4070
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01004071 frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004072 if (!frm) {
4073 TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
4074 goto err;
4075 }
4076
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004077 cid = new_quic_cid(&qc->cids, qc, NULL, NULL);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004078 if (!cid) {
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01004079 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004080 TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc);
4081 goto err;
4082 }
4083
4084 /* insert the allocated CID in the receiver datagram handler tree */
4085 ebmb_insert(&quic_dghdlrs[tid].cids, &cid->node, cid->cid.len);
4086
4087 quic_connection_id_to_frm_cpy(frm, cid);
4088 LIST_APPEND(&frm_list, &frm->list);
4089 }
4090
4091 LIST_SPLICE(&qel->pktns->tx.frms, &frm_list);
4092 qc->flags |= QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT;
4093
4094 ret = 1;
4095 leave:
4096 TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
4097 return ret;
4098
4099 err:
4100 /* free the frames */
4101 list_for_each_entry_safe(frm, frmbak, &frm_list, list)
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01004102 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004103
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004104 /* The first CID sequence number value used to allocated CIDs by this function is 1,
4105 * 0 being the sequence number of the CID for this connection.
4106 */
4107 node = eb64_lookup_ge(&qc->cids, 1);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004108 while (node) {
4109 struct quic_connection_id *cid;
4110
4111 cid = eb64_entry(node, struct quic_connection_id, seq_num);
4112 if (cid->seq_num.key >= max)
4113 break;
4114
4115 node = eb64_next(node);
4116 ebmb_delete(&cid->node);
4117 eb64_delete(&cid->seq_num);
4118 pool_free(pool_head_quic_connection_id, cid);
4119 }
4120 goto leave;
4121}
4122
4123/* Deallocate <l> list of ACK ranges. */
4124void quic_free_arngs(struct quic_conn *qc, struct quic_arngs *arngs)
4125{
4126 struct eb64_node *n;
4127 struct quic_arng_node *ar;
4128
4129 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
4130
4131 n = eb64_first(&arngs->root);
4132 while (n) {
4133 struct eb64_node *next;
4134
4135 ar = eb64_entry(n, struct quic_arng_node, first);
4136 next = eb64_next(n);
4137 eb64_delete(n);
4138 pool_free(pool_head_quic_arng, ar);
4139 n = next;
4140 }
4141
4142 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
4143}
4144
4145/* Return the gap value between <p> and <q> ACK ranges where <q> follows <p> in
4146 * descending order.
4147 */
4148static inline size_t sack_gap(struct quic_arng_node *p,
4149 struct quic_arng_node *q)
4150{
4151 return p->first.key - q->last - 2;
4152}
4153
4154
4155/* Remove the last elements of <ack_ranges> list of ack range updating its
4156 * encoded size until it goes below <limit>.
4157 * Returns 1 if succeeded, 0 if not (no more element to remove).
4158 */
4159static int quic_rm_last_ack_ranges(struct quic_conn *qc,
4160 struct quic_arngs *arngs, size_t limit)
4161{
4162 int ret = 0;
4163 struct eb64_node *last, *prev;
4164
4165 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4166
4167 last = eb64_last(&arngs->root);
4168 while (last && arngs->enc_sz > limit) {
4169 struct quic_arng_node *last_node, *prev_node;
4170
4171 prev = eb64_prev(last);
4172 if (!prev) {
4173 TRACE_DEVEL("<last> not found", QUIC_EV_CONN_TXPKT, qc);
4174 goto out;
4175 }
4176
4177 last_node = eb64_entry(last, struct quic_arng_node, first);
4178 prev_node = eb64_entry(prev, struct quic_arng_node, first);
4179 arngs->enc_sz -= quic_int_getsize(last_node->last - last_node->first.key);
4180 arngs->enc_sz -= quic_int_getsize(sack_gap(prev_node, last_node));
4181 arngs->enc_sz -= quic_decint_size_diff(arngs->sz);
4182 --arngs->sz;
4183 eb64_delete(last);
4184 pool_free(pool_head_quic_arng, last);
4185 last = prev;
4186 }
4187
4188 ret = 1;
4189 out:
4190 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4191 return ret;
4192}
4193
4194/* Set the encoded size of <arngs> QUIC ack ranges. */
4195static void quic_arngs_set_enc_sz(struct quic_conn *qc, struct quic_arngs *arngs)
4196{
4197 struct eb64_node *node, *next;
4198 struct quic_arng_node *ar, *ar_next;
4199
4200 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4201
4202 node = eb64_last(&arngs->root);
4203 if (!node)
4204 goto leave;
4205
4206 ar = eb64_entry(node, struct quic_arng_node, first);
4207 arngs->enc_sz = quic_int_getsize(ar->last) +
4208 quic_int_getsize(ar->last - ar->first.key) + quic_int_getsize(arngs->sz - 1);
4209
4210 while ((next = eb64_prev(node))) {
4211 ar_next = eb64_entry(next, struct quic_arng_node, first);
4212 arngs->enc_sz += quic_int_getsize(sack_gap(ar, ar_next)) +
4213 quic_int_getsize(ar_next->last - ar_next->first.key);
4214 node = next;
4215 ar = eb64_entry(node, struct quic_arng_node, first);
4216 }
4217
4218 leave:
4219 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4220}
4221
4222/* Insert <ar> ack range into <argns> tree of ack ranges.
4223 * Returns the ack range node which has been inserted if succeeded, NULL if not.
4224 */
4225static inline
4226struct quic_arng_node *quic_insert_new_range(struct quic_conn *qc,
4227 struct quic_arngs *arngs,
4228 struct quic_arng *ar)
4229{
4230 struct quic_arng_node *new_ar;
4231
4232 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
4233
4234 new_ar = pool_alloc(pool_head_quic_arng);
4235 if (!new_ar) {
4236 TRACE_ERROR("ack range allocation failed", QUIC_EV_CONN_RXPKT, qc);
4237 goto leave;
4238 }
4239
4240 new_ar->first.key = ar->first;
4241 new_ar->last = ar->last;
4242 eb64_insert(&arngs->root, &new_ar->first);
4243 arngs->sz++;
4244
4245 leave:
4246 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
4247 return new_ar;
4248}
4249
4250/* Update <arngs> tree of ACK ranges with <ar> as new ACK range value.
4251 * Note that this function computes the number of bytes required to encode
4252 * this tree of ACK ranges in descending order.
4253 *
4254 * Descending order
4255 * ------------->
4256 * range1 range2
4257 * ..........|--------|..............|--------|
4258 * ^ ^ ^ ^
4259 * | | | |
4260 * last1 first1 last2 first2
4261 * ..........+--------+--------------+--------+......
4262 * diff1 gap12 diff2
4263 *
4264 * To encode the previous list of ranges we must encode integers as follows in
4265 * descending order:
4266 * enc(last2),enc(diff2),enc(gap12),enc(diff1)
4267 * with diff1 = last1 - first1
4268 * diff2 = last2 - first2
4269 * gap12 = first1 - last2 - 2 (>= 0)
4270 *
4271
4272returns 0 on error
4273
4274 */
4275int quic_update_ack_ranges_list(struct quic_conn *qc,
4276 struct quic_arngs *arngs,
4277 struct quic_arng *ar)
4278{
4279 int ret = 0;
4280 struct eb64_node *le;
4281 struct quic_arng_node *new_node;
4282 struct eb64_node *new;
4283
4284 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
4285
4286 new = NULL;
4287 if (eb_is_empty(&arngs->root)) {
4288 new_node = quic_insert_new_range(qc, arngs, ar);
4289 if (new_node)
4290 ret = 1;
4291
4292 goto leave;
4293 }
4294
4295 le = eb64_lookup_le(&arngs->root, ar->first);
4296 if (!le) {
4297 new_node = quic_insert_new_range(qc, arngs, ar);
4298 if (!new_node)
4299 goto leave;
4300
4301 new = &new_node->first;
4302 }
4303 else {
4304 struct quic_arng_node *le_ar =
4305 eb64_entry(le, struct quic_arng_node, first);
4306
4307 /* Already existing range */
4308 if (le_ar->last >= ar->last) {
4309 ret = 1;
4310 }
4311 else if (le_ar->last + 1 >= ar->first) {
4312 le_ar->last = ar->last;
4313 new = le;
4314 new_node = le_ar;
4315 }
4316 else {
4317 new_node = quic_insert_new_range(qc, arngs, ar);
4318 if (!new_node)
4319 goto leave;
4320
4321 new = &new_node->first;
4322 }
4323 }
4324
4325 /* Verify that the new inserted node does not overlap the nodes
4326 * which follow it.
4327 */
4328 if (new) {
4329 struct eb64_node *next;
4330 struct quic_arng_node *next_node;
4331
4332 while ((next = eb64_next(new))) {
4333 next_node =
4334 eb64_entry(next, struct quic_arng_node, first);
4335 if (new_node->last + 1 < next_node->first.key)
4336 break;
4337
4338 if (next_node->last > new_node->last)
4339 new_node->last = next_node->last;
4340 eb64_delete(next);
4341 pool_free(pool_head_quic_arng, next_node);
4342 /* Decrement the size of these ranges. */
4343 arngs->sz--;
4344 }
4345 }
4346
4347 ret = 1;
4348 leave:
4349 quic_arngs_set_enc_sz(qc, arngs);
4350 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
4351 return ret;
4352}
Frédéric Lécailleece86e62023-03-07 11:53:43 +01004353
4354/* Detect the value of the spin bit to be used. */
4355static inline void qc_handle_spin_bit(struct quic_conn *qc, struct quic_rx_packet *pkt,
4356 struct quic_enc_level *qel)
4357{
4358 uint64_t largest_pn = qel->pktns->rx.largest_pn;
4359
4360 if (qel != &qc->els[QUIC_TLS_ENC_LEVEL_APP] || largest_pn == -1 ||
4361 pkt->pn <= largest_pn)
4362 return;
4363
4364 if (qc_is_listener(qc)) {
4365 if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
4366 qc->flags |= QUIC_FL_CONN_SPIN_BIT;
4367 else
4368 qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
4369 }
4370 else {
4371 if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
4372 qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
4373 else
4374 qc->flags |= QUIC_FL_CONN_SPIN_BIT;
4375 }
4376}
4377
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004378/* Remove the header protection of packets at <el> encryption level.
4379 * Always succeeds.
4380 */
4381static inline void qc_rm_hp_pkts(struct quic_conn *qc, struct quic_enc_level *el)
4382{
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004383 struct quic_rx_packet *pqpkt, *pkttmp;
4384 struct quic_enc_level *app_qel;
4385
4386 TRACE_ENTER(QUIC_EV_CONN_ELRMHP, qc);
4387 app_qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4388 /* A server must not process incoming 1-RTT packets before the handshake is complete. */
4389 if (el == app_qel && qc_is_listener(qc) && qc->state < QUIC_HS_ST_COMPLETE) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004390 TRACE_PROTO("RX hp not removed (handshake not completed)",
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004391 QUIC_EV_CONN_ELRMHP, qc);
4392 goto out;
4393 }
Frédéric Lécaille72027782023-02-22 16:20:09 +01004394
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004395 list_for_each_entry_safe(pqpkt, pkttmp, &el->rx.pqpkts, list) {
Frédéric Lécaille72027782023-02-22 16:20:09 +01004396 struct quic_tls_ctx *tls_ctx;
4397
4398 tls_ctx = qc_select_tls_ctx(qc, el, pqpkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004399 if (!qc_do_rm_hp(qc, pqpkt, tls_ctx, el->pktns->rx.largest_pn,
4400 pqpkt->data + pqpkt->pn_offset, pqpkt->data)) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004401 TRACE_ERROR("RX hp removing error", QUIC_EV_CONN_ELRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004402 }
4403 else {
Frédéric Lécailleece86e62023-03-07 11:53:43 +01004404 qc_handle_spin_bit(qc, pqpkt, el);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004405 /* The AAD includes the packet number field */
4406 pqpkt->aad_len = pqpkt->pn_offset + pqpkt->pnl;
4407 /* Store the packet into the tree of packets to decrypt. */
4408 pqpkt->pn_node.key = pqpkt->pn;
4409 eb64_insert(&el->rx.pkts, &pqpkt->pn_node);
4410 quic_rx_packet_refinc(pqpkt);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004411 TRACE_PROTO("RX hp removed", QUIC_EV_CONN_ELRMHP, qc, pqpkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004412 }
4413 LIST_DELETE(&pqpkt->list);
4414 quic_rx_packet_refdec(pqpkt);
4415 }
4416
4417 out:
4418 TRACE_LEAVE(QUIC_EV_CONN_ELRMHP, qc);
4419}
4420
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004421/* Process all the CRYPTO frame at <el> encryption level. This is the
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05004422 * responsibility of the called to ensure there exists a CRYPTO data
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004423 * stream for this level.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004424 * Return 1 if succeeded, 0 if not.
4425 */
4426static inline int qc_treat_rx_crypto_frms(struct quic_conn *qc,
4427 struct quic_enc_level *el,
4428 struct ssl_sock_ctx *ctx)
4429{
4430 int ret = 0;
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004431 struct ncbuf *ncbuf;
4432 struct quic_cstream *cstream = el->cstream;
4433 ncb_sz_t data;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004434
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004435 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004436
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004437 BUG_ON(!cstream);
4438 ncbuf = &cstream->rx.ncbuf;
4439 if (ncb_is_null(ncbuf))
4440 goto done;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004441
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004442 /* TODO not working if buffer is wrapping */
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004443 while ((data = ncb_data(ncbuf, 0))) {
4444 const unsigned char *cdata = (const unsigned char *)ncb_head(ncbuf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004445
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004446 if (!qc_provide_cdata(el, ctx, cdata, data, NULL, NULL))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004447 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004448
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004449 cstream->rx.offset += data;
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004450 TRACE_DEVEL("buffered crypto data were provided to TLS stack",
4451 QUIC_EV_CONN_PHPKTS, qc, el);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004452 }
4453
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004454 done:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004455 ret = 1;
4456 leave:
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004457 if (!ncb_is_null(ncbuf) && ncb_is_empty(ncbuf)) {
4458 TRACE_DEVEL("freeing crypto buf", QUIC_EV_CONN_PHPKTS, qc, el);
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004459 quic_free_ncbuf(ncbuf);
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004460 }
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004461 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004462 return ret;
4463}
4464
4465/* Process all the packets at <el> and <next_el> encryption level.
4466 * This is the caller responsibility to check that <cur_el> is different of <next_el>
4467 * as pointer value.
4468 * Return 1 if succeeded, 0 if not.
4469 */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004470int qc_treat_rx_pkts(struct quic_conn *qc, struct quic_enc_level *cur_el,
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01004471 struct quic_enc_level *next_el)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004472{
4473 int ret = 0;
4474 struct eb64_node *node;
4475 int64_t largest_pn = -1;
4476 unsigned int largest_pn_time_received = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004477 struct quic_enc_level *qel = cur_el;
4478
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004479 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004480 qel = cur_el;
4481 next_tel:
4482 if (!qel)
4483 goto out;
4484
4485 node = eb64_first(&qel->rx.pkts);
4486 while (node) {
4487 struct quic_rx_packet *pkt;
4488
4489 pkt = eb64_entry(node, struct quic_rx_packet, pn_node);
4490 TRACE_DATA("new packet", QUIC_EV_CONN_RXPKT,
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004491 qc, pkt, NULL, qc->xprt_ctx->ssl);
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01004492 if (!qc_pkt_decrypt(qc, qel, pkt)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004493 /* Drop the packet */
4494 TRACE_ERROR("packet decryption failed -> dropped",
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004495 QUIC_EV_CONN_RXPKT, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004496 }
4497 else {
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004498 if (!qc_parse_pkt_frms(qc, pkt, qel)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004499 /* Drop the packet */
4500 TRACE_ERROR("packet parsing failed -> dropped",
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004501 QUIC_EV_CONN_RXPKT, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004502 HA_ATOMIC_INC(&qc->prx_counters->dropped_parsing);
4503 }
4504 else {
4505 struct quic_arng ar = { .first = pkt->pn, .last = pkt->pn };
4506
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01004507 if (pkt->flags & QUIC_FL_RX_PACKET_ACK_ELICITING) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004508 qel->pktns->flags |= QUIC_FL_PKTNS_ACK_REQUIRED;
4509 qel->pktns->rx.nb_aepkts_since_last_ack++;
Frédéric Lécailled7215712023-03-24 18:13:37 +01004510 qc_idle_timer_rearm(qc, 1, 1);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004511 }
4512 if (pkt->pn > largest_pn) {
4513 largest_pn = pkt->pn;
4514 largest_pn_time_received = pkt->time_received;
4515 }
4516 /* Update the list of ranges to acknowledge. */
4517 if (!quic_update_ack_ranges_list(qc, &qel->pktns->rx.arngs, &ar))
4518 TRACE_ERROR("Could not update ack range list",
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004519 QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004520 }
4521 }
4522 node = eb64_next(node);
4523 eb64_delete(&pkt->pn_node);
4524 quic_rx_packet_refdec(pkt);
4525 }
4526
4527 if (largest_pn != -1 && largest_pn > qel->pktns->rx.largest_pn) {
4528 /* Update the largest packet number. */
4529 qel->pktns->rx.largest_pn = largest_pn;
4530 /* Update the largest acknowledged packet timestamps */
4531 qel->pktns->rx.largest_time_received = largest_pn_time_received;
4532 qel->pktns->flags |= QUIC_FL_PKTNS_NEW_LARGEST_PN;
4533 }
4534
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004535 if (qel->cstream && !qc_treat_rx_crypto_frms(qc, qel, qc->xprt_ctx)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004536 // trace already emitted by function above
4537 goto leave;
4538 }
4539
4540 if (qel == cur_el) {
4541 BUG_ON(qel == next_el);
4542 qel = next_el;
4543 largest_pn = -1;
4544 goto next_tel;
4545 }
4546
4547 out:
4548 ret = 1;
4549 leave:
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004550 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004551 return ret;
4552}
4553
4554/* Check if it's possible to remove header protection for packets related to
4555 * encryption level <qel>. If <qel> is NULL, assume it's false.
4556 *
4557 * Return true if the operation is possible else false.
4558 */
4559static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel)
4560{
4561 int ret = 0;
4562 enum quic_tls_enc_level tel;
4563
4564 TRACE_ENTER(QUIC_EV_CONN_TRMHP, qc);
4565
4566 if (!qel)
4567 goto cant_rm_hp;
4568
4569 tel = ssl_to_quic_enc_level(qel->level);
4570
4571 /* check if tls secrets are available */
4572 if (qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004573 TRACE_PROTO("Discarded keys", QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004574 goto cant_rm_hp;
4575 }
4576
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02004577 if (!quic_tls_has_rx_sec(qel)) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004578 TRACE_PROTO("non available secrets", QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004579 goto cant_rm_hp;
4580 }
4581
Frédéric Lécaille8417beb2023-02-01 10:31:35 +01004582 if (tel == QUIC_TLS_ENC_LEVEL_APP && qc->state < QUIC_HS_ST_COMPLETE) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004583 TRACE_PROTO("handshake not complete", QUIC_EV_CONN_TRMHP, qc);
Frédéric Lécaille8417beb2023-02-01 10:31:35 +01004584 goto cant_rm_hp;
4585 }
4586
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004587 /* check if the connection layer is ready before using app level */
4588 if ((tel == QUIC_TLS_ENC_LEVEL_APP || tel == QUIC_TLS_ENC_LEVEL_EARLY_DATA) &&
4589 qc->mux_state == QC_MUX_NULL) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004590 TRACE_PROTO("connection layer not ready", QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004591 goto cant_rm_hp;
4592 }
4593
4594 ret = 1;
4595 cant_rm_hp:
4596 TRACE_LEAVE(QUIC_EV_CONN_TRMHP, qc);
4597 return ret;
4598}
4599
Amaury Denoyelle147862d2023-02-28 15:10:00 +01004600/* Flush txbuf for <qc> connection. This must be called prior to a packet
4601 * preparation when txbuf contains older data. A send will be conducted for
4602 * these data.
4603 *
4604 * Returns 1 on success : buffer is empty and can be use for packet
4605 * preparation. On error 0 is returned.
4606 */
4607static int qc_purge_txbuf(struct quic_conn *qc, struct buffer *buf)
4608{
4609 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4610
4611 /* This operation can only be conducted if txbuf is not empty. This
4612 * case only happens for connection with their owned socket due to an
4613 * older transient sendto() error.
4614 */
4615 BUG_ON(!qc_test_fd(qc));
4616
4617 if (b_data(buf) && !qc_send_ppkts(buf, qc->xprt_ctx)) {
4618 if (qc->flags & QUIC_FL_CONN_TO_KILL)
4619 qc_txb_release(qc);
4620 TRACE_DEVEL("leaving in error", QUIC_EV_CONN_TXPKT, qc);
4621 return 0;
4622 }
4623
4624 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4625 return 1;
4626}
4627
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004628/* Try to send application frames from list <frms> on connection <qc>.
4629 *
4630 * Use qc_send_app_probing wrapper when probing with old data.
4631 *
4632 * Returns 1 on success. Some data might not have been sent due to congestion,
4633 * in this case they are left in <frms> input list. The caller may subscribe on
4634 * quic-conn to retry later.
4635 *
4636 * Returns 0 on critical error.
4637 * TODO review and classify more distinctly transient from definitive errors to
4638 * allow callers to properly handle it.
4639 */
4640static int qc_send_app_pkts(struct quic_conn *qc, struct list *frms)
4641{
4642 int status = 0;
4643 struct buffer *buf;
4644
4645 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4646
4647 buf = qc_txb_alloc(qc);
4648 if (!buf) {
4649 TRACE_ERROR("buffer allocation failed", QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyelle37333862023-02-28 11:53:48 +01004650 goto err;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004651 }
4652
Amaury Denoyelle147862d2023-02-28 15:10:00 +01004653 if (b_data(buf) && !qc_purge_txbuf(qc, buf))
4654 goto err;
4655
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004656 /* Prepare and send packets until we could not further prepare packets. */
4657 while (1) {
4658 int ret;
4659 /* Currently buf cannot be non-empty at this stage. Even if a
4660 * previous sendto() has failed it is emptied to simulate
4661 * packet emission and rely on QUIC lost detection to try to
4662 * emit it.
4663 */
4664 BUG_ON_HOT(b_data(buf));
4665 b_reset(buf);
4666
4667 ret = qc_prep_app_pkts(qc, buf, frms);
Amaury Denoyelle37333862023-02-28 11:53:48 +01004668 if (ret == -1) {
4669 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004670 goto err;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004671 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004672
Amaury Denoyelle37333862023-02-28 11:53:48 +01004673 if (!ret)
4674 break;
4675
4676 if (!qc_send_ppkts(buf, qc->xprt_ctx)) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01004677 if (qc->flags & QUIC_FL_CONN_TO_KILL)
4678 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004679 goto err;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004680 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004681 }
4682
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004683 status = 1;
4684 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004685 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4686 return status;
4687
4688 err:
Amaury Denoyelle37333862023-02-28 11:53:48 +01004689 TRACE_DEVEL("leaving in error", QUIC_EV_CONN_TXPKT, qc);
4690 return 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004691}
4692
4693/* Try to send application frames from list <frms> on connection <qc>. Use this
4694 * function when probing is required.
4695 *
4696 * Returns the result from qc_send_app_pkts function.
4697 */
4698static forceinline int qc_send_app_probing(struct quic_conn *qc,
4699 struct list *frms)
4700{
4701 int ret;
4702
4703 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4704
4705 TRACE_STATE("preparing old data (probing)", QUIC_EV_CONN_TXPKT, qc);
4706 qc->flags |= QUIC_FL_CONN_RETRANS_OLD_DATA;
4707 ret = qc_send_app_pkts(qc, frms);
4708 qc->flags &= ~QUIC_FL_CONN_RETRANS_OLD_DATA;
4709
4710 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4711 return ret;
4712}
4713
4714/* Try to send application frames from list <frms> on connection <qc>. This
4715 * function is provided for MUX upper layer usage only.
4716 *
4717 * Returns the result from qc_send_app_pkts function.
4718 */
4719int qc_send_mux(struct quic_conn *qc, struct list *frms)
4720{
4721 int ret;
4722
4723 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4724 BUG_ON(qc->mux_state != QC_MUX_READY); /* Only MUX can uses this function so it must be ready. */
4725
4726 TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc);
4727 qc->flags |= QUIC_FL_CONN_TX_MUX_CONTEXT;
4728 ret = qc_send_app_pkts(qc, frms);
4729 qc->flags &= ~QUIC_FL_CONN_TX_MUX_CONTEXT;
4730
4731 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4732 return ret;
4733}
4734
4735/* Sends handshake packets from up to two encryption levels <tel> and <next_te>
4736 * with <tel_frms> and <next_tel_frms> as frame list respectively for <qc>
4737 * QUIC connection. <old_data> is used as boolean to send data already sent but
4738 * not already acknowledged (in flight).
4739 * Returns 1 if succeeded, 0 if not.
4740 */
4741int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
4742 enum quic_tls_enc_level tel, struct list *tel_frms,
4743 enum quic_tls_enc_level next_tel, struct list *next_tel_frms)
4744{
4745 int ret, status = 0;
4746 struct buffer *buf = qc_txb_alloc(qc);
4747
4748 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4749
4750 if (!buf) {
4751 TRACE_ERROR("buffer allocation failed", QUIC_EV_CONN_TXPKT, qc);
4752 goto leave;
4753 }
4754
Amaury Denoyelle147862d2023-02-28 15:10:00 +01004755 if (b_data(buf) && !qc_purge_txbuf(qc, buf))
4756 goto out;
4757
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004758 /* Currently buf cannot be non-empty at this stage. Even if a previous
4759 * sendto() has failed it is emptied to simulate packet emission and
4760 * rely on QUIC lost detection to try to emit it.
4761 */
4762 BUG_ON_HOT(b_data(buf));
4763 b_reset(buf);
4764
4765 if (old_data) {
4766 TRACE_STATE("old data for probing asked", QUIC_EV_CONN_TXPKT, qc);
4767 qc->flags |= QUIC_FL_CONN_RETRANS_OLD_DATA;
4768 }
4769
4770 ret = qc_prep_pkts(qc, buf, tel, tel_frms, next_tel, next_tel_frms);
Amaury Denoyelle37333862023-02-28 11:53:48 +01004771 if (ret == -1) {
4772 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004773 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004774 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004775
Amaury Denoyelle37333862023-02-28 11:53:48 +01004776 if (ret && !qc_send_ppkts(buf, qc->xprt_ctx)) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01004777 if (qc->flags & QUIC_FL_CONN_TO_KILL)
4778 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004779 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004780 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004781
Amaury Denoyelle37333862023-02-28 11:53:48 +01004782 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004783 status = 1;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004784
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004785 out:
4786 TRACE_STATE("no more need old data for probing", QUIC_EV_CONN_TXPKT, qc);
4787 qc->flags &= ~QUIC_FL_CONN_RETRANS_OLD_DATA;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004788 leave:
4789 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4790 return status;
4791}
4792
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004793/* Retransmit up to two datagrams depending on packet number space.
4794 * Return 0 when failed, 0 if not.
4795 */
4796static int qc_dgrams_retransmit(struct quic_conn *qc)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004797{
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004798 int ret = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004799 struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
4800 struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
4801 struct quic_enc_level *aqel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4802
4803 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4804
4805 if (iqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
Frédéric Lécaille37ed4a32023-01-31 17:32:06 +01004806 int i;
4807
4808 for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
4809 struct list ifrms = LIST_HEAD_INIT(ifrms);
4810 struct list hfrms = LIST_HEAD_INIT(hfrms);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004811
Frédéric Lécaille37ed4a32023-01-31 17:32:06 +01004812 qc_prep_hdshk_fast_retrans(qc, &ifrms, &hfrms);
4813 TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &ifrms);
4814 TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &hfrms);
4815 if (!LIST_ISEMPTY(&ifrms)) {
4816 iqel->pktns->tx.pto_probe = 1;
4817 if (!LIST_ISEMPTY(&hfrms))
4818 hqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004819 if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms,
4820 QUIC_TLS_ENC_LEVEL_HANDSHAKE, &hfrms))
4821 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004822 /* Put back unsent frames in their packet number spaces */
4823 LIST_SPLICE(&iqel->pktns->tx.frms, &ifrms);
4824 LIST_SPLICE(&hqel->pktns->tx.frms, &hfrms);
4825 }
Frédéric Lécailleec937212023-03-03 17:34:41 +01004826 else {
4827 if (!(qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED)) {
4828 iqel->pktns->tx.pto_probe = 1;
4829 if (!qc_send_hdshk_pkts(qc, 0, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms,
4830 QUIC_TLS_ENC_LEVEL_NONE, NULL))
4831 goto leave;
4832 }
4833 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004834 }
4835 TRACE_STATE("no more need to probe Initial packet number space",
4836 QUIC_EV_CONN_TXPKT, qc);
4837 iqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
Frédéric Lécaille37ed4a32023-01-31 17:32:06 +01004838 hqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004839 }
4840 else {
4841 int i;
4842
4843 if (hqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004844 hqel->pktns->tx.pto_probe = 0;
4845 for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
Frédéric Lécaille7b5d9b12022-11-28 17:21:45 +01004846 struct list frms1 = LIST_HEAD_INIT(frms1);
4847
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004848 qc_prep_fast_retrans(qc, hqel, &frms1, NULL);
4849 TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
4850 if (!LIST_ISEMPTY(&frms1)) {
4851 hqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004852 if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_HANDSHAKE, &frms1,
4853 QUIC_TLS_ENC_LEVEL_NONE, NULL))
4854 goto leave;
4855
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004856 /* Put back unsent frames into their packet number spaces */
4857 LIST_SPLICE(&hqel->pktns->tx.frms, &frms1);
4858 }
4859 }
4860 TRACE_STATE("no more need to probe Handshake packet number space",
4861 QUIC_EV_CONN_TXPKT, qc);
4862 hqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
4863 }
4864 else if (aqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
4865 struct list frms2 = LIST_HEAD_INIT(frms2);
4866 struct list frms1 = LIST_HEAD_INIT(frms1);
4867
4868 aqel->pktns->tx.pto_probe = 0;
4869 qc_prep_fast_retrans(qc, aqel, &frms1, &frms2);
4870 TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
4871 TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms2);
4872 if (!LIST_ISEMPTY(&frms1)) {
4873 aqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004874 if (!qc_send_app_probing(qc, &frms1))
4875 goto leave;
4876
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004877 /* Put back unsent frames into their packet number spaces */
4878 LIST_SPLICE(&aqel->pktns->tx.frms, &frms1);
4879 }
4880 if (!LIST_ISEMPTY(&frms2)) {
4881 aqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004882 if (!qc_send_app_probing(qc, &frms2))
4883 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004884 /* Put back unsent frames into their packet number spaces */
4885 LIST_SPLICE(&aqel->pktns->tx.frms, &frms2);
4886 }
4887 TRACE_STATE("no more need to probe 01RTT packet number space",
4888 QUIC_EV_CONN_TXPKT, qc);
4889 aqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
4890 }
4891 }
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004892
4893 ret = 1;
4894 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004895 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004896 return ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004897}
4898
4899/* QUIC connection packet handler task (post handshake) */
4900struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state)
4901{
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004902 struct quic_conn *qc = context;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004903 struct quic_enc_level *qel;
4904
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004905 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4906
4907 TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
4908 TRACE_STATE("connection handshake state", QUIC_EV_CONN_IO_CB, qc, &qc->state);
4909
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01004910 if (qc_test_fd(qc))
4911 qc_rcv_buf(qc);
4912
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004913 /* Retranmissions */
4914 if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
4915 TRACE_STATE("retransmission needed", QUIC_EV_CONN_IO_CB, qc);
4916 qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004917 if (!qc_dgrams_retransmit(qc))
4918 goto out;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004919 }
4920
4921 if (!LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel))
4922 qc_rm_hp_pkts(qc, qel);
4923
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01004924 if (!qc_treat_rx_pkts(qc, qel, NULL)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004925 TRACE_DEVEL("qc_treat_rx_pkts() failed", QUIC_EV_CONN_IO_CB, qc);
4926 goto out;
4927 }
4928
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01004929 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
4930 TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_IO_CB, qc);
4931 goto out;
4932 }
4933
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004934 if ((qc->flags & QUIC_FL_CONN_DRAINING) &&
4935 !(qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)) {
4936 TRACE_STATE("draining connection (must not send packets)", QUIC_EV_CONN_IO_CB, qc);
4937 goto out;
4938 }
4939
4940 /* XXX TODO: how to limit the list frames to send */
4941 if (!qc_send_app_pkts(qc, &qel->pktns->tx.frms)) {
4942 TRACE_DEVEL("qc_send_app_pkts() failed", QUIC_EV_CONN_IO_CB, qc);
4943 goto out;
4944 }
4945
4946 out:
4947 TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
4948 return t;
4949}
4950
4951/* Returns a boolean if <qc> needs to emit frames for <qel> encryption level. */
4952static int qc_need_sending(struct quic_conn *qc, struct quic_enc_level *qel)
4953{
4954 return (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) ||
4955 (qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) ||
4956 qel->pktns->tx.pto_probe ||
4957 !LIST_ISEMPTY(&qel->pktns->tx.frms);
4958}
4959
4960/* QUIC connection packet handler task. */
4961struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
4962{
4963 int ret, ssl_err;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004964 struct quic_conn *qc = context;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004965 enum quic_tls_enc_level tel, next_tel;
4966 struct quic_enc_level *qel, *next_qel;
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02004967 /* Early-data encryption level */
4968 struct quic_enc_level *eqel;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004969 struct buffer *buf = NULL;
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01004970 int st, zero_rtt;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004971
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004972 TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02004973 eqel = &qc->els[QUIC_TLS_ENC_LEVEL_EARLY_DATA];
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004974 st = qc->state;
4975 TRACE_PROTO("connection state", QUIC_EV_CONN_IO_CB, qc, &st);
4976
4977 /* Retranmissions */
4978 if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
4979 TRACE_DEVEL("retransmission needed", QUIC_EV_CONN_PHPKTS, qc);
4980 qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004981 if (!qc_dgrams_retransmit(qc))
4982 goto out;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004983 }
4984
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004985 ssl_err = SSL_ERROR_NONE;
4986 zero_rtt = st < QUIC_HS_ST_COMPLETE &&
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02004987 quic_tls_has_rx_sec(eqel) &&
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02004988 (!LIST_ISEMPTY(&eqel->rx.pqpkts) || qc_el_rx_pkts(eqel));
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01004989
4990 if (qc_test_fd(qc))
4991 qc_rcv_buf(qc);
4992
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004993 if (st >= QUIC_HS_ST_COMPLETE &&
4994 qc_el_rx_pkts(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE])) {
4995 TRACE_DEVEL("remaining Handshake packets", QUIC_EV_CONN_PHPKTS, qc);
4996 /* There may be remaining Handshake packets to treat and acknowledge. */
4997 tel = QUIC_TLS_ENC_LEVEL_HANDSHAKE;
4998 next_tel = QUIC_TLS_ENC_LEVEL_APP;
4999 }
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005000 else if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, zero_rtt))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005001 goto out;
5002
5003 qel = &qc->els[tel];
5004 next_qel = next_tel == QUIC_TLS_ENC_LEVEL_NONE ? NULL : &qc->els[next_tel];
5005
5006 next_level:
5007 /* Treat packets waiting for header packet protection decryption */
5008 if (!LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel))
5009 qc_rm_hp_pkts(qc, qel);
5010
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01005011 if (!qc_treat_rx_pkts(qc, qel, next_qel))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005012 goto out;
5013
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01005014 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
5015 TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_PHPKTS, qc);
5016 goto out;
5017 }
5018
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005019 if ((qc->flags & QUIC_FL_CONN_DRAINING) &&
5020 !(qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE))
5021 goto out;
5022
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005023 zero_rtt = st < QUIC_HS_ST_COMPLETE &&
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005024 quic_tls_has_rx_sec(eqel) &&
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005025 (!LIST_ISEMPTY(&eqel->rx.pqpkts) || qc_el_rx_pkts(eqel));
5026 if (next_qel && next_qel == eqel && zero_rtt) {
5027 TRACE_DEVEL("select 0RTT as next encryption level",
5028 QUIC_EV_CONN_PHPKTS, qc);
5029 qel = next_qel;
5030 next_qel = NULL;
5031 goto next_level;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005032 }
5033
5034 st = qc->state;
5035 if (st >= QUIC_HS_ST_COMPLETE) {
5036 if (!(qc->flags & QUIC_FL_CONN_POST_HANDSHAKE_FRAMES_BUILT) &&
5037 !quic_build_post_handshake_frames(qc))
5038 goto out;
5039
5040 if (!(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].tls_ctx.flags &
5041 QUIC_FL_TLS_SECRETS_DCD)) {
5042 /* Discard the Handshake keys. */
5043 quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]);
5044 TRACE_PROTO("discarding Handshake pktns", QUIC_EV_CONN_PHPKTS, qc);
5045 quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns, qc);
5046 qc_set_timer(qc);
5047 qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]);
5048 qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns);
5049 }
5050
5051 if (qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) {
5052 /* There may be remaining handshake to build (acks) */
5053 st = QUIC_HS_ST_SERVER_HANDSHAKE;
5054 }
5055 }
5056
5057 /* A listener does not send any O-RTT packet. O-RTT packet number space must not
5058 * be considered.
5059 */
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005060 if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, 0))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005061 goto out;
5062
5063 if (!qc_need_sending(qc, qel) &&
5064 (!next_qel || !qc_need_sending(qc, next_qel))) {
5065 goto skip_send;
5066 }
5067
5068 buf = qc_txb_alloc(qc);
5069 if (!buf)
5070 goto out;
5071
Amaury Denoyelle147862d2023-02-28 15:10:00 +01005072 if (b_data(buf) && !qc_purge_txbuf(qc, buf))
5073 goto skip_send;
5074
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005075 /* Currently buf cannot be non-empty at this stage. Even if a previous
5076 * sendto() has failed it is emptied to simulate packet emission and
5077 * rely on QUIC lost detection to try to emit it.
5078 */
5079 BUG_ON_HOT(b_data(buf));
5080 b_reset(buf);
5081
5082 ret = qc_prep_pkts(qc, buf, tel, &qc->els[tel].pktns->tx.frms,
5083 next_tel, &qc->els[next_tel].pktns->tx.frms);
Amaury Denoyelle37333862023-02-28 11:53:48 +01005084 if (ret == -1) {
5085 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005086 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01005087 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005088
Amaury Denoyelle37333862023-02-28 11:53:48 +01005089 if (ret && !qc_send_ppkts(buf, qc->xprt_ctx)) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01005090 if (qc->flags & QUIC_FL_CONN_TO_KILL)
5091 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005092 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01005093 }
5094
5095 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005096
5097 skip_send:
5098 /* Check if there is something to do for the next level.
5099 */
5100 if (next_qel && next_qel != qel &&
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005101 quic_tls_has_rx_sec(next_qel) &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005102 (!LIST_ISEMPTY(&next_qel->rx.pqpkts) || qc_el_rx_pkts(next_qel))) {
5103 qel = next_qel;
5104 next_qel = NULL;
5105 goto next_level;
5106 }
5107
5108 out:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01005109 TRACE_PROTO("ssl error", QUIC_EV_CONN_IO_CB, qc, &st, &ssl_err);
5110 TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005111 return t;
5112}
5113
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005114/* Release the memory allocated for <cs> CRYPTO stream */
5115void quic_cstream_free(struct quic_cstream *cs)
5116{
5117 if (!cs) {
5118 /* This is the case for ORTT encryption level */
5119 return;
5120 }
5121
Amaury Denoyellebc174b22022-11-17 10:12:52 +01005122 quic_free_ncbuf(&cs->rx.ncbuf);
5123
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005124 qc_stream_desc_release(cs->desc);
5125 pool_free(pool_head_quic_cstream, cs);
5126}
5127
5128/* Allocate a new QUIC stream for <qc>.
5129 * Return it if succeeded, NULL if not.
5130 */
5131struct quic_cstream *quic_cstream_new(struct quic_conn *qc)
5132{
5133 struct quic_cstream *cs, *ret_cs = NULL;
5134
5135 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
5136 cs = pool_alloc(pool_head_quic_cstream);
5137 if (!cs) {
5138 TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
5139 goto leave;
5140 }
5141
5142 cs->rx.offset = 0;
5143 cs->rx.ncbuf = NCBUF_NULL;
5144 cs->rx.offset = 0;
5145
5146 cs->tx.offset = 0;
5147 cs->tx.sent_offset = 0;
5148 cs->tx.buf = BUF_NULL;
5149 cs->desc = qc_stream_desc_new((uint64_t)-1, -1, cs, qc);
5150 if (!cs->desc) {
5151 TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
5152 goto err;
5153 }
5154
5155 ret_cs = cs;
5156 leave:
5157 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
5158 return ret_cs;
5159
5160 err:
5161 pool_free(pool_head_quic_cstream, cs);
5162 goto leave;
5163}
5164
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005165/* Uninitialize <qel> QUIC encryption level. Never fails. */
5166static void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel)
5167{
5168 int i;
5169
5170 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
5171
5172 for (i = 0; i < qel->tx.crypto.nb_buf; i++) {
5173 if (qel->tx.crypto.bufs[i]) {
5174 pool_free(pool_head_quic_crypto_buf, qel->tx.crypto.bufs[i]);
5175 qel->tx.crypto.bufs[i] = NULL;
5176 }
5177 }
5178 ha_free(&qel->tx.crypto.bufs);
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005179 quic_cstream_free(qel->cstream);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005180
5181 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
5182}
5183
5184/* Initialize QUIC TLS encryption level with <level<> as level for <qc> QUIC
5185 * connection allocating everything needed.
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005186 *
5187 * Returns 1 if succeeded, 0 if not. On error the caller is responsible to use
5188 * quic_conn_enc_level_uninit() to cleanup partially allocated content.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005189 */
5190static int quic_conn_enc_level_init(struct quic_conn *qc,
5191 enum quic_tls_enc_level level)
5192{
5193 int ret = 0;
5194 struct quic_enc_level *qel;
5195
5196 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
5197
5198 qel = &qc->els[level];
5199 qel->level = quic_to_ssl_enc_level(level);
5200 qel->tls_ctx.rx.aead = qel->tls_ctx.tx.aead = NULL;
5201 qel->tls_ctx.rx.md = qel->tls_ctx.tx.md = NULL;
5202 qel->tls_ctx.rx.hp = qel->tls_ctx.tx.hp = NULL;
5203 qel->tls_ctx.flags = 0;
5204
5205 qel->rx.pkts = EB_ROOT;
5206 LIST_INIT(&qel->rx.pqpkts);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005207
5208 /* Allocate only one buffer. */
5209 /* TODO: use a pool */
5210 qel->tx.crypto.bufs = malloc(sizeof *qel->tx.crypto.bufs);
5211 if (!qel->tx.crypto.bufs)
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005212 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005213
5214 qel->tx.crypto.bufs[0] = pool_alloc(pool_head_quic_crypto_buf);
5215 if (!qel->tx.crypto.bufs[0])
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005216 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005217
5218 qel->tx.crypto.bufs[0]->sz = 0;
5219 qel->tx.crypto.nb_buf = 1;
5220
5221 qel->tx.crypto.sz = 0;
5222 qel->tx.crypto.offset = 0;
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005223 /* No CRYPTO data for early data TLS encryption level */
5224 if (level == QUIC_TLS_ENC_LEVEL_EARLY_DATA)
5225 qel->cstream = NULL;
5226 else {
5227 qel->cstream = quic_cstream_new(qc);
5228 if (!qel->cstream)
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005229 goto leave;
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005230 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005231
5232 ret = 1;
5233 leave:
5234 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
5235 return ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005236}
5237
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005238/* Return 1 if <qc> connection may probe the Initial packet number space, 0 if not.
5239 * This is not the case if the remote peer address is not validated and if
5240 * it cannot send at least QUIC_INITIAL_PACKET_MINLEN bytes.
5241 */
5242static int qc_may_probe_ipktns(struct quic_conn *qc)
5243{
5244 return quic_peer_validated_addr(qc) ||
5245 (int)(3 * qc->rx.bytes - qc->tx.prep_bytes) >= QUIC_INITIAL_PACKET_MINLEN;
5246}
5247
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005248/* Callback called upon loss detection and PTO timer expirations. */
5249struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state)
5250{
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005251 struct quic_conn *qc = ctx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005252 struct quic_pktns *pktns;
5253
Frédéric Lécaille8f991942023-03-24 15:14:45 +01005254 TRACE_ENTER(QUIC_EV_CONN_PTIMER, qc);
5255 TRACE_PROTO("process timer", QUIC_EV_CONN_PTIMER, qc,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005256 NULL, NULL, &qc->path->ifae_pkts);
5257 task->expire = TICK_ETERNITY;
5258 pktns = quic_loss_pktns(qc);
5259 if (tick_isset(pktns->tx.loss_time)) {
5260 struct list lost_pkts = LIST_HEAD_INIT(lost_pkts);
5261
5262 qc_packet_loss_lookup(pktns, qc, &lost_pkts);
5263 if (!LIST_ISEMPTY(&lost_pkts))
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005264 tasklet_wakeup(qc->wait_event.tasklet);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01005265 if (qc_release_lost_pkts(qc, pktns, &lost_pkts, now_ms))
5266 qc_set_timer(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005267 goto out;
5268 }
5269
5270 if (qc->path->in_flight) {
Frédéric Lécailleb75eecc2023-01-26 15:18:17 +01005271 pktns = quic_pto_pktns(qc, qc->state >= QUIC_HS_ST_CONFIRMED, NULL);
Frédéric Lécaille68737312023-04-07 16:28:46 +02005272 if (!pktns->tx.in_flight) {
5273 TRACE_PROTO("No in flight packets to probe with", QUIC_EV_CONN_TXPKT, qc);
5274 goto out;
5275 }
5276
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005277 if (pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL]) {
5278 if (qc_may_probe_ipktns(qc)) {
5279 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5280 pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
5281 TRACE_STATE("needs to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5282 }
5283 else {
5284 TRACE_STATE("Cannot probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5285 }
5286 if (qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].tx.in_flight) {
5287 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5288 qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
5289 TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
5290 }
Frédéric Lécaillee25fce02023-03-20 17:23:19 +01005291 }
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005292 else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE]) {
5293 TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
5294 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5295 pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
5296 if (qc->pktns[QUIC_TLS_PKTNS_INITIAL].tx.in_flight) {
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005297 if (qc_may_probe_ipktns(qc)) {
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005298 qc->pktns[QUIC_TLS_PKTNS_INITIAL].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005299 TRACE_STATE("needs to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5300 }
5301 else {
5302 TRACE_STATE("Cannot probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5303 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005304 }
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005305 }
5306 else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT]) {
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01005307 pktns->tx.pto_probe = QUIC_MAX_NB_PTO_DGRAMS;
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005308 /* Wake up upper layer if waiting to send new data. */
5309 if (!qc_notify_send(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005310 TRACE_STATE("needs to probe 01RTT packet number space", QUIC_EV_CONN_TXPKT, qc);
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005311 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5312 pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005313 }
5314 }
5315 }
5316 else if (!qc_is_listener(qc) && qc->state <= QUIC_HS_ST_COMPLETE) {
5317 struct quic_enc_level *iel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
5318 struct quic_enc_level *hel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
5319
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005320 if (quic_tls_has_tx_sec(hel))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005321 hel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005322 if (quic_tls_has_tx_sec(iel))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005323 iel->pktns->tx.pto_probe = 1;
5324 }
5325
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005326 tasklet_wakeup(qc->wait_event.tasklet);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005327 qc->path->loss.pto_count++;
5328
5329 out:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01005330 TRACE_PROTO("process timer", QUIC_EV_CONN_PTIMER, qc, pktns);
5331 TRACE_LEAVE(QUIC_EV_CONN_PTIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005332
5333 return task;
5334}
5335
5336/* Parse the Retry token from buffer <token> with <end> a pointer to
5337 * one byte past the end of this buffer. This will extract the ODCID
5338 * which will be stored into <odcid>
5339 *
5340 * Returns 0 on success else non-zero.
5341 */
5342static int parse_retry_token(struct quic_conn *qc,
5343 const unsigned char *token, const unsigned char *end,
5344 struct quic_cid *odcid)
5345{
5346 int ret = 0;
5347 uint64_t odcid_len;
5348 uint32_t timestamp;
5349
5350 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
5351
5352 if (!quic_dec_int(&odcid_len, &token, end)) {
5353 TRACE_ERROR("quic_dec_int() error", QUIC_EV_CONN_LPKT, qc);
5354 goto leave;
5355 }
5356
5357 /* RFC 9000 7.2. Negotiating Connection IDs:
5358 * When an Initial packet is sent by a client that has not previously
5359 * received an Initial or Retry packet from the server, the client
5360 * populates the Destination Connection ID field with an unpredictable
5361 * value. This Destination Connection ID MUST be at least 8 bytes in length.
5362 */
5363 if (odcid_len < QUIC_ODCID_MINLEN || odcid_len > QUIC_CID_MAXLEN) {
5364 TRACE_ERROR("wrong ODCID length", QUIC_EV_CONN_LPKT, qc);
5365 goto leave;
5366 }
5367
5368 if (end - token < odcid_len + sizeof timestamp) {
5369 TRACE_ERROR("too long ODCID length", QUIC_EV_CONN_LPKT, qc);
5370 goto leave;
5371 }
5372
5373 timestamp = ntohl(read_u32(token + odcid_len));
5374 if (timestamp + MS_TO_TICKS(QUIC_RETRY_DURATION_MS) <= now_ms) {
5375 TRACE_ERROR("token has expired", QUIC_EV_CONN_LPKT, qc);
5376 goto leave;
5377 }
5378
5379 ret = 1;
5380 memcpy(odcid->data, token, odcid_len);
5381 odcid->len = odcid_len;
5382 leave:
5383 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
5384 return !ret;
5385}
5386
5387/* Allocate a new QUIC connection with <version> as QUIC version. <ipv4>
5388 * boolean is set to 1 for IPv4 connection, 0 for IPv6. <server> is set to 1
5389 * for QUIC servers (or haproxy listeners).
5390 * <dcid> is the destination connection ID, <scid> is the source connection ID,
5391 * <token> the token found to be used for this connection with <token_len> as
Amaury Denoyelle97ecc7a2022-09-23 17:15:58 +02005392 * length. Endpoints addresses are specified via <local_addr> and <peer_addr>.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005393 * Returns the connection if succeeded, NULL if not.
5394 */
5395static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
5396 struct quic_cid *dcid, struct quic_cid *scid,
5397 const struct quic_cid *token_odcid,
Amaury Denoyelle97ecc7a2022-09-23 17:15:58 +02005398 struct sockaddr_storage *local_addr,
5399 struct sockaddr_storage *peer_addr,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005400 int server, int token, void *owner)
5401{
5402 int i;
5403 struct quic_conn *qc;
5404 /* Initial CID. */
5405 struct quic_connection_id *icid;
5406 char *buf_area = NULL;
5407 struct listener *l = NULL;
5408 struct quic_cc_algo *cc_algo = NULL;
5409 struct quic_tls_ctx *ictx;
5410 TRACE_ENTER(QUIC_EV_CONN_INIT);
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005411 /* TODO replace pool_zalloc by pool_alloc(). This requires special care
5412 * to properly initialized internal quic_conn members to safely use
5413 * quic_conn_release() on alloc failure.
5414 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005415 qc = pool_zalloc(pool_head_quic_conn);
5416 if (!qc) {
5417 TRACE_ERROR("Could not allocate a new connection", QUIC_EV_CONN_INIT);
5418 goto err;
5419 }
5420
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005421 /* Initialize in priority qc members required for a safe dealloc. */
5422
5423 /* required to use MTLIST_IN_LIST */
5424 MT_LIST_INIT(&qc->accept_list);
5425
5426 LIST_INIT(&qc->rx.pkt_list);
5427
Amaury Denoyelle42448332022-12-12 11:24:05 +01005428 qc_init_fd(qc);
5429
Amaury Denoyelle15c74702023-02-01 10:18:26 +01005430 LIST_INIT(&qc->back_refs);
5431
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005432 /* Now proceeds to allocation of qc members. */
5433
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005434 buf_area = pool_alloc(pool_head_quic_conn_rxbuf);
5435 if (!buf_area) {
5436 TRACE_ERROR("Could not allocate a new RX buffer", QUIC_EV_CONN_INIT, qc);
5437 goto err;
5438 }
5439
5440 qc->cids = EB_ROOT;
5441 /* QUIC Server (or listener). */
5442 if (server) {
5443 struct proxy *prx;
5444
5445 l = owner;
5446 prx = l->bind_conf->frontend;
5447 cc_algo = l->bind_conf->quic_cc_algo;
5448
5449 qc->prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe,
5450 &quic_stats_module);
5451 qc->flags |= QUIC_FL_CONN_LISTENER;
5452 qc->state = QUIC_HS_ST_SERVER_INITIAL;
Amaury Denoyelle15adc4c2023-04-05 09:50:17 +02005453 /* Copy the client original DCID. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005454 qc->odcid.len = dcid->len;
Amaury Denoyelle15adc4c2023-04-05 09:50:17 +02005455 memcpy(qc->odcid.data, dcid->data, dcid->len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005456
5457 /* copy the packet SCID to reuse it as DCID for sending */
5458 if (scid->len)
5459 memcpy(qc->dcid.data, scid->data, scid->len);
5460 qc->dcid.len = scid->len;
5461 qc->tx.buf = BUF_NULL;
5462 qc->li = l;
5463 }
5464 /* QUIC Client (outgoing connection to servers) */
5465 else {
5466 qc->state = QUIC_HS_ST_CLIENT_INITIAL;
5467 if (dcid->len)
5468 memcpy(qc->dcid.data, dcid->data, dcid->len);
5469 qc->dcid.len = dcid->len;
5470 }
5471 qc->mux_state = QC_MUX_NULL;
5472 qc->err = quic_err_transport(QC_ERR_NO_ERROR);
5473
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01005474 /* Initialize the next CID sequence number to be used for this connection. */
5475 qc->next_cid_seq_num = 0;
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02005476 /* Generate the first connection CID. This is derived from the client
5477 * ODCID and address. This allows to retrieve the connection from the
5478 * ODCID without storing it in the CID tree. This is an interesting
5479 * optimization as the client is expected to stop using its ODCID in
5480 * favor of our generated value.
5481 */
5482 icid = new_quic_cid(&qc->cids, qc, dcid, peer_addr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005483 if (!icid) {
5484 TRACE_ERROR("Could not allocate a new connection ID", QUIC_EV_CONN_INIT, qc);
5485 goto err;
5486 }
5487
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005488 if ((global.tune.options & GTUNE_QUIC_SOCK_PER_CONN) &&
5489 is_addr(local_addr)) {
5490 TRACE_USER("Allocate a socket for QUIC connection", QUIC_EV_CONN_INIT, qc);
5491 qc_alloc_fd(qc, local_addr, peer_addr);
Amaury Denoyellefb375572023-02-01 09:28:32 +01005492
5493 /* haproxy soft-stop is supported only for QUIC connections
5494 * with their owned socket.
5495 */
5496 if (qc_test_fd(qc))
5497 _HA_ATOMIC_INC(&jobs);
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005498 }
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005499
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005500 /* insert the allocated CID in the receiver datagram handler tree */
5501 if (server)
5502 ebmb_insert(&quic_dghdlrs[tid].cids, &icid->node, icid->cid.len);
5503
5504 /* Select our SCID which is the first CID with 0 as sequence number. */
5505 qc->scid = icid->cid;
5506
5507 /* Packet number spaces initialization. */
5508 for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++)
5509 quic_pktns_init(&qc->pktns[i]);
5510 /* QUIC encryption level context initialization. */
5511 for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
5512 if (!quic_conn_enc_level_init(qc, i)) {
5513 TRACE_ERROR("Could not initialize an encryption level", QUIC_EV_CONN_INIT, qc);
5514 goto err;
5515 }
5516 /* Initialize the packet number space. */
5517 qc->els[i].pktns = &qc->pktns[quic_tls_pktns(i)];
5518 }
5519
5520 qc->original_version = qv;
5521 qc->tps_tls_ext = (qc->original_version->num & 0xff000000) == 0xff000000 ?
5522 TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS_DRAFT:
5523 TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS;
5524 /* TX part. */
5525 LIST_INIT(&qc->tx.frms_to_send);
5526 qc->tx.nb_buf = QUIC_CONN_TX_BUFS_NB;
5527 qc->tx.wbuf = qc->tx.rbuf = 0;
5528 qc->tx.bytes = 0;
5529 qc->tx.buf = BUF_NULL;
5530 /* RX part. */
5531 qc->rx.bytes = 0;
5532 qc->rx.buf = b_make(buf_area, QUIC_CONN_RX_BUFSZ, 0, 0);
5533 for (i = 0; i < QCS_MAX_TYPES; i++)
5534 qc->rx.strms[i].nb_streams = 0;
5535
5536 qc->nb_pkt_for_cc = 1;
5537 qc->nb_pkt_since_cc = 0;
5538
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005539 if (!quic_tls_ku_init(qc)) {
5540 TRACE_ERROR("Key update initialization failed", QUIC_EV_CONN_INIT, qc);
5541 goto err;
5542 }
5543
5544 /* XXX TO DO: Only one path at this time. */
5545 qc->path = &qc->paths[0];
5546 quic_path_init(qc->path, ipv4, cc_algo ? cc_algo : default_quic_cc_algo, qc);
5547
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005548 qc->streams_by_id = EB_ROOT_UNIQUE;
5549 qc->stream_buf_count = 0;
Amaury Denoyelle97ecc7a2022-09-23 17:15:58 +02005550 memcpy(&qc->local_addr, local_addr, sizeof(qc->local_addr));
5551 memcpy(&qc->peer_addr, peer_addr, sizeof qc->peer_addr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005552
5553 if (server && !qc_lstnr_params_init(qc, &l->bind_conf->quic_params,
5554 icid->stateless_reset_token,
5555 dcid->data, dcid->len,
5556 qc->scid.data, qc->scid.len, token_odcid))
5557 goto err;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005558
Frédéric Lécailledeb97812023-03-22 11:29:45 +01005559 /* Initialize the idle timeout of the connection at the "max_idle_timeout"
5560 * value from local transport parameters.
5561 */
5562 qc->max_idle_timeout = qc->rx.params.max_idle_timeout;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005563 qc->wait_event.tasklet = tasklet_new();
5564 if (!qc->wait_event.tasklet) {
5565 TRACE_ERROR("tasklet_new() failed", QUIC_EV_CONN_TXPKT);
5566 goto err;
5567 }
5568 qc->wait_event.tasklet->process = quic_conn_io_cb;
5569 qc->wait_event.tasklet->context = qc;
5570 qc->wait_event.events = 0;
5571 /* Set tasklet tid based on the SCID selected by us for this
5572 * connection. The upper layer will also be binded on the same thread.
5573 */
Willy Tarreaueed78262022-12-21 09:09:19 +01005574 qc->tid = quic_get_cid_tid(qc->scid.data, &l->rx);
Willy Tarreauf5a0c8a2022-10-13 16:14:11 +02005575 qc->wait_event.tasklet->tid = qc->tid;
Amaury Denoyellebbb1c682022-09-28 15:15:51 +02005576 qc->subs = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005577
5578 if (qc_conn_alloc_ssl_ctx(qc) ||
5579 !quic_conn_init_timer(qc) ||
5580 !quic_conn_init_idle_timer_task(qc))
5581 goto err;
5582
5583 ictx = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx;
5584 if (!qc_new_isecs(qc, ictx,qc->original_version, dcid->data, dcid->len, 1))
5585 goto err;
5586
Amaury Denoyelle15c74702023-02-01 10:18:26 +01005587 LIST_APPEND(&th_ctx->quic_conns, &qc->el_th_ctx);
5588 qc->qc_epoch = HA_ATOMIC_LOAD(&qc_epoch);
5589
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005590 TRACE_LEAVE(QUIC_EV_CONN_INIT, qc);
5591
5592 return qc;
5593
5594 err:
5595 pool_free(pool_head_quic_conn_rxbuf, buf_area);
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005596 if (qc) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005597 qc->rx.buf.area = NULL;
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005598 quic_conn_release(qc);
5599 }
5600 TRACE_LEAVE(QUIC_EV_CONN_INIT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005601 return NULL;
5602}
5603
5604/* Release the quic_conn <qc>. The connection is removed from the CIDs tree.
5605 * The connection tasklet is killed.
5606 *
5607 * This function must only be called by the thread responsible of the quic_conn
5608 * tasklet.
5609 */
5610void quic_conn_release(struct quic_conn *qc)
5611{
5612 int i;
5613 struct ssl_sock_ctx *conn_ctx;
5614 struct eb64_node *node;
5615 struct quic_tls_ctx *app_tls_ctx;
5616 struct quic_rx_packet *pkt, *pktback;
5617
5618 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
5619
5620 /* We must not free the quic-conn if the MUX is still allocated. */
5621 BUG_ON(qc->mux_state == QC_MUX_READY);
5622
Amaury Denoyellefb375572023-02-01 09:28:32 +01005623 if (qc_test_fd(qc))
5624 _HA_ATOMIC_DEC(&jobs);
5625
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005626 /* Close quic-conn socket fd. */
Amaury Denoyelled3083c92022-12-01 16:20:06 +01005627 qc_release_fd(qc, 0);
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005628
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005629 /* in the unlikely (but possible) case the connection was just added to
5630 * the accept_list we must delete it from there.
5631 */
5632 MT_LIST_DELETE(&qc->accept_list);
5633
5634 /* free remaining stream descriptors */
5635 node = eb64_first(&qc->streams_by_id);
5636 while (node) {
5637 struct qc_stream_desc *stream;
5638
5639 stream = eb64_entry(node, struct qc_stream_desc, by_id);
5640 node = eb64_next(node);
5641
5642 /* all streams attached to the quic-conn are released, so
5643 * qc_stream_desc_free will liberate the stream instance.
5644 */
5645 BUG_ON(!stream->release);
5646 qc_stream_desc_free(stream, 1);
5647 }
5648
5649 /* Purge Rx packet list. */
5650 list_for_each_entry_safe(pkt, pktback, &qc->rx.pkt_list, qc_rx_pkt_list) {
5651 LIST_DELETE(&pkt->qc_rx_pkt_list);
5652 pool_free(pool_head_quic_rx_packet, pkt);
5653 }
5654
5655 if (qc->idle_timer_task) {
5656 task_destroy(qc->idle_timer_task);
5657 qc->idle_timer_task = NULL;
5658 }
5659
5660 if (qc->timer_task) {
5661 task_destroy(qc->timer_task);
5662 qc->timer_task = NULL;
5663 }
5664
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005665 if (qc->wait_event.tasklet)
5666 tasklet_free(qc->wait_event.tasklet);
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005667
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005668 /* remove the connection from receiver cids trees */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005669 ebmb_delete(&qc->scid_node);
5670 free_quic_conn_cids(qc);
5671
5672 conn_ctx = qc->xprt_ctx;
5673 if (conn_ctx) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005674 SSL_free(conn_ctx->ssl);
5675 pool_free(pool_head_quic_conn_ctx, conn_ctx);
5676 }
5677
5678 quic_tls_ku_free(qc);
5679 for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
5680 quic_tls_ctx_secs_free(&qc->els[i].tls_ctx);
5681 quic_conn_enc_level_uninit(qc, &qc->els[i]);
5682 }
5683 quic_tls_ctx_secs_free(&qc->negotiated_ictx);
5684
5685 app_tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
5686 pool_free(pool_head_quic_tls_secret, app_tls_ctx->rx.secret);
5687 pool_free(pool_head_quic_tls_secret, app_tls_ctx->tx.secret);
5688
5689 for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++) {
5690 quic_pktns_tx_pkts_release(&qc->pktns[i], qc);
5691 quic_free_arngs(qc, &qc->pktns[i].rx.arngs);
5692 }
5693
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01005694 qc_detach_th_ctx_list(qc, 0);
Amaury Denoyelle15c74702023-02-01 10:18:26 +01005695
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005696 pool_free(pool_head_quic_conn_rxbuf, qc->rx.buf.area);
5697 pool_free(pool_head_quic_conn, qc);
Frédéric Lécailleeb3e5172023-04-12 13:41:54 +02005698 qc = NULL;
Amaury Denoyellefb375572023-02-01 09:28:32 +01005699
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005700 TRACE_PROTO("QUIC conn. freed", QUIC_EV_CONN_FREED, qc);
5701
5702 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
5703}
5704
5705/* Initialize the timer task of <qc> QUIC connection.
5706 * Returns 1 if succeeded, 0 if not.
5707 */
5708static int quic_conn_init_timer(struct quic_conn *qc)
5709{
5710 int ret = 0;
5711 /* Attach this task to the same thread ID used for the connection */
5712 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
5713
5714 qc->timer_task = task_new_on(qc->tid);
5715 if (!qc->timer_task) {
5716 TRACE_ERROR("timer task allocation failed", QUIC_EV_CONN_NEW, qc);
5717 goto leave;
5718 }
5719
5720 qc->timer = TICK_ETERNITY;
5721 qc->timer_task->process = qc_process_timer;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005722 qc->timer_task->context = qc;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005723
5724 ret = 1;
5725 leave:
5726 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
5727 return ret;
5728}
5729
Frédéric Lécailled7215712023-03-24 18:13:37 +01005730/* Rearm the idle timer or the ack timer (if not already armde) for <qc> QUIC
5731 * connection. */
5732static void qc_idle_timer_do_rearm(struct quic_conn *qc, int arm_ack)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005733{
5734 unsigned int expire;
5735
Amaury Denoyelle77ed6312023-02-01 09:28:55 +01005736 if (stopping && qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) {
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005737 TRACE_PROTO("executing idle timer immediately on stopping", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005738 qc->ack_expire = TICK_ETERNITY;
Amaury Denoyelle77ed6312023-02-01 09:28:55 +01005739 task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG);
5740 }
5741 else {
5742 expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005743 qc->idle_expire = tick_add(now_ms, MS_TO_TICKS(expire));
5744 if (arm_ack) {
5745 /* Arm the ack timer only if not already armed. */
5746 if (!tick_isset(qc->ack_expire)) {
5747 qc->ack_expire = tick_add(now_ms, MS_TO_TICKS(QUIC_ACK_DELAY));
5748 qc->idle_timer_task->expire = qc->ack_expire;
5749 task_queue(qc->idle_timer_task);
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005750 TRACE_PROTO("ack timer armed", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005751 }
5752 }
5753 else {
5754 qc->idle_timer_task->expire = tick_first(qc->ack_expire, qc->idle_expire);
5755 task_queue(qc->idle_timer_task);
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005756 TRACE_PROTO("idle timer armed", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005757 }
Amaury Denoyelle77ed6312023-02-01 09:28:55 +01005758 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005759}
5760
Frédéric Lécailled7215712023-03-24 18:13:37 +01005761/* Rearm the idle timer or ack timer for <qc> QUIC connection depending on <read>
5762 * and <arm_ack> booleans. The former is set to 1 when receiving a packet ,
5763 * and 0 when sending packet. <arm_ack> is set to 1 if this is the ack timer
5764 * which must be rearmed.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005765 */
Frédéric Lécailled7215712023-03-24 18:13:37 +01005766static void qc_idle_timer_rearm(struct quic_conn *qc, int read, int arm_ack)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005767{
5768 TRACE_ENTER(QUIC_EV_CONN_IDLE_TIMER, qc);
5769
5770 if (read) {
5771 qc->flags |= QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ;
5772 }
5773 else {
5774 qc->flags &= ~QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ;
5775 }
Frédéric Lécailled7215712023-03-24 18:13:37 +01005776 qc_idle_timer_do_rearm(qc, arm_ack);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005777
5778 TRACE_LEAVE(QUIC_EV_CONN_IDLE_TIMER, qc);
5779}
5780
5781/* The task handling the idle timeout */
5782struct task *qc_idle_timer_task(struct task *t, void *ctx, unsigned int state)
5783{
5784 struct quic_conn *qc = ctx;
5785 struct quic_counters *prx_counters = qc->prx_counters;
5786 unsigned int qc_flags = qc->flags;
5787
5788 TRACE_ENTER(QUIC_EV_CONN_IDLE_TIMER, qc);
5789
Frédéric Lécaille12eca3a2023-04-04 10:46:54 +02005790 if ((state & TASK_WOKEN_ANY) == TASK_WOKEN_TIMER && !tick_is_expired(t->expire, now_ms))
5791 goto requeue;
5792
Frédéric Lécailled7215712023-03-24 18:13:37 +01005793 if (tick_is_expired(qc->ack_expire, now_ms)) {
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005794 TRACE_PROTO("ack timer expired", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005795 qc->ack_expire = TICK_ETERNITY;
5796 /* Note that ->idle_expire is always set. */
5797 t->expire = qc->idle_expire;
5798 qc->flags |= QUIC_FL_CONN_ACK_TIMER_FIRED;
5799 tasklet_wakeup(qc->wait_event.tasklet);
5800 goto requeue;
5801 }
5802
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005803 TRACE_PROTO("idle timer task running", QUIC_EV_CONN_IDLE_TIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005804 /* Notify the MUX before settings QUIC_FL_CONN_EXP_TIMER or the MUX
5805 * might free the quic-conn too early via quic_close().
5806 */
5807 qc_notify_close(qc);
5808
5809 /* If the MUX is still alive, keep the quic-conn. The MUX is
5810 * responsible to call quic_close to release it.
5811 */
5812 qc->flags |= QUIC_FL_CONN_EXP_TIMER;
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005813 if (qc->mux_state != QC_MUX_READY) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005814 quic_conn_release(qc);
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005815 qc = NULL;
5816 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005817
5818 /* TODO if the quic-conn cannot be freed because of the MUX, we may at
5819 * least clean some parts of it such as the tasklet.
5820 */
5821
5822 if (!(qc_flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
5823 qc_flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005824 TRACE_DEVEL("dec half open counter", QUIC_EV_CONN_IDLE_TIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005825 HA_ATOMIC_DEC(&prx_counters->half_open_conn);
5826 }
5827
Frédéric Lécailled7215712023-03-24 18:13:37 +01005828 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005829 TRACE_LEAVE(QUIC_EV_CONN_IDLE_TIMER, qc);
5830 return NULL;
Frédéric Lécailled7215712023-03-24 18:13:37 +01005831
5832 requeue:
5833 TRACE_LEAVE(QUIC_EV_CONN_IDLE_TIMER, qc);
5834 return t;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005835}
5836
5837/* Initialize the idle timeout task for <qc>.
5838 * Returns 1 if succeeded, 0 if not.
5839 */
5840static int quic_conn_init_idle_timer_task(struct quic_conn *qc)
5841{
5842 int ret = 0;
5843
5844 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
5845
5846 qc->idle_timer_task = task_new_here();
5847 if (!qc->idle_timer_task) {
5848 TRACE_ERROR("Idle timer task allocation failed", QUIC_EV_CONN_NEW, qc);
5849 goto leave;
5850 }
5851
5852 qc->idle_timer_task->process = qc_idle_timer_task;
5853 qc->idle_timer_task->context = qc;
Frédéric Lécailled7215712023-03-24 18:13:37 +01005854 qc->ack_expire = TICK_ETERNITY;
5855 qc_idle_timer_rearm(qc, 1, 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005856 task_queue(qc->idle_timer_task);
5857
5858 ret = 1;
5859 leave:
5860 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
5861 return ret;
5862}
5863
5864/* Parse into <pkt> a long header located at <*buf> buffer, <end> begin a pointer to the end
5865 * past one byte of this buffer.
5866 */
5867static inline int quic_packet_read_long_header(unsigned char **buf, const unsigned char *end,
5868 struct quic_rx_packet *pkt)
5869{
5870 int ret = 0;
5871 unsigned char dcid_len, scid_len;
5872
5873 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
5874
5875 if (end == *buf) {
5876 TRACE_ERROR("buffer data consumed", QUIC_EV_CONN_RXPKT);
5877 goto leave;
5878 }
5879
5880 /* Destination Connection ID Length */
5881 dcid_len = *(*buf)++;
5882 /* We want to be sure we can read <dcid_len> bytes and one more for <scid_len> value */
5883 if (dcid_len > QUIC_CID_MAXLEN || end - *buf < dcid_len + 1) {
5884 TRACE_ERROR("too long DCID", QUIC_EV_CONN_RXPKT);
5885 goto leave;
5886 }
5887
5888 if (dcid_len) {
5889 /* Check that the length of this received DCID matches the CID lengths
5890 * of our implementation for non Initials packets only.
5891 */
5892 if (pkt->type != QUIC_PACKET_TYPE_INITIAL &&
5893 pkt->type != QUIC_PACKET_TYPE_0RTT &&
5894 dcid_len != QUIC_HAP_CID_LEN) {
5895 TRACE_ERROR("wrong DCID length", QUIC_EV_CONN_RXPKT);
5896 goto leave;
5897 }
5898
5899 memcpy(pkt->dcid.data, *buf, dcid_len);
5900 }
5901
5902 pkt->dcid.len = dcid_len;
5903 *buf += dcid_len;
5904
5905 /* Source Connection ID Length */
5906 scid_len = *(*buf)++;
5907 if (scid_len > QUIC_CID_MAXLEN || end - *buf < scid_len) {
5908 TRACE_ERROR("too long SCID", QUIC_EV_CONN_RXPKT);
5909 goto leave;
5910 }
5911
5912 if (scid_len)
5913 memcpy(pkt->scid.data, *buf, scid_len);
5914 pkt->scid.len = scid_len;
5915 *buf += scid_len;
5916
5917 ret = 1;
5918 leave:
5919 TRACE_LEAVE(QUIC_EV_CONN_RXPKT);
5920 return ret;
5921}
5922
5923/* Insert <pkt> RX packet in its <qel> RX packets tree */
5924static void qc_pkt_insert(struct quic_conn *qc,
5925 struct quic_rx_packet *pkt, struct quic_enc_level *qel)
5926{
5927 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
5928
5929 pkt->pn_node.key = pkt->pn;
5930 quic_rx_packet_refinc(pkt);
5931 eb64_insert(&qel->rx.pkts, &pkt->pn_node);
5932
5933 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
5934}
5935
Amaury Denoyelle845169d2022-10-17 18:05:26 +02005936/* Try to remove the header protection of <pkt> QUIC packet with <beg> the
5937 * address of the packet first byte, using the keys from encryption level <el>.
5938 *
5939 * If header protection has been successfully removed, packet data are copied
5940 * into <qc> Rx buffer. If <el> secrets are not yet available, the copy is also
5941 * proceeded, and the packet is inserted into <qc> protected packets tree. In
5942 * both cases, packet can now be considered handled by the <qc> connection.
5943 *
5944 * If header protection cannot be removed due to <el> secrets already
5945 * discarded, no operation is conducted.
5946 *
5947 * Returns 1 on success : packet data is now handled by the connection. On
5948 * error 0 is returned : packet should be dropped by the caller.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005949 */
5950static inline int qc_try_rm_hp(struct quic_conn *qc,
5951 struct quic_rx_packet *pkt,
Amaury Denoyelle845169d2022-10-17 18:05:26 +02005952 unsigned char *beg,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005953 struct quic_enc_level **el)
5954{
5955 int ret = 0;
5956 unsigned char *pn = NULL; /* Packet number field */
5957 enum quic_tls_enc_level tel;
5958 struct quic_enc_level *qel;
5959 /* Only for traces. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005960
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005961 TRACE_ENTER(QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle845169d2022-10-17 18:05:26 +02005962 BUG_ON(!pkt->pn_offset);
5963
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005964 /* The packet number is here. This is also the start minus
5965 * QUIC_PACKET_PN_MAXLEN of the sample used to add/remove the header
5966 * protection.
5967 */
Amaury Denoyelle845169d2022-10-17 18:05:26 +02005968 pn = beg + pkt->pn_offset;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005969
5970 tel = quic_packet_type_enc_level(pkt->type);
5971 qel = &qc->els[tel];
5972
5973 if (qc_qel_may_rm_hp(qc, qel)) {
Frédéric Lécaille72027782023-02-22 16:20:09 +01005974 struct quic_tls_ctx *tls_ctx = qc_select_tls_ctx(qc, qel, pkt);
5975
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005976 /* Note that the following function enables us to unprotect the packet
5977 * number and its length subsequently used to decrypt the entire
5978 * packets.
5979 */
Frédéric Lécaille72027782023-02-22 16:20:09 +01005980 if (!qc_do_rm_hp(qc, pkt, tls_ctx,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005981 qel->pktns->rx.largest_pn, pn, beg)) {
5982 TRACE_PROTO("hp error", QUIC_EV_CONN_TRMHP, qc);
5983 goto out;
5984 }
5985
Frédéric Lécailleece86e62023-03-07 11:53:43 +01005986 qc_handle_spin_bit(qc, pkt, qel);
Amaury Denoyelle845169d2022-10-17 18:05:26 +02005987 /* The AAD includes the packet number field. */
5988 pkt->aad_len = pkt->pn_offset + pkt->pnl;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005989 if (pkt->len - pkt->aad_len < QUIC_TLS_TAG_LEN) {
5990 TRACE_PROTO("Too short packet", QUIC_EV_CONN_TRMHP, qc);
5991 goto out;
5992 }
5993
Frédéric Lécaillec0aaa072023-04-07 17:58:49 +02005994 TRACE_PROTO("RX hp removed", QUIC_EV_CONN_TRMHP, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005995 }
5996 else {
5997 if (qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD) {
5998 /* If the packet number space has been discarded, this packet
5999 * will be not parsed.
6000 */
6001 TRACE_PROTO("Discarded pktns", QUIC_EV_CONN_TRMHP, qc, pkt);
6002 goto out;
6003 }
6004
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006005 TRACE_PROTO("RX hp not removed", QUIC_EV_CONN_TRMHP, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006006 LIST_APPEND(&qel->rx.pqpkts, &pkt->list);
6007 quic_rx_packet_refinc(pkt);
6008 }
6009
6010 *el = qel;
6011 /* No reference counter incrementation here!!! */
6012 LIST_APPEND(&qc->rx.pkt_list, &pkt->qc_rx_pkt_list);
6013 memcpy(b_tail(&qc->rx.buf), beg, pkt->len);
6014 pkt->data = (unsigned char *)b_tail(&qc->rx.buf);
6015 b_add(&qc->rx.buf, pkt->len);
6016
6017 ret = 1;
6018 out:
Frédéric Lécaillec0aaa072023-04-07 17:58:49 +02006019 TRACE_LEAVE(QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006020 return ret;
6021}
6022
6023/* Parse the header form from <byte0> first byte of <pkt> packet to set its type.
6024 * Also set <*long_header> to 1 if this form is long, 0 if not and the version
6025 * of this packet into <*version>.
6026 */
6027static inline int qc_parse_hd_form(struct quic_rx_packet *pkt,
6028 unsigned char **buf, const unsigned char *end,
6029 int *long_header, uint32_t *version)
6030{
6031 int ret = 0;
6032 const unsigned char byte0 = **buf;
6033
6034 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
6035
6036 (*buf)++;
6037 if (byte0 & QUIC_PACKET_LONG_HEADER_BIT) {
6038 unsigned char type =
6039 (byte0 >> QUIC_PACKET_TYPE_SHIFT) & QUIC_PACKET_TYPE_BITMASK;
6040
6041 *long_header = 1;
6042 /* Version */
6043 if (!quic_read_uint32(version, (const unsigned char **)buf, end)) {
6044 TRACE_ERROR("could not read the packet version", QUIC_EV_CONN_RXPKT);
6045 goto out;
6046 }
6047
Frédéric Lécaille21c4c9b2023-01-13 16:37:02 +01006048 if (*version != QUIC_PROTOCOL_VERSION_2) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006049 pkt->type = type;
6050 }
6051 else {
6052 switch (type) {
6053 case 0:
6054 pkt->type = QUIC_PACKET_TYPE_RETRY;
6055 break;
6056 case 1:
6057 pkt->type = QUIC_PACKET_TYPE_INITIAL;
6058 break;
6059 case 2:
6060 pkt->type = QUIC_PACKET_TYPE_0RTT;
6061 break;
6062 case 3:
6063 pkt->type = QUIC_PACKET_TYPE_HANDSHAKE;
6064 break;
6065 }
6066 }
6067 }
6068 else {
Frédéric Lécailleece86e62023-03-07 11:53:43 +01006069 if (byte0 & QUIC_PACKET_SPIN_BIT)
6070 pkt->flags |= QUIC_FL_RX_PACKET_SPIN_BIT;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006071 pkt->type = QUIC_PACKET_TYPE_SHORT;
6072 *long_header = 0;
6073 }
6074
6075 ret = 1;
6076 out:
6077 TRACE_LEAVE(QUIC_EV_CONN_RXPKT);
6078 return ret;
6079}
6080
6081/* Return the QUIC version (quic_version struct) with <version> as version number
6082 * if supported or NULL if not.
6083 */
6084static inline const struct quic_version *qc_supported_version(uint32_t version)
6085{
6086 int i;
6087
6088 for (i = 0; i < quic_versions_nb; i++)
6089 if (quic_versions[i].num == version)
6090 return &quic_versions[i];
6091
6092 return NULL;
6093}
6094
6095/*
6096 * Send a Version Negotiation packet on response to <pkt> on socket <fd> to
6097 * address <addr>.
6098 * Implementation of RFC9000 6. Version Negotiation
6099 *
6100 * TODO implement a rate-limiting sending of Version Negotiation packets
6101 *
6102 * Returns 0 on success else non-zero
6103 */
6104static int send_version_negotiation(int fd, struct sockaddr_storage *addr,
6105 struct quic_rx_packet *pkt)
6106{
6107 char buf[256];
6108 int ret = 0, i = 0, j;
6109 uint32_t version;
6110 const socklen_t addrlen = get_addr_len(addr);
6111
6112 TRACE_ENTER(QUIC_EV_CONN_TXPKT);
6113 /*
6114 * header form
6115 * long header, fixed bit to 0 for Version Negotiation
6116 */
6117 /* TODO: RAND_bytes() should be replaced? */
6118 if (RAND_bytes((unsigned char *)buf, 1) != 1) {
6119 TRACE_ERROR("RAND_bytes() error", QUIC_EV_CONN_TXPKT);
6120 goto out;
6121 }
6122
6123 buf[i++] |= '\x80';
6124 /* null version for Version Negotiation */
6125 buf[i++] = '\x00';
6126 buf[i++] = '\x00';
6127 buf[i++] = '\x00';
6128 buf[i++] = '\x00';
6129
6130 /* source connection id */
6131 buf[i++] = pkt->scid.len;
6132 memcpy(&buf[i], pkt->scid.data, pkt->scid.len);
6133 i += pkt->scid.len;
6134
6135 /* destination connection id */
6136 buf[i++] = pkt->dcid.len;
6137 memcpy(&buf[i], pkt->dcid.data, pkt->dcid.len);
6138 i += pkt->dcid.len;
6139
6140 /* supported version */
6141 for (j = 0; j < quic_versions_nb; j++) {
6142 version = htonl(quic_versions[j].num);
6143 memcpy(&buf[i], &version, sizeof(version));
6144 i += sizeof(version);
6145 }
6146
6147 if (sendto(fd, buf, i, 0, (struct sockaddr *)addr, addrlen) < 0)
6148 goto out;
6149
6150 ret = 1;
6151 out:
6152 TRACE_LEAVE(QUIC_EV_CONN_TXPKT);
6153 return !ret;
6154}
6155
6156/* Send a stateless reset packet depending on <pkt> RX packet information
6157 * from <fd> UDP socket to <dst>
6158 * Return 1 if succeeded, 0 if not.
6159 */
6160static int send_stateless_reset(struct listener *l, struct sockaddr_storage *dstaddr,
6161 struct quic_rx_packet *rxpkt)
6162{
6163 int ret = 0, pktlen, rndlen;
6164 unsigned char pkt[64];
6165 const socklen_t addrlen = get_addr_len(dstaddr);
6166 struct proxy *prx;
6167 struct quic_counters *prx_counters;
6168
6169 TRACE_ENTER(QUIC_EV_STATELESS_RST);
6170
6171 prx = l->bind_conf->frontend;
6172 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
6173 /* 10.3 Stateless Reset (https://www.rfc-editor.org/rfc/rfc9000.html#section-10.3)
6174 * The resulting minimum size of 21 bytes does not guarantee that a Stateless
6175 * Reset is difficult to distinguish from other packets if the recipient requires
6176 * the use of a connection ID. To achieve that end, the endpoint SHOULD ensure
6177 * that all packets it sends are at least 22 bytes longer than the minimum
6178 * connection ID length that it requests the peer to include in its packets,
6179 * adding PADDING frames as necessary. This ensures that any Stateless Reset
6180 * sent by the peer is indistinguishable from a valid packet sent to the endpoint.
6181 * An endpoint that sends a Stateless Reset in response to a packet that is
6182 * 43 bytes or shorter SHOULD send a Stateless Reset that is one byte shorter
6183 * than the packet it responds to.
6184 */
6185
6186 /* Note that we build at most a 42 bytes QUIC packet to mimic a short packet */
6187 pktlen = rxpkt->len <= 43 ? rxpkt->len - 1 : 0;
6188 pktlen = QUIC_MAX(QUIC_STATELESS_RESET_PACKET_MINLEN, pktlen);
6189 rndlen = pktlen - QUIC_STATELESS_RESET_TOKEN_LEN;
6190
6191 /* Put a header of random bytes */
6192 /* TODO: RAND_bytes() should be replaced */
6193 if (RAND_bytes(pkt, rndlen) != 1) {
6194 TRACE_ERROR("RAND_bytes() failed", QUIC_EV_STATELESS_RST);
6195 goto leave;
6196 }
6197
6198 /* Clear the most significant bit, and set the second one */
6199 *pkt = (*pkt & ~0x80) | 0x40;
6200 if (!quic_stateless_reset_token_cpy(NULL, pkt + rndlen, QUIC_STATELESS_RESET_TOKEN_LEN,
6201 rxpkt->dcid.data, rxpkt->dcid.len))
6202 goto leave;
6203
6204 if (sendto(l->rx.fd, pkt, pktlen, 0, (struct sockaddr *)dstaddr, addrlen) < 0)
6205 goto leave;
6206
6207 ret = 1;
6208 HA_ATOMIC_INC(&prx_counters->stateless_reset_sent);
6209 TRACE_PROTO("stateless reset sent", QUIC_EV_STATELESS_RST, NULL, &rxpkt->dcid);
6210 leave:
6211 TRACE_LEAVE(QUIC_EV_STATELESS_RST);
6212 return ret;
6213}
6214
6215/* QUIC server only function.
6216 * Add AAD to <add> buffer from <cid> connection ID and <addr> socket address.
6217 * This is the responsibility of the caller to check <aad> size is big enough
6218 * to contain these data.
6219 * Return the number of bytes copied to <aad>.
6220 */
6221static int quic_generate_retry_token_aad(unsigned char *aad,
6222 uint32_t version,
6223 const struct quic_cid *cid,
6224 const struct sockaddr_storage *addr)
6225{
6226 unsigned char *p;
6227
6228 p = aad;
6229 memcpy(p, &version, sizeof version);
6230 p += sizeof version;
6231 p += quic_saddr_cpy(p, addr);
6232 memcpy(p, cid->data, cid->len);
6233 p += cid->len;
6234
6235 return p - aad;
6236}
6237
6238/* QUIC server only function.
6239 * Generate the token to be used in Retry packets. The token is written to
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05006240 * <buf> with <len> as length. <odcid> is the original destination connection
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006241 * ID and <dcid> is our side destination connection ID (or client source
6242 * connection ID).
6243 * Returns the length of the encoded token or 0 on error.
6244 */
6245static int quic_generate_retry_token(unsigned char *buf, size_t len,
6246 const uint32_t version,
6247 const struct quic_cid *odcid,
6248 const struct quic_cid *dcid,
6249 struct sockaddr_storage *addr)
6250{
6251 int ret = 0;
6252 unsigned char *p;
6253 unsigned char aad[sizeof(uint32_t) + sizeof(in_port_t) +
Amaury Denoyelle6c940562022-10-18 11:05:02 +02006254 sizeof(struct in6_addr) + QUIC_CID_MAXLEN];
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006255 size_t aadlen;
6256 unsigned char salt[QUIC_RETRY_TOKEN_SALTLEN];
6257 unsigned char key[QUIC_TLS_KEY_LEN];
6258 unsigned char iv[QUIC_TLS_IV_LEN];
6259 const unsigned char *sec = (const unsigned char *)global.cluster_secret;
6260 size_t seclen = strlen(global.cluster_secret);
6261 EVP_CIPHER_CTX *ctx = NULL;
6262 const EVP_CIPHER *aead = EVP_aes_128_gcm();
6263 uint32_t timestamp = now_ms;
6264
6265 TRACE_ENTER(QUIC_EV_CONN_TXPKT);
6266
6267 /* We copy the odcid into the token, prefixed by its one byte
6268 * length, the format token byte. It is followed by an AEAD TAG, and finally
6269 * the random bytes used to derive the secret to encrypt the token.
6270 */
6271 if (1 + dcid->len + 1 + QUIC_TLS_TAG_LEN + sizeof salt > len)
6272 goto err;
6273
6274 aadlen = quic_generate_retry_token_aad(aad, version, dcid, addr);
6275 /* TODO: RAND_bytes() should be replaced */
6276 if (RAND_bytes(salt, sizeof salt) != 1) {
6277 TRACE_ERROR("RAND_bytes()", QUIC_EV_CONN_TXPKT);
6278 goto err;
6279 }
6280
6281 if (!quic_tls_derive_retry_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv,
6282 salt, sizeof salt, sec, seclen)) {
6283 TRACE_ERROR("quic_tls_derive_retry_token_secret() failed", QUIC_EV_CONN_TXPKT);
6284 goto err;
6285 }
6286
6287 if (!quic_tls_tx_ctx_init(&ctx, aead, key)) {
6288 TRACE_ERROR("quic_tls_tx_ctx_init() failed", QUIC_EV_CONN_TXPKT);
6289 goto err;
6290 }
6291
6292 /* Token build */
6293 p = buf;
6294 *p++ = QUIC_TOKEN_FMT_RETRY,
6295 *p++ = odcid->len;
6296 memcpy(p, odcid->data, odcid->len);
6297 p += odcid->len;
6298 write_u32(p, htonl(timestamp));
6299 p += sizeof timestamp;
6300
6301 /* Do not encrypt the QUIC_TOKEN_FMT_RETRY byte */
6302 if (!quic_tls_encrypt(buf + 1, p - buf - 1, aad, aadlen, ctx, aead, key, iv)) {
6303 TRACE_ERROR("quic_tls_encrypt() failed", QUIC_EV_CONN_TXPKT);
6304 goto err;
6305 }
6306
6307 p += QUIC_TLS_TAG_LEN;
6308 memcpy(p, salt, sizeof salt);
6309 p += sizeof salt;
6310 EVP_CIPHER_CTX_free(ctx);
6311
6312 ret = p - buf;
6313 leave:
6314 TRACE_LEAVE(QUIC_EV_CONN_TXPKT);
6315 return ret;
6316
6317 err:
6318 if (ctx)
6319 EVP_CIPHER_CTX_free(ctx);
6320 goto leave;
6321}
6322
6323/* QUIC server only function.
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006324 *
6325 * Check the validity of the Retry token from Initial packet <pkt>. <dgram> is
6326 * the UDP datagram containing <pkt> and <l> is the listener instance on which
6327 * it was received. If the token is valid, the ODCID of <qc> QUIC connection
6328 * will be put into <odcid>. <qc> is used to retrieve the QUIC version needed
6329 * to validate the token but it can be NULL : in this case the version will be
6330 * retrieved from the packet.
6331 *
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006332 * Return 1 if succeeded, 0 if not.
6333 */
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006334
6335static int quic_retry_token_check(struct quic_rx_packet *pkt,
6336 struct quic_dgram *dgram,
6337 struct listener *l,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006338 struct quic_conn *qc,
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006339 struct quic_cid *odcid)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006340{
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006341 struct proxy *prx;
6342 struct quic_counters *prx_counters;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006343 int ret = 0;
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006344 unsigned char *token = pkt->token;
6345 const uint64_t tokenlen = pkt->token_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006346 unsigned char buf[128];
6347 unsigned char aad[sizeof(uint32_t) + sizeof(in_port_t) +
Amaury Denoyelle6c940562022-10-18 11:05:02 +02006348 sizeof(struct in6_addr) + QUIC_CID_MAXLEN];
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006349 size_t aadlen;
6350 const unsigned char *salt;
6351 unsigned char key[QUIC_TLS_KEY_LEN];
6352 unsigned char iv[QUIC_TLS_IV_LEN];
6353 const unsigned char *sec = (const unsigned char *)global.cluster_secret;
6354 size_t seclen = strlen(global.cluster_secret);
6355 EVP_CIPHER_CTX *ctx = NULL;
6356 const EVP_CIPHER *aead = EVP_aes_128_gcm();
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006357 const struct quic_version *qv = qc ? qc->original_version :
6358 pkt->version;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006359
6360 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
6361
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006362 /* The caller must ensure this. */
6363 BUG_ON(!global.cluster_secret || !pkt->token_len);
6364
6365 prx = l->bind_conf->frontend;
6366 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
6367
6368 if (*pkt->token != QUIC_TOKEN_FMT_RETRY) {
6369 /* TODO: New token check */
6370 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc, NULL, NULL, pkt->version);
6371 goto leave;
6372 }
6373
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006374 if (sizeof buf < tokenlen) {
6375 TRACE_ERROR("too short buffer", QUIC_EV_CONN_LPKT, qc);
6376 goto err;
6377 }
6378
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006379 aadlen = quic_generate_retry_token_aad(aad, qv->num, &pkt->scid, &dgram->saddr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006380 salt = token + tokenlen - QUIC_RETRY_TOKEN_SALTLEN;
6381 if (!quic_tls_derive_retry_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv,
6382 salt, QUIC_RETRY_TOKEN_SALTLEN, sec, seclen)) {
6383 TRACE_ERROR("Could not derive retry secret", QUIC_EV_CONN_LPKT, qc);
6384 goto err;
6385 }
6386
6387 if (!quic_tls_rx_ctx_init(&ctx, aead, key)) {
6388 TRACE_ERROR("quic_tls_rx_ctx_init() failed", QUIC_EV_CONN_LPKT, qc);
6389 goto err;
6390 }
6391
6392 /* Do not decrypt the QUIC_TOKEN_FMT_RETRY byte */
6393 if (!quic_tls_decrypt2(buf, token + 1, tokenlen - QUIC_RETRY_TOKEN_SALTLEN - 1, aad, aadlen,
6394 ctx, aead, key, iv)) {
6395 TRACE_ERROR("Could not decrypt retry token", QUIC_EV_CONN_LPKT, qc);
6396 goto err;
6397 }
6398
6399 if (parse_retry_token(qc, buf, buf + tokenlen - QUIC_RETRY_TOKEN_SALTLEN - 1, odcid)) {
6400 TRACE_ERROR("Error during Initial token parsing", QUIC_EV_CONN_LPKT, qc);
6401 goto err;
6402 }
6403
6404 EVP_CIPHER_CTX_free(ctx);
6405
6406 ret = 1;
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006407 HA_ATOMIC_INC(&prx_counters->retry_validated);
6408
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006409 leave:
6410 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
6411 return ret;
6412
6413 err:
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006414 HA_ATOMIC_INC(&prx_counters->retry_error);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006415 if (ctx)
6416 EVP_CIPHER_CTX_free(ctx);
6417 goto leave;
6418}
6419
6420/* Generate a Retry packet and send it on <fd> socket to <addr> in response to
6421 * the Initial <pkt> packet.
6422 *
6423 * Returns 0 on success else non-zero.
6424 */
6425static int send_retry(int fd, struct sockaddr_storage *addr,
6426 struct quic_rx_packet *pkt, const struct quic_version *qv)
6427{
6428 int ret = 0;
6429 unsigned char buf[128];
6430 int i = 0, token_len;
6431 const socklen_t addrlen = get_addr_len(addr);
6432 struct quic_cid scid;
6433
6434 TRACE_ENTER(QUIC_EV_CONN_TXPKT);
6435
6436 /* long header + fixed bit + packet type QUIC_PACKET_TYPE_RETRY */
6437 buf[i++] = (QUIC_PACKET_LONG_HEADER_BIT | QUIC_PACKET_FIXED_BIT) |
6438 (quic_pkt_type(QUIC_PACKET_TYPE_RETRY, qv->num) << QUIC_PACKET_TYPE_SHIFT);
6439 /* version */
6440 buf[i++] = *((unsigned char *)&qv->num + 3);
6441 buf[i++] = *((unsigned char *)&qv->num + 2);
6442 buf[i++] = *((unsigned char *)&qv->num + 1);
6443 buf[i++] = *(unsigned char *)&qv->num;
6444
6445 /* Use the SCID from <pkt> for Retry DCID. */
6446 buf[i++] = pkt->scid.len;
6447 memcpy(&buf[i], pkt->scid.data, pkt->scid.len);
6448 i += pkt->scid.len;
6449
6450 /* Generate a new CID to be used as SCID for the Retry packet. */
6451 scid.len = QUIC_HAP_CID_LEN;
6452 /* TODO: RAND_bytes() should be replaced */
6453 if (RAND_bytes(scid.data, scid.len) != 1) {
6454 TRACE_ERROR("RAND_bytes() failed", QUIC_EV_CONN_TXPKT);
6455 goto out;
6456 }
6457
6458 buf[i++] = scid.len;
6459 memcpy(&buf[i], scid.data, scid.len);
6460 i += scid.len;
6461
6462 /* token */
6463 if (!(token_len = quic_generate_retry_token(&buf[i], sizeof(buf) - i, qv->num,
6464 &pkt->dcid, &pkt->scid, addr))) {
6465 TRACE_ERROR("quic_generate_retry_token() failed", QUIC_EV_CONN_TXPKT);
6466 goto out;
6467 }
6468
6469 i += token_len;
6470
6471 /* token integrity tag */
6472 if ((&buf[i] - buf < QUIC_TLS_TAG_LEN) ||
6473 !quic_tls_generate_retry_integrity_tag(pkt->dcid.data,
6474 pkt->dcid.len, buf, i, qv)) {
6475 TRACE_ERROR("quic_tls_generate_retry_integrity_tag() failed", QUIC_EV_CONN_TXPKT);
6476 goto out;
6477 }
6478
6479 i += QUIC_TLS_TAG_LEN;
6480
6481 if (sendto(fd, buf, i, 0, (struct sockaddr *)addr, addrlen) < 0) {
6482 TRACE_ERROR("quic_tls_generate_retry_integrity_tag() failed", QUIC_EV_CONN_TXPKT);
6483 goto out;
6484 }
6485
6486 ret = 1;
6487 out:
6488 TRACE_LEAVE(QUIC_EV_CONN_TXPKT);
6489 return !ret;
6490}
6491
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006492/* Retrieve a quic_conn instance from the <pkt> DCID field. If the packet is an
6493 * INITIAL or 0RTT type, we may have to use client address <saddr> if an ODCID
6494 * is used.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006495 *
6496 * Returns the instance or NULL if not found.
6497 */
6498static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt,
6499 struct listener *l,
6500 struct sockaddr_storage *saddr)
6501{
6502 struct quic_conn *qc = NULL;
6503 struct ebmb_node *node;
6504 struct quic_connection_id *id;
6505 /* set if the quic_conn is found in the second DCID tree */
6506
6507 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
6508
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006509 /* First look into DCID tree. */
6510 node = ebmb_lookup(&quic_dghdlrs[tid].cids, pkt->dcid.data, pkt->dcid.len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006511
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006512 /* If not found on an Initial/0-RTT packet, it could be because an
6513 * ODCID is reused by the client. Calculate the derived CID value to
6514 * retrieve it from the DCID tree.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006515 */
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006516 if (!node && (pkt->type == QUIC_PACKET_TYPE_INITIAL ||
6517 pkt->type == QUIC_PACKET_TYPE_0RTT)) {
6518 uint64_t hash = quic_derive_cid(&pkt->dcid, saddr);
6519 node = ebmb_lookup(&quic_dghdlrs[tid].cids, &hash, sizeof(hash));
6520 }
6521
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006522 if (!node)
6523 goto end;
6524
6525 id = ebmb_entry(node, struct quic_connection_id, node);
6526 qc = id->qc;
6527
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006528 end:
6529 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
6530 return qc;
6531}
6532
6533/* Try to allocate the <*ssl> SSL session object for <qc> QUIC connection
6534 * with <ssl_ctx> as SSL context inherited settings. Also set the transport
6535 * parameters of this session.
6536 * This is the responsibility of the caller to check the validity of all the
6537 * pointers passed as parameter to this function.
6538 * Return 0 if succeeded, -1 if not. If failed, sets the ->err_code member of <qc->conn> to
6539 * CO_ER_SSL_NO_MEM.
6540 */
6541static int qc_ssl_sess_init(struct quic_conn *qc, SSL_CTX *ssl_ctx, SSL **ssl,
6542 unsigned char *params, size_t params_len)
6543{
6544 int retry, ret = -1;
6545
6546 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
6547
6548 retry = 1;
6549 retry:
6550 *ssl = SSL_new(ssl_ctx);
6551 if (!*ssl) {
6552 if (!retry--)
6553 goto err;
6554
6555 pool_gc(NULL);
6556 goto retry;
6557 }
6558
6559 if (!SSL_set_quic_method(*ssl, &ha_quic_method) ||
6560 !SSL_set_ex_data(*ssl, ssl_qc_app_data_index, qc)) {
6561 SSL_free(*ssl);
6562 *ssl = NULL;
6563 if (!retry--)
6564 goto err;
6565
6566 pool_gc(NULL);
6567 goto retry;
6568 }
6569
6570 ret = 0;
6571 leave:
6572 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
6573 return ret;
6574
6575 err:
6576 qc->conn->err_code = CO_ER_SSL_NO_MEM;
6577 goto leave;
6578}
6579
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006580/* Allocate the ssl_sock_ctx from connection <qc>. This creates the tasklet
6581 * used to process <qc> received packets. The allocated context is stored in
6582 * <qc.xprt_ctx>.
6583 *
6584 * Returns 0 on success else non-zero.
6585 */
6586static int qc_conn_alloc_ssl_ctx(struct quic_conn *qc)
6587{
6588 int ret = 0;
6589 struct bind_conf *bc = qc->li->bind_conf;
6590 struct ssl_sock_ctx *ctx = NULL;
6591
6592 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
6593
6594 ctx = pool_zalloc(pool_head_quic_conn_ctx);
6595 if (!ctx) {
6596 TRACE_ERROR("SSL context allocation failed", QUIC_EV_CONN_TXPKT);
6597 goto err;
6598 }
6599
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006600 ctx->subs = NULL;
6601 ctx->xprt_ctx = NULL;
6602 ctx->qc = qc;
6603
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006604 if (qc_is_listener(qc)) {
6605 if (qc_ssl_sess_init(qc, bc->initial_ctx, &ctx->ssl,
6606 qc->enc_params, qc->enc_params_len) == -1) {
6607 goto err;
6608 }
6609#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
6610 /* Enabling 0-RTT */
6611 if (bc->ssl_conf.early_data)
6612 SSL_set_quic_early_data_enabled(ctx->ssl, 1);
6613#endif
6614
6615 SSL_set_accept_state(ctx->ssl);
6616 }
6617
6618 ctx->xprt = xprt_get(XPRT_QUIC);
6619
6620 /* Store the allocated context in <qc>. */
6621 qc->xprt_ctx = ctx;
6622
6623 ret = 1;
6624 leave:
6625 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
6626 return !ret;
6627
6628 err:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006629 pool_free(pool_head_quic_conn_ctx, ctx);
6630 goto leave;
6631}
6632
6633/* Check that all the bytes between <buf> included and <end> address
6634 * excluded are null. This is the responsibility of the caller to
6635 * check that there is at least one byte between <buf> end <end>.
6636 * Return 1 if this all the bytes are null, 0 if not.
6637 */
6638static inline int quic_padding_check(const unsigned char *buf,
6639 const unsigned char *end)
6640{
6641 while (buf < end && !*buf)
6642 buf++;
6643
6644 return buf == end;
6645}
6646
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006647/* Find the associated connection to the packet <pkt> or create a new one if
6648 * this is an Initial packet. <dgram> is the datagram containing the packet and
6649 * <l> is the listener instance on which it was received.
6650 *
6651 * Returns the quic-conn instance or NULL.
6652 */
6653static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
6654 struct quic_dgram *dgram,
6655 struct listener *l)
6656{
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006657 struct quic_cid token_odcid = { .len = 0 };
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006658 struct quic_conn *qc = NULL;
6659 struct proxy *prx;
6660 struct quic_counters *prx_counters;
6661
6662 TRACE_ENTER(QUIC_EV_CONN_LPKT);
6663
6664 prx = l->bind_conf->frontend;
6665 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
6666
6667 qc = retrieve_qc_conn_from_cid(pkt, l, &dgram->saddr);
6668
6669 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
6670 BUG_ON(!pkt->version); /* This must not happen. */
6671
6672 if (global.cluster_secret && pkt->token_len) {
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006673 if (!quic_retry_token_check(pkt, dgram, l, qc, &token_odcid))
6674 goto err;
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006675 }
6676
6677 if (!qc) {
6678 int ipv4;
6679
6680 if (global.cluster_secret && !pkt->token_len && !(l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) &&
6681 HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold) {
6682 TRACE_PROTO("Initial without token, sending retry",
6683 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
6684 if (send_retry(l->rx.fd, &dgram->saddr, pkt, pkt->version)) {
6685 TRACE_ERROR("Error during Retry generation",
6686 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
6687 goto out;
6688 }
6689
6690 HA_ATOMIC_INC(&prx_counters->retry_sent);
6691 goto out;
6692 }
6693
6694 /* RFC 9000 7.2. Negotiating Connection IDs:
6695 * When an Initial packet is sent by a client that has not previously
6696 * received an Initial or Retry packet from the server, the client
6697 * populates the Destination Connection ID field with an unpredictable
6698 * value. This Destination Connection ID MUST be at least 8 bytes in length.
6699 */
6700 if (pkt->dcid.len < QUIC_ODCID_MINLEN) {
6701 TRACE_PROTO("dropped packet",
6702 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
6703 goto err;
6704 }
6705
6706 pkt->saddr = dgram->saddr;
6707 ipv4 = dgram->saddr.ss_family == AF_INET;
6708
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006709 qc = qc_new_conn(pkt->version, ipv4, &pkt->dcid, &pkt->scid, &token_odcid,
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006710 &dgram->daddr, &pkt->saddr, 1,
6711 !!pkt->token_len, l);
6712 if (qc == NULL)
6713 goto err;
6714
6715 HA_ATOMIC_INC(&prx_counters->half_open_conn);
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006716 }
6717 }
6718 else if (!qc) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006719 TRACE_PROTO("RX non Initial pkt without connection", QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006720 if (global.cluster_secret && !send_stateless_reset(l, &dgram->saddr, pkt))
6721 TRACE_ERROR("stateless reset not sent", QUIC_EV_CONN_LPKT, qc);
6722 goto err;
6723 }
6724
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006725 out:
6726 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
6727 return qc;
6728
6729 err:
6730 HA_ATOMIC_INC(&prx_counters->dropped_pkt);
6731 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
6732 return NULL;
6733}
6734
Amaury Denoyelle98289692022-10-19 15:37:44 +02006735/* Parse a QUIC packet starting at <buf>. Data won't be read after <end> even
6736 * if the packet is incomplete. This function will populate fields of <pkt>
6737 * instance, most notably its length. <dgram> is the UDP datagram which
6738 * contains the parsed packet. <l> is the listener instance on which it was
6739 * received.
6740 *
6741 * Returns 0 on success else non-zero. Packet length is guaranteed to be set to
6742 * the real packet value or to cover all data between <buf> and <end> : this is
6743 * useful to reject a whole datagram.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006744 */
Amaury Denoyelle98289692022-10-19 15:37:44 +02006745static int quic_rx_pkt_parse(struct quic_rx_packet *pkt,
6746 unsigned char *buf, const unsigned char *end,
6747 struct quic_dgram *dgram, struct listener *l)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006748{
Amaury Denoyelle98289692022-10-19 15:37:44 +02006749 const unsigned char *beg = buf;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006750 struct proxy *prx;
6751 struct quic_counters *prx_counters;
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006752 int long_header = 0;
Willy Tarreau33a68702022-11-24 09:16:41 +01006753 uint32_t version = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006754 const struct quic_version *qv = NULL;
6755
6756 TRACE_ENTER(QUIC_EV_CONN_LPKT);
6757
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006758 prx = l->bind_conf->frontend;
6759 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
6760 /* This ist only to please to traces and distinguish the
6761 * packet with parsed packet number from others.
6762 */
6763 pkt->pn_node.key = (uint64_t)-1;
6764 if (end <= buf) {
6765 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
6766 goto drop;
6767 }
6768
6769 /* Fixed bit */
6770 if (!(*buf & QUIC_PACKET_FIXED_BIT)) {
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02006771 if (!(pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST) &&
6772 quic_padding_check(buf, end)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006773 /* Some browsers may pad the remaining datagram space with null bytes.
6774 * That is what we called add padding out of QUIC packets. Such
6775 * datagrams must be considered as valid. But we can only consume
6776 * the remaining space.
6777 */
6778 pkt->len = end - buf;
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006779 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006780 }
6781
6782 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
6783 goto drop;
6784 }
6785
6786 /* Header form */
6787 if (!qc_parse_hd_form(pkt, &buf, end, &long_header, &version)) {
6788 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
6789 goto drop;
6790 }
6791
6792 if (long_header) {
6793 uint64_t len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006794
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006795 TRACE_PROTO("long header packet received", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006796 if (!quic_packet_read_long_header(&buf, end, pkt)) {
6797 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
6798 goto drop;
6799 }
6800
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006801 /* When multiple QUIC packets are coalesced on the same UDP datagram,
6802 * they must have the same DCID.
6803 */
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02006804 if (!(pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST) &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006805 (pkt->dcid.len != dgram->dcid_len ||
6806 memcmp(dgram->dcid, pkt->dcid.data, pkt->dcid.len))) {
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006807 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006808 goto drop;
6809 }
6810
6811 /* Retry of Version Negotiation packets are only sent by servers */
6812 if (pkt->type == QUIC_PACKET_TYPE_RETRY || !version) {
6813 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
6814 goto drop;
6815 }
6816
6817 /* RFC9000 6. Version Negotiation */
6818 qv = qc_supported_version(version);
6819 if (!qv) {
6820 /* unsupported version, send Negotiation packet */
6821 if (send_version_negotiation(l->rx.fd, &dgram->saddr, pkt)) {
6822 TRACE_ERROR("VN packet not sent", QUIC_EV_CONN_LPKT);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006823 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006824 }
6825
6826 TRACE_PROTO("VN packet sent", QUIC_EV_CONN_LPKT);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006827 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006828 }
Amaury Denoyelle0eae5722022-10-17 18:05:18 +02006829 pkt->version = qv;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006830
6831 /* For Initial packets, and for servers (QUIC clients connections),
6832 * there is no Initial connection IDs storage.
6833 */
6834 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
6835 uint64_t token_len;
6836
6837 if (!quic_dec_int(&token_len, (const unsigned char **)&buf, end) ||
6838 end - buf < token_len) {
6839 TRACE_PROTO("Packet dropped",
6840 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, qv);
6841 goto drop;
6842 }
6843
6844 /* TODO Retry should be automatically activated if
6845 * suspect network usage is detected.
6846 */
6847 if (global.cluster_secret && !token_len) {
6848 if (l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) {
6849 TRACE_PROTO("Initial without token, sending retry",
Amaury Denoyelle90121b32022-09-27 10:35:29 +02006850 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, qv);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006851 if (send_retry(l->rx.fd, &dgram->saddr, pkt, qv)) {
6852 TRACE_PROTO("Error during Retry generation",
Amaury Denoyelle90121b32022-09-27 10:35:29 +02006853 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, qv);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006854 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006855 }
6856
6857 HA_ATOMIC_INC(&prx_counters->retry_sent);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006858 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006859 }
6860 }
6861 else if (!global.cluster_secret && token_len) {
6862 /* Impossible case: a token was received without configured
6863 * cluster secret.
6864 */
6865 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT,
6866 NULL, NULL, NULL, qv);
6867 goto drop;
6868 }
6869
6870 pkt->token = buf;
6871 pkt->token_len = token_len;
6872 buf += pkt->token_len;
6873 }
6874 else if (pkt->type != QUIC_PACKET_TYPE_0RTT) {
6875 if (pkt->dcid.len != QUIC_HAP_CID_LEN) {
6876 TRACE_PROTO("Packet dropped",
6877 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, qv);
6878 goto drop;
6879 }
6880 }
6881
6882 if (!quic_dec_int(&len, (const unsigned char **)&buf, end) ||
6883 end - buf < len) {
6884 TRACE_PROTO("Packet dropped",
6885 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, qv);
6886 goto drop;
6887 }
6888
Amaury Denoyelle845169d2022-10-17 18:05:26 +02006889 /* Packet Number is stored here. Packet Length totalizes the
6890 * rest of the content.
6891 */
6892 pkt->pn_offset = buf - beg;
6893 pkt->len = pkt->pn_offset + len;
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006894
Frédéric Lécaille35218c62023-02-16 11:40:11 +01006895 /* RFC 9000. Initial Datagram Size
6896 *
6897 * A server MUST discard an Initial packet that is carried in a UDP datagram
6898 * with a payload that is smaller than the smallest allowed maximum datagram
6899 * size of 1200 bytes.
6900 */
6901 if (pkt->type == QUIC_PACKET_TYPE_INITIAL &&
6902 dgram->len < QUIC_INITIAL_PACKET_MINLEN) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006903 TRACE_PROTO("RX too short datagram with an Initial packet", QUIC_EV_CONN_LPKT);
Frédéric Lécaille35218c62023-02-16 11:40:11 +01006904 HA_ATOMIC_INC(&prx_counters->too_short_initial_dgram);
6905 goto drop;
6906 }
6907
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006908 /* Interrupt parsing after packet length retrieval : this
6909 * ensures that only the packet is dropped but not the whole
6910 * datagram.
6911 */
6912 if (pkt->type == QUIC_PACKET_TYPE_0RTT && !l->bind_conf->ssl_conf.early_data) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006913 TRACE_PROTO("RX 0-RTT packet not supported", QUIC_EV_CONN_LPKT);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006914 goto drop;
6915 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006916 }
6917 else {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006918 TRACE_PROTO("RX short header packet", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006919 if (end - buf < QUIC_HAP_CID_LEN) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006920 TRACE_PROTO("RX pkt dropped", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006921 goto drop;
6922 }
6923
6924 memcpy(pkt->dcid.data, buf, QUIC_HAP_CID_LEN);
6925 pkt->dcid.len = QUIC_HAP_CID_LEN;
6926
6927 /* When multiple QUIC packets are coalesced on the same UDP datagram,
6928 * they must have the same DCID.
6929 */
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02006930 if (!(pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST) &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006931 (pkt->dcid.len != dgram->dcid_len ||
6932 memcmp(dgram->dcid, pkt->dcid.data, pkt->dcid.len))) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006933 TRACE_PROTO("RX pkt dropped", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006934 goto drop;
6935 }
6936
6937 buf += QUIC_HAP_CID_LEN;
6938
Amaury Denoyelle845169d2022-10-17 18:05:26 +02006939 pkt->pn_offset = buf - beg;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006940 /* A short packet is the last one of a UDP datagram. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006941 pkt->len = end - beg;
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006942 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006943
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006944 TRACE_PROTO("RX pkt parsed", QUIC_EV_CONN_LPKT, NULL, pkt, NULL, qv);
6945 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
Amaury Denoyelle98289692022-10-19 15:37:44 +02006946 return 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006947
Amaury Denoyelle98289692022-10-19 15:37:44 +02006948 drop:
6949 HA_ATOMIC_INC(&prx_counters->dropped_pkt);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02006950 drop_silent:
Amaury Denoyelle98289692022-10-19 15:37:44 +02006951 if (!pkt->len)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006952 pkt->len = end - beg;
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006953 TRACE_PROTO("RX pkt parsing failed", QUIC_EV_CONN_LPKT, NULL, pkt, NULL, qv);
6954 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
Amaury Denoyelle98289692022-10-19 15:37:44 +02006955 return -1;
6956}
6957
6958/* Check if received packet <pkt> should be drop due to <qc> already in closing
6959 * state. This can be true if a CONNECTION_CLOSE has already been emitted for
6960 * this connection.
6961 *
6962 * Returns false if connection is not in closing state else true. The caller
6963 * should drop the whole datagram in the last case to not mess up <qc>
6964 * CONNECTION_CLOSE rate limit counter.
6965 */
6966static int qc_rx_check_closing(struct quic_conn *qc,
6967 struct quic_rx_packet *pkt)
6968{
6969 if (!(qc->flags & QUIC_FL_CONN_CLOSING))
6970 return 0;
6971
6972 TRACE_STATE("Closing state connection", QUIC_EV_CONN_LPKT, qc, NULL, NULL, pkt->version);
6973
6974 /* Check if CONNECTION_CLOSE rate reemission is reached. */
6975 if (++qc->nb_pkt_since_cc >= qc->nb_pkt_for_cc) {
6976 qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
6977 qc->nb_pkt_for_cc++;
6978 qc->nb_pkt_since_cc = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006979 }
6980
Amaury Denoyelle98289692022-10-19 15:37:44 +02006981 return 1;
6982}
6983
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01006984/* React to a connection migration initiated on <qc> by a client with the new
6985 * path addresses <peer_addr>/<local_addr>.
6986 *
6987 * Returns 0 on success else non-zero.
6988 */
6989static int qc_handle_conn_migration(struct quic_conn *qc,
6990 const struct sockaddr_storage *peer_addr,
6991 const struct sockaddr_storage *local_addr)
6992{
6993 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
6994
Frédéric Lécaille6fc86972023-01-12 08:29:23 +01006995 /* RFC 9000. Connection Migration
6996 *
6997 * If the peer sent the disable_active_migration transport parameter,
6998 * an endpoint also MUST NOT send packets (including probing packets;
6999 * see Section 9.1) from a different local address to the address the peer
7000 * used during the handshake, unless the endpoint has acted on a
7001 * preferred_address transport parameter from the peer.
7002 */
7003 if (qc->li->bind_conf->quic_params.disable_active_migration) {
7004 TRACE_ERROR("Active migration was disabled, datagram dropped", QUIC_EV_CONN_LPKT, qc);
7005 goto err;
7006 }
7007
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007008 /* RFC 9000 9. Connection Migration
7009 *
Amaury Denoyelleeb6be982022-11-21 11:14:45 +01007010 * The design of QUIC relies on endpoints retaining a stable address for
7011 * the duration of the handshake. An endpoint MUST NOT initiate
7012 * connection migration before the handshake is confirmed, as defined in
7013 * Section 4.1.2 of [QUIC-TLS].
7014 */
7015 if (qc->state < QUIC_HS_ST_COMPLETE) {
7016 TRACE_STATE("Connection migration during handshake rejected", QUIC_EV_CONN_LPKT, qc);
7017 goto err;
7018 }
7019
7020 /* RFC 9000 9. Connection Migration
7021 *
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007022 * TODO
7023 * An endpoint MUST
7024 * perform path validation (Section 8.2) if it detects any change to a
7025 * peer's address, unless it has previously validated that address.
7026 */
7027
Amaury Denoyelled3083c92022-12-01 16:20:06 +01007028 /* Update quic-conn owned socket if in used.
7029 * TODO try to reuse it instead of closing and opening a new one.
7030 */
7031 if (qc_test_fd(qc)) {
7032 /* TODO try to reuse socket instead of closing it and opening a new one. */
7033 TRACE_STATE("Connection migration detected, allocate a new connection socket", QUIC_EV_CONN_LPKT, qc);
7034 qc_release_fd(qc, 1);
Amaury Denoyellefb375572023-02-01 09:28:32 +01007035 /* TODO need to adjust <jobs> on socket allocation failure. */
Amaury Denoyelled3083c92022-12-01 16:20:06 +01007036 qc_alloc_fd(qc, local_addr, peer_addr);
7037 }
7038
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007039 qc->local_addr = *local_addr;
7040 qc->peer_addr = *peer_addr;
7041 HA_ATOMIC_INC(&qc->prx_counters->conn_migration_done);
7042
7043 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
7044 return 0;
7045
7046 err:
7047 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
7048 return 1;
7049}
7050
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007051/* Release the memory for the RX packets which are no more referenced
7052 * and consume their payloads which have been copied to the RX buffer
7053 * for the connection.
7054 * Always succeeds.
7055 */
7056static inline void quic_rx_pkts_del(struct quic_conn *qc)
7057{
7058 struct quic_rx_packet *pkt, *pktback;
7059
7060 list_for_each_entry_safe(pkt, pktback, &qc->rx.pkt_list, qc_rx_pkt_list) {
7061 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_LPKT, qc, 0, 0, 0,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007062 "pkt #%lld(type=%d,len=%llu,rawlen=%llu,refcnt=%u) (diff: %zd)",
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007063 (long long)pkt->pn_node.key,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007064 pkt->type, (ull)pkt->len, (ull)pkt->raw_len, pkt->refcnt,
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007065 (unsigned char *)b_head(&qc->rx.buf) - pkt->data);
7066 if (pkt->data != (unsigned char *)b_head(&qc->rx.buf)) {
7067 size_t cdata;
7068
7069 cdata = b_contig_data(&qc->rx.buf, 0);
7070 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_LPKT, qc, 0, 0, 0,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007071 "cdata=%llu *b_head()=0x%x", (ull)cdata, *b_head(&qc->rx.buf));
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007072 if (cdata && !*b_head(&qc->rx.buf)) {
7073 /* Consume the remaining data */
7074 b_del(&qc->rx.buf, cdata);
7075 }
7076 break;
7077 }
7078
7079 if (pkt->refcnt)
7080 break;
7081
7082 b_del(&qc->rx.buf, pkt->raw_len);
7083 LIST_DELETE(&pkt->qc_rx_pkt_list);
7084 pool_free(pool_head_quic_rx_packet, pkt);
7085 }
7086
7087 /* In frequent cases the buffer will be emptied at this stage. */
7088 b_realign_if_empty(&qc->rx.buf);
7089}
7090
Amaury Denoyelle98289692022-10-19 15:37:44 +02007091/* Handle a parsed packet <pkt> by the connection <qc>. Data will be copied
7092 * into <qc> receive buffer after header protection removal procedure.
7093 *
7094 * <dgram> must be set to the datagram which contains the QUIC packet. <beg>
7095 * must point to packet buffer first byte.
7096 *
7097 * <tasklist_head> may be non-NULL when the caller treat several datagrams for
7098 * different quic-conn. In this case, each quic-conn tasklet will be appended
7099 * to it in order to be woken up after the current task.
7100 *
7101 * The caller can safely removed the packet data. If packet refcount was not
7102 * incremented by this function, it means that the connection did not handled
7103 * it and it should be freed by the caller.
7104 */
7105static void qc_rx_pkt_handle(struct quic_conn *qc, struct quic_rx_packet *pkt,
7106 struct quic_dgram *dgram, unsigned char *beg,
7107 struct list **tasklist_head)
7108{
7109 const struct quic_version *qv = pkt->version;
7110 struct quic_enc_level *qel = NULL;
7111 size_t b_cspace;
Amaury Denoyelle98289692022-10-19 15:37:44 +02007112
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007113 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
7114 TRACE_PROTO("RX pkt", QUIC_EV_CONN_LPKT, qc, pkt, NULL, qv);
Amaury Denoyelle3f474e62022-11-24 17:15:08 +01007115
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02007116 if (pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007117 qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED) {
7118 TRACE_PROTO("PTO timer must be armed after anti-amplication was reached",
7119 QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01007120 TRACE_DEVEL("needs to wakeup the timer task after the amplification limit was reached",
7121 QUIC_EV_CONN_LPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007122 /* Reset the anti-amplification bit. It will be set again
7123 * when sending the next packet if reached again.
7124 */
7125 qc->flags &= ~QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01007126 qc_set_timer(qc);
7127 if (qc->timer_task && tick_isset(qc->timer) && tick_is_lt(qc->timer, now_ms))
7128 task_wakeup(qc->timer_task, TASK_WOKEN_MSG);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007129 }
7130
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007131 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) {
7132 TRACE_PROTO("Connection error",
7133 QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
7134 goto out;
7135 }
7136
7137 pkt->raw_len = pkt->len;
7138 quic_rx_pkts_del(qc);
7139 b_cspace = b_contig_space(&qc->rx.buf);
7140 if (b_cspace < pkt->len) {
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007141 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_LPKT, qc, 0, 0, 0,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007142 "bspace=%llu pkt->len=%llu", (ull)b_cspace, (ull)pkt->len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007143 /* Do not consume buf if space not at the end. */
7144 if (b_tail(&qc->rx.buf) + b_cspace < b_wrap(&qc->rx.buf)) {
7145 TRACE_PROTO("Packet dropped",
7146 QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
Amaury Denoyelle98289692022-10-19 15:37:44 +02007147 HA_ATOMIC_INC(&qc->prx_counters->dropped_pkt_bufoverrun);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007148 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007149 }
7150
7151 /* Let us consume the remaining contiguous space. */
7152 if (b_cspace) {
7153 b_putchr(&qc->rx.buf, 0x00);
7154 b_cspace--;
7155 }
7156 b_add(&qc->rx.buf, b_cspace);
7157 if (b_contig_space(&qc->rx.buf) < pkt->len) {
7158 TRACE_PROTO("Too big packet",
7159 QUIC_EV_CONN_LPKT, qc, pkt, &pkt->len, qv);
Amaury Denoyelle98289692022-10-19 15:37:44 +02007160 HA_ATOMIC_INC(&qc->prx_counters->dropped_pkt_bufoverrun);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007161 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007162 }
7163 }
7164
Amaury Denoyelle845169d2022-10-17 18:05:26 +02007165 if (!qc_try_rm_hp(qc, pkt, beg, &qel)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007166 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
7167 goto drop;
7168 }
7169
7170 TRACE_DATA("New packet", QUIC_EV_CONN_LPKT, qc, pkt, NULL, qv);
7171 if (pkt->aad_len)
7172 qc_pkt_insert(qc, pkt, qel);
7173 out:
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02007174 *tasklist_head = tasklet_wakeup_after(*tasklist_head,
7175 qc->wait_event.tasklet);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007176
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007177 drop_silent:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007178 TRACE_PROTO("RX pkt", QUIC_EV_CONN_LPKT, qc ? qc : NULL, pkt, NULL, qv);
7179 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc ? qc : NULL);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007180 return;
7181
7182 drop:
Amaury Denoyelle98289692022-10-19 15:37:44 +02007183 HA_ATOMIC_INC(&qc->prx_counters->dropped_pkt);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007184 TRACE_PROTO("packet drop", QUIC_EV_CONN_LPKT, qc ? qc : NULL, pkt, NULL, qv);
7185 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc ? qc : NULL);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007186}
7187
7188/* This function builds into <buf> buffer a QUIC long packet header.
7189 * Return 1 if enough room to build this header, 0 if not.
7190 */
7191static int quic_build_packet_long_header(unsigned char **buf, const unsigned char *end,
7192 int type, size_t pn_len,
7193 struct quic_conn *qc, const struct quic_version *ver)
7194{
7195 int ret = 0;
7196
7197 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
7198
7199 if (end - *buf < sizeof ver->num + qc->dcid.len + qc->scid.len + 3) {
7200 TRACE_DEVEL("not enough room", QUIC_EV_CONN_LPKT, qc);
7201 goto leave;
7202 }
7203
7204 type = quic_pkt_type(type, ver->num);
7205 /* #0 byte flags */
7206 *(*buf)++ = QUIC_PACKET_FIXED_BIT | QUIC_PACKET_LONG_HEADER_BIT |
7207 (type << QUIC_PACKET_TYPE_SHIFT) | (pn_len - 1);
7208 /* Version */
7209 quic_write_uint32(buf, end, ver->num);
7210 *(*buf)++ = qc->dcid.len;
7211 /* Destination connection ID */
7212 if (qc->dcid.len) {
7213 memcpy(*buf, qc->dcid.data, qc->dcid.len);
7214 *buf += qc->dcid.len;
7215 }
7216 /* Source connection ID */
7217 *(*buf)++ = qc->scid.len;
7218 if (qc->scid.len) {
7219 memcpy(*buf, qc->scid.data, qc->scid.len);
7220 *buf += qc->scid.len;
7221 }
7222
7223 ret = 1;
7224 leave:
7225 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
7226 return ret;
7227}
7228
7229/* This function builds into <buf> buffer a QUIC short packet header.
7230 * Return 1 if enough room to build this header, 0 if not.
7231 */
7232static int quic_build_packet_short_header(unsigned char **buf, const unsigned char *end,
7233 size_t pn_len, struct quic_conn *qc,
7234 unsigned char tls_flags)
7235{
7236 int ret = 0;
Frédéric Lécailleece86e62023-03-07 11:53:43 +01007237 unsigned char spin_bit =
7238 (qc->flags & QUIC_FL_CONN_SPIN_BIT) ? QUIC_PACKET_SPIN_BIT : 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007239
7240 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7241
7242 if (end - *buf < 1 + qc->dcid.len) {
7243 TRACE_DEVEL("not enough room", QUIC_EV_CONN_LPKT, qc);
7244 goto leave;
7245 }
7246
7247 /* #0 byte flags */
Frédéric Lécailleece86e62023-03-07 11:53:43 +01007248 *(*buf)++ = QUIC_PACKET_FIXED_BIT | spin_bit |
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007249 ((tls_flags & QUIC_FL_TLS_KP_BIT_SET) ? QUIC_PACKET_KEY_PHASE_BIT : 0) | (pn_len - 1);
7250 /* Destination connection ID */
7251 if (qc->dcid.len) {
7252 memcpy(*buf, qc->dcid.data, qc->dcid.len);
7253 *buf += qc->dcid.len;
7254 }
7255
7256 ret = 1;
7257 leave:
7258 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
7259 return ret;
7260}
7261
7262/* Apply QUIC header protection to the packet with <buf> as first byte address,
7263 * <pn> as address of the Packet number field, <pnlen> being this field length
7264 * with <aead> as AEAD cipher and <key> as secret key.
7265 * Returns 1 if succeeded or 0 if failed.
7266 */
7267static int quic_apply_header_protection(struct quic_conn *qc, unsigned char *buf,
7268 unsigned char *pn, size_t pnlen,
7269 struct quic_tls_ctx *tls_ctx)
7270
7271{
7272 int i, ret = 0;
7273 /* We need an IV of at least 5 bytes: one byte for bytes #0
7274 * and at most 4 bytes for the packet number
7275 */
7276 unsigned char mask[5] = {0};
7277 EVP_CIPHER_CTX *aes_ctx = tls_ctx->tx.hp_ctx;
7278
7279 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7280
7281 if (!quic_tls_aes_encrypt(mask, pn + QUIC_PACKET_PN_MAXLEN, sizeof mask, aes_ctx)) {
7282 TRACE_ERROR("could not apply header protection", QUIC_EV_CONN_TXPKT, qc);
7283 goto out;
7284 }
7285
7286 *buf ^= mask[0] & (*buf & QUIC_PACKET_LONG_HEADER_BIT ? 0xf : 0x1f);
7287 for (i = 0; i < pnlen; i++)
7288 pn[i] ^= mask[i + 1];
7289
7290 ret = 1;
7291 out:
7292 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
7293 return ret;
7294}
7295
7296/* Reduce the encoded size of <ack_frm> ACK frame removing the last
7297 * ACK ranges if needed to a value below <limit> in bytes.
7298 * Return 1 if succeeded, 0 if not.
7299 */
7300static int quic_ack_frm_reduce_sz(struct quic_conn *qc,
7301 struct quic_frame *ack_frm, size_t limit)
7302{
7303 size_t room, ack_delay_sz;
7304 int ret = 0;
7305
7306 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7307
7308 ack_delay_sz = quic_int_getsize(ack_frm->tx_ack.ack_delay);
Frédéric Lécaille9d68c6a2023-04-12 20:49:29 +02007309 if (limit <= ack_delay_sz - 1)
7310 goto leave;
7311
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007312 /* A frame is made of 1 byte for the frame type. */
7313 room = limit - ack_delay_sz - 1;
7314 if (!quic_rm_last_ack_ranges(qc, ack_frm->tx_ack.arngs, room))
7315 goto leave;
7316
7317 ret = 1 + ack_delay_sz + ack_frm->tx_ack.arngs->enc_sz;
7318 leave:
7319 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
7320 return ret;
7321}
7322
7323/* Prepare into <outlist> as most as possible ack-eliciting frame from their
7324 * <inlist> prebuilt frames for <qel> encryption level to be encoded in a buffer
7325 * with <room> as available room, and <*len> the packet Length field initialized
7326 * with the number of bytes already present in this buffer which must be taken
7327 * into an account for the Length packet field value. <headlen> is the number of
7328 * bytes already present in this packet before building frames.
7329 *
7330 * Update consequently <*len> to reflect the size of these frames built
7331 * by this function. Also attach these frames to <l> frame list.
7332 * Return 1 if at least one ack-eleciting frame could be built, 0 if not.
7333 */
7334static inline int qc_build_frms(struct list *outlist, struct list *inlist,
7335 size_t room, size_t *len, size_t headlen,
7336 struct quic_enc_level *qel,
7337 struct quic_conn *qc)
7338{
7339 int ret;
7340 struct quic_frame *cf, *cfbak;
7341
7342 TRACE_ENTER(QUIC_EV_CONN_BCFRMS, qc);
7343
7344 ret = 0;
7345 if (*len > room)
7346 goto leave;
7347
7348 /* If we are not probing we must take into an account the congestion
7349 * control window.
7350 */
7351 if (!qel->pktns->tx.pto_probe) {
7352 size_t remain = quic_path_prep_data(qc->path);
7353
7354 if (headlen > remain)
7355 goto leave;
7356
7357 room = QUIC_MIN(room, remain - headlen);
7358 }
7359
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007360 TRACE_PROTO("TX frms build (headlen)",
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007361 QUIC_EV_CONN_BCFRMS, qc, &headlen);
7362
7363 /* NOTE: switch/case block inside a loop, a successful status must be
7364 * returned by this function only if at least one frame could be built
7365 * in the switch/case block.
7366 */
7367 list_for_each_entry_safe(cf, cfbak, inlist, list) {
7368 /* header length, data length, frame length. */
7369 size_t hlen, dlen, dlen_sz, avail_room, flen;
7370
7371 if (!room)
7372 break;
7373
7374 switch (cf->type) {
7375 case QUIC_FT_CRYPTO:
7376 TRACE_DEVEL(" New CRYPTO frame build (room, len)",
7377 QUIC_EV_CONN_BCFRMS, qc, &room, len);
7378 /* Compute the length of this CRYPTO frame header */
7379 hlen = 1 + quic_int_getsize(cf->crypto.offset);
7380 /* Compute the data length of this CRyPTO frame. */
7381 dlen = max_stream_data_size(room, *len + hlen, cf->crypto.len);
7382 TRACE_DEVEL(" CRYPTO data length (hlen, crypto.len, dlen)",
7383 QUIC_EV_CONN_BCFRMS, qc, &hlen, &cf->crypto.len, &dlen);
7384 if (!dlen)
7385 continue;
7386
7387 /* CRYPTO frame length. */
7388 flen = hlen + quic_int_getsize(dlen) + dlen;
7389 TRACE_DEVEL(" CRYPTO frame length (flen)",
7390 QUIC_EV_CONN_BCFRMS, qc, &flen);
7391 /* Add the CRYPTO data length and its encoded length to the packet
7392 * length and the length of this length.
7393 */
7394 *len += flen;
7395 room -= flen;
7396 if (dlen == cf->crypto.len) {
7397 /* <cf> CRYPTO data have been consumed. */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007398 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007399 LIST_APPEND(outlist, &cf->list);
7400 }
7401 else {
7402 struct quic_frame *new_cf;
7403
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01007404 new_cf = qc_frm_alloc(QUIC_FT_CRYPTO);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007405 if (!new_cf) {
7406 TRACE_ERROR("No memory for new crypto frame", QUIC_EV_CONN_BCFRMS, qc);
7407 continue;
7408 }
7409
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007410 new_cf->crypto.len = dlen;
7411 new_cf->crypto.offset = cf->crypto.offset;
7412 new_cf->crypto.qel = qel;
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05007413 TRACE_DEVEL("split frame", QUIC_EV_CONN_PRSAFRM, qc, new_cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007414 if (cf->origin) {
7415 TRACE_DEVEL("duplicated frame", QUIC_EV_CONN_PRSAFRM, qc);
7416 /* This <cf> frame was duplicated */
7417 LIST_APPEND(&cf->origin->reflist, &new_cf->ref);
7418 new_cf->origin = cf->origin;
Frédéric Lécailledd419462023-01-26 15:07:39 +01007419 /* Detach the remaining CRYPTO frame from its original frame */
7420 LIST_DEL_INIT(&cf->ref);
7421 cf->origin = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007422 }
7423 LIST_APPEND(outlist, &new_cf->list);
7424 /* Consume <dlen> bytes of the current frame. */
7425 cf->crypto.len -= dlen;
7426 cf->crypto.offset += dlen;
7427 }
7428 break;
7429
7430 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
Amaury Denoyellec8a0efb2023-02-22 10:44:27 +01007431 if (cf->stream.dup) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007432 struct eb64_node *node = NULL;
7433 struct qc_stream_desc *stream_desc = NULL;
7434 struct quic_stream *strm = &cf->stream;
7435
7436 /* As this frame has been already lost, ensure the stream is always
7437 * available or the range of this frame is not consumed before
7438 * resending it.
7439 */
7440 node = eb64_lookup(&qc->streams_by_id, strm->id);
7441 if (!node) {
7442 TRACE_DEVEL("released stream", QUIC_EV_CONN_PRSAFRM, qc, cf);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007443 qc_frm_free(&cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007444 continue;
7445 }
7446
7447 stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
7448 if (strm->offset.key + strm->len <= stream_desc->ack_offset) {
7449 TRACE_DEVEL("ignored frame frame in already acked range",
7450 QUIC_EV_CONN_PRSAFRM, qc, cf);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007451 qc_frm_free(&cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007452 continue;
7453 }
7454 else if (strm->offset.key < stream_desc->ack_offset) {
Frédéric Lécailleca079792023-03-17 08:56:50 +01007455 uint64_t diff = stream_desc->ack_offset - strm->offset.key;
7456
Frédéric Lécaillec425e032023-03-20 14:32:59 +01007457 qc_stream_frm_mv_fwd(cf, diff);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007458 TRACE_DEVEL("updated partially acked frame",
7459 QUIC_EV_CONN_PRSAFRM, qc, cf);
7460 }
7461 }
7462 /* Note that these frames are accepted in short packets only without
7463 * "Length" packet field. Here, <*len> is used only to compute the
7464 * sum of the lengths of the already built frames for this packet.
7465 *
7466 * Compute the length of this STREAM frame "header" made a all the field
7467 * excepting the variable ones. Note that +1 is for the type of this frame.
7468 */
7469 hlen = 1 + quic_int_getsize(cf->stream.id) +
7470 ((cf->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) ? quic_int_getsize(cf->stream.offset.key) : 0);
7471 /* Compute the data length of this STREAM frame. */
7472 avail_room = room - hlen - *len;
7473 if ((ssize_t)avail_room <= 0)
7474 continue;
7475
7476 TRACE_DEVEL(" New STREAM frame build (room, len)",
7477 QUIC_EV_CONN_BCFRMS, qc, &room, len);
Amaury Denoyellef2f08f82023-02-03 18:39:06 +01007478
7479 /* hlen contains STREAM id and offset. Ensure there is
7480 * enough room for length field.
7481 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007482 if (cf->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) {
Amaury Denoyellef2f08f82023-02-03 18:39:06 +01007483 dlen = QUIC_MIN((uint64_t)max_available_room(avail_room, &dlen_sz),
7484 cf->stream.len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007485 dlen_sz = quic_int_getsize(dlen);
7486 flen = hlen + dlen_sz + dlen;
7487 }
7488 else {
7489 dlen = QUIC_MIN((uint64_t)avail_room, cf->stream.len);
7490 flen = hlen + dlen;
7491 }
Amaury Denoyellef2f08f82023-02-03 18:39:06 +01007492
7493 if (cf->stream.len && !dlen) {
7494 /* Only a small gap is left on buffer, not
7495 * enough to encode the STREAM data length.
7496 */
7497 continue;
7498 }
7499
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007500 TRACE_DEVEL(" STREAM data length (hlen, stream.len, dlen)",
7501 QUIC_EV_CONN_BCFRMS, qc, &hlen, &cf->stream.len, &dlen);
7502 TRACE_DEVEL(" STREAM frame length (flen)",
7503 QUIC_EV_CONN_BCFRMS, qc, &flen);
7504 /* Add the STREAM data length and its encoded length to the packet
7505 * length and the length of this length.
7506 */
7507 *len += flen;
7508 room -= flen;
7509 if (dlen == cf->stream.len) {
7510 /* <cf> STREAM data have been consumed. */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007511 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007512 LIST_APPEND(outlist, &cf->list);
7513
7514 /* Do not notify MUX on retransmission. */
7515 if (qc->flags & QUIC_FL_CONN_TX_MUX_CONTEXT) {
7516 qcc_streams_sent_done(cf->stream.stream->ctx,
7517 cf->stream.len,
7518 cf->stream.offset.key);
7519 }
7520 }
7521 else {
7522 struct quic_frame *new_cf;
7523 struct buffer cf_buf;
7524
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01007525 new_cf = qc_frm_alloc(cf->type);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007526 if (!new_cf) {
7527 TRACE_ERROR("No memory for new STREAM frame", QUIC_EV_CONN_BCFRMS, qc);
7528 continue;
7529 }
7530
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007531 new_cf->stream.stream = cf->stream.stream;
7532 new_cf->stream.buf = cf->stream.buf;
7533 new_cf->stream.id = cf->stream.id;
Amaury Denoyelle1dac0182023-02-02 16:45:07 +01007534 new_cf->stream.offset = cf->stream.offset;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007535 new_cf->stream.len = dlen;
7536 new_cf->type |= QUIC_STREAM_FRAME_TYPE_LEN_BIT;
7537 /* FIN bit reset */
7538 new_cf->type &= ~QUIC_STREAM_FRAME_TYPE_FIN_BIT;
7539 new_cf->stream.data = cf->stream.data;
Amaury Denoyellec8a0efb2023-02-22 10:44:27 +01007540 new_cf->stream.dup = cf->stream.dup;
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05007541 TRACE_DEVEL("split frame", QUIC_EV_CONN_PRSAFRM, qc, new_cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007542 if (cf->origin) {
7543 TRACE_DEVEL("duplicated frame", QUIC_EV_CONN_PRSAFRM, qc);
7544 /* This <cf> frame was duplicated */
7545 LIST_APPEND(&cf->origin->reflist, &new_cf->ref);
7546 new_cf->origin = cf->origin;
Frédéric Lécailledd419462023-01-26 15:07:39 +01007547 /* Detach this STREAM frame from its origin */
7548 LIST_DEL_INIT(&cf->ref);
7549 cf->origin = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007550 }
7551 LIST_APPEND(outlist, &new_cf->list);
7552 cf->type |= QUIC_STREAM_FRAME_TYPE_OFF_BIT;
7553 /* Consume <dlen> bytes of the current frame. */
7554 cf_buf = b_make(b_orig(cf->stream.buf),
7555 b_size(cf->stream.buf),
7556 (char *)cf->stream.data - b_orig(cf->stream.buf), 0);
7557 cf->stream.len -= dlen;
7558 cf->stream.offset.key += dlen;
7559 cf->stream.data = (unsigned char *)b_peek(&cf_buf, dlen);
7560
7561 /* Do not notify MUX on retransmission. */
7562 if (qc->flags & QUIC_FL_CONN_TX_MUX_CONTEXT) {
7563 qcc_streams_sent_done(new_cf->stream.stream->ctx,
7564 new_cf->stream.len,
7565 new_cf->stream.offset.key);
7566 }
7567 }
7568
7569 /* TODO the MUX is notified about the frame sending via
7570 * previous qcc_streams_sent_done call. However, the
7571 * sending can fail later, for example if the sendto
7572 * system call returns an error. As the MUX has been
7573 * notified, the transport layer is responsible to
7574 * bufferize and resent the announced data later.
7575 */
7576
7577 break;
7578
7579 default:
7580 flen = qc_frm_len(cf);
7581 BUG_ON(!flen);
7582 if (flen > room)
7583 continue;
7584
7585 *len += flen;
7586 room -= flen;
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007587 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007588 LIST_APPEND(outlist, &cf->list);
7589 break;
7590 }
7591
7592 /* Successful status as soon as a frame could be built */
7593 ret = 1;
7594 }
7595
7596 leave:
7597 TRACE_LEAVE(QUIC_EV_CONN_BCFRMS, qc);
7598 return ret;
7599}
7600
7601/* Generate a CONNECTION_CLOSE frame for <qc> on <qel> encryption level. <out>
7602 * is used as return parameter and should be zero'ed by the caller.
7603 */
7604static void qc_build_cc_frm(struct quic_conn *qc, struct quic_enc_level *qel,
7605 struct quic_frame *out)
7606{
7607 /* TODO improve CONNECTION_CLOSE on Initial/Handshake encryption levels
7608 *
7609 * A CONNECTION_CLOSE frame should be sent in several packets with
7610 * different encryption levels depending on the client context. This is
7611 * to ensure that the client can decrypt it. See RFC 9000 10.2.3 for
7612 * more details on how to implement it.
7613 */
7614 TRACE_ENTER(QUIC_EV_CONN_BFRM, qc);
7615
7616
7617 if (qc->err.app) {
7618 if (unlikely(qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] ||
7619 qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE])) {
7620 /* RFC 9000 10.2.3. Immediate Close during the Handshake
7621 *
7622 * Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake
7623 * packet could expose application state or be used to alter application
7624 * state. A CONNECTION_CLOSE of type 0x1d MUST be replaced by a
7625 * CONNECTION_CLOSE of type 0x1c when sending the frame in Initial or
7626 * Handshake packets. Otherwise, information about the application
7627 * state might be revealed. Endpoints MUST clear the value of the
7628 * Reason Phrase field and SHOULD use the APPLICATION_ERROR code when
7629 * converting to a CONNECTION_CLOSE of type 0x1c.
7630 */
7631 out->type = QUIC_FT_CONNECTION_CLOSE;
7632 out->connection_close.error_code = QC_ERR_APPLICATION_ERROR;
7633 out->connection_close.reason_phrase_len = 0;
7634 }
7635 else {
7636 out->type = QUIC_FT_CONNECTION_CLOSE_APP;
7637 out->connection_close.error_code = qc->err.code;
7638 }
7639 }
7640 else {
7641 out->type = QUIC_FT_CONNECTION_CLOSE;
7642 out->connection_close.error_code = qc->err.code;
7643 }
7644 TRACE_LEAVE(QUIC_EV_CONN_BFRM, qc);
7645
7646}
7647
7648/* This function builds a clear packet from <pkt> information (its type)
7649 * into a buffer with <pos> as position pointer and <qel> as QUIC TLS encryption
7650 * level for <conn> QUIC connection and <qel> as QUIC TLS encryption level,
7651 * filling the buffer with as much frames as possible from <frms> list of
7652 * prebuilt frames.
7653 * The trailing QUIC_TLS_TAG_LEN bytes of this packet are not built. But they are
7654 * reserved so that to ensure there is enough room to build this AEAD TAG after
7655 * having returned from this function.
7656 * This function also updates the value of <buf_pn> pointer to point to the packet
7657 * number field in this packet. <pn_len> will also have the packet number
7658 * length as value.
7659 *
7660 * Return 1 if succeeded (enough room to buile this packet), O if not.
7661 */
7662static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end,
7663 size_t dglen, struct quic_tx_packet *pkt,
7664 int64_t pn, size_t *pn_len, unsigned char **buf_pn,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007665 int must_ack, int padding, int cc, int probe,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007666 struct quic_enc_level *qel, struct quic_conn *qc,
7667 const struct quic_version *ver, struct list *frms)
7668{
7669 unsigned char *beg, *payload;
7670 size_t len, len_sz, len_frms, padding_len;
7671 struct quic_frame frm = { .type = QUIC_FT_CRYPTO, };
7672 struct quic_frame ack_frm = { .type = QUIC_FT_ACK, };
7673 struct quic_frame cc_frm = { };
7674 size_t ack_frm_len, head_len;
7675 int64_t rx_largest_acked_pn;
7676 int add_ping_frm;
7677 struct list frm_list = LIST_HEAD_INIT(frm_list);
7678 struct quic_frame *cf;
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007679 int ret = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007680
7681 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7682
7683 /* Length field value with CRYPTO frames if present. */
7684 len_frms = 0;
7685 beg = pos;
7686 /* When not probing, and no immediate close is required, reduce the size of this
7687 * buffer to respect the congestion controller window.
7688 * This size will be limited if we have ack-eliciting frames to send from <frms>.
7689 */
7690 if (!probe && !LIST_ISEMPTY(frms) && !cc) {
7691 size_t path_room;
7692
7693 path_room = quic_path_prep_data(qc->path);
7694 if (end - beg > path_room)
7695 end = beg + path_room;
7696 }
7697
7698 /* Ensure there is enough room for the TLS encryption tag and a zero token
7699 * length field if any.
7700 */
7701 if (end - pos < QUIC_TLS_TAG_LEN +
7702 (pkt->type == QUIC_PACKET_TYPE_INITIAL ? 1 : 0))
7703 goto no_room;
7704
7705 end -= QUIC_TLS_TAG_LEN;
7706 rx_largest_acked_pn = qel->pktns->rx.largest_acked_pn;
7707 /* packet number length */
7708 *pn_len = quic_packet_number_length(pn, rx_largest_acked_pn);
7709 /* Build the header */
7710 if ((pkt->type == QUIC_PACKET_TYPE_SHORT &&
7711 !quic_build_packet_short_header(&pos, end, *pn_len, qc, qel->tls_ctx.flags)) ||
7712 (pkt->type != QUIC_PACKET_TYPE_SHORT &&
7713 !quic_build_packet_long_header(&pos, end, pkt->type, *pn_len, qc, ver)))
7714 goto no_room;
7715
7716 /* Encode the token length (0) for an Initial packet. */
7717 if (pkt->type == QUIC_PACKET_TYPE_INITIAL)
7718 *pos++ = 0;
7719 head_len = pos - beg;
7720 /* Build an ACK frame if required. */
7721 ack_frm_len = 0;
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007722 /* Do not ack and probe at the same time. */
7723 if ((must_ack || (qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED)) && !qel->pktns->tx.pto_probe) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007724 struct quic_arngs *arngs = &qel->pktns->rx.arngs;
7725 BUG_ON(eb_is_empty(&qel->pktns->rx.arngs.root));
7726 ack_frm.tx_ack.arngs = arngs;
7727 if (qel->pktns->flags & QUIC_FL_PKTNS_NEW_LARGEST_PN) {
7728 qel->pktns->tx.ack_delay =
7729 quic_compute_ack_delay_us(qel->pktns->rx.largest_time_received, qc);
7730 qel->pktns->flags &= ~QUIC_FL_PKTNS_NEW_LARGEST_PN;
7731 }
7732 ack_frm.tx_ack.ack_delay = qel->pktns->tx.ack_delay;
7733 /* XXX BE CAREFUL XXX : here we reserved at least one byte for the
7734 * smallest frame (PING) and <*pn_len> more for the packet number. Note
7735 * that from here, we do not know if we will have to send a PING frame.
7736 * This will be decided after having computed the ack-eliciting frames
7737 * to be added to this packet.
7738 */
Frédéric Lécaille9d68c6a2023-04-12 20:49:29 +02007739 if (end - pos <= 1 + *pn_len)
7740 goto no_room;
7741
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007742 ack_frm_len = quic_ack_frm_reduce_sz(qc, &ack_frm, end - 1 - *pn_len - pos);
7743 if (!ack_frm_len)
7744 goto no_room;
7745 }
7746
7747 /* Length field value without the ack-eliciting frames. */
7748 len = ack_frm_len + *pn_len;
7749 len_frms = 0;
7750 if (!cc && !LIST_ISEMPTY(frms)) {
7751 ssize_t room = end - pos;
7752
7753 TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, frms);
7754 /* Initialize the length of the frames built below to <len>.
7755 * If any frame could be successfully built by qc_build_frms(),
7756 * we will have len_frms > len.
7757 */
7758 len_frms = len;
7759 if (!qc_build_frms(&frm_list, frms,
7760 end - pos, &len_frms, pos - beg, qel, qc)) {
7761 TRACE_DEVEL("Not enough room", QUIC_EV_CONN_TXPKT,
7762 qc, NULL, NULL, &room);
7763 if (!ack_frm_len && !qel->pktns->tx.pto_probe)
7764 goto no_room;
7765 }
7766 }
7767
7768 /* Length (of the remaining data). Must not fail because, the buffer size
7769 * has been checked above. Note that we have reserved QUIC_TLS_TAG_LEN bytes
7770 * for the encryption tag. It must be taken into an account for the length
7771 * of this packet.
7772 */
7773 if (len_frms)
7774 len = len_frms + QUIC_TLS_TAG_LEN;
7775 else
7776 len += QUIC_TLS_TAG_LEN;
7777 /* CONNECTION_CLOSE frame */
7778 if (cc) {
7779 qc_build_cc_frm(qc, qel, &cc_frm);
7780 len += qc_frm_len(&cc_frm);
7781 }
7782 add_ping_frm = 0;
7783 padding_len = 0;
7784 len_sz = quic_int_getsize(len);
7785 /* Add this packet size to <dglen> */
7786 dglen += head_len + len_sz + len;
Frédéric Lécailleec937212023-03-03 17:34:41 +01007787 /* Note that <padding> is true only when building an Handshake packet
7788 * coalesced to an Initial packet.
7789 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007790 if (padding && dglen < QUIC_INITIAL_PACKET_MINLEN) {
7791 /* This is a maximum padding size */
7792 padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen;
7793 /* The length field value is of this packet is <len> + <padding_len>
7794 * the size of which may be greater than the initial computed size
7795 * <len_sz>. So, let's deduce the difference between these to packet
7796 * sizes from <padding_len>.
7797 */
7798 padding_len -= quic_int_getsize(len + padding_len) - len_sz;
7799 len += padding_len;
7800 }
Frédéric Lécaille5faf5772023-02-16 17:30:53 +01007801 else if (len_frms && len_frms < QUIC_PACKET_PN_MAXLEN) {
7802 len += padding_len = QUIC_PACKET_PN_MAXLEN - len_frms;
7803 }
7804 else if (LIST_ISEMPTY(&frm_list)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007805 if (qel->pktns->tx.pto_probe) {
7806 /* If we cannot send a frame, we send a PING frame. */
7807 add_ping_frm = 1;
7808 len += 1;
Frédéric Lécailleec937212023-03-03 17:34:41 +01007809 dglen += 1;
7810 /* Note that only we are in the case where this Initial packet
7811 * is not coalesced to an Handshake packet. We must directly
7812 * pad the datragram.
7813 */
Frédéric Lécaille9c317b12023-03-28 15:39:11 +02007814 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
7815 if (dglen < QUIC_INITIAL_PACKET_MINLEN) {
7816 padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen;
7817 padding_len -= quic_int_getsize(len + padding_len) - len_sz;
7818 len += padding_len;
7819 }
7820 }
7821 else {
7822 /* Note that +1 is for the PING frame */
7823 if (*pn_len + 1 < QUIC_PACKET_PN_MAXLEN)
7824 len += padding_len = QUIC_PACKET_PN_MAXLEN - *pn_len - 1;
Frédéric Lécailleec937212023-03-03 17:34:41 +01007825 }
7826 }
7827 else {
7828 /* If there is no frame at all to follow, add at least a PADDING frame. */
7829 if (!ack_frm_len && !cc)
7830 len += padding_len = QUIC_PACKET_PN_MAXLEN - *pn_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007831 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007832 }
7833
7834 if (pkt->type != QUIC_PACKET_TYPE_SHORT && !quic_enc_int(&pos, end, len))
7835 goto no_room;
7836
7837 /* Packet number field address. */
7838 *buf_pn = pos;
7839
7840 /* Packet number encoding. */
7841 if (!quic_packet_number_encode(&pos, end, pn, *pn_len))
7842 goto no_room;
7843
7844 /* payload building (ack-eliciting or not frames) */
7845 payload = pos;
7846 if (ack_frm_len) {
7847 if (!qc_build_frm(&pos, end, &ack_frm, pkt, qc))
7848 goto no_room;
7849
7850 pkt->largest_acked_pn = quic_pktns_get_largest_acked_pn(qel->pktns);
7851 pkt->flags |= QUIC_FL_TX_PACKET_ACK;
7852 }
7853
7854 /* Ack-eliciting frames */
7855 if (!LIST_ISEMPTY(&frm_list)) {
7856 struct quic_frame *tmp_cf;
7857 list_for_each_entry_safe(cf, tmp_cf, &frm_list, list) {
7858 if (!qc_build_frm(&pos, end, cf, pkt, qc)) {
7859 ssize_t room = end - pos;
7860 TRACE_DEVEL("Not enough room", QUIC_EV_CONN_TXPKT,
7861 qc, NULL, NULL, &room);
7862 /* Note that <cf> was added from <frms> to <frm_list> list by
7863 * qc_build_frms().
7864 */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007865 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007866 LIST_INSERT(frms, &cf->list);
7867 continue;
7868 }
7869
7870 quic_tx_packet_refinc(pkt);
7871 cf->pkt = pkt;
7872 }
7873 }
7874
7875 /* Build a PING frame if needed. */
7876 if (add_ping_frm) {
7877 frm.type = QUIC_FT_PING;
7878 if (!qc_build_frm(&pos, end, &frm, pkt, qc))
7879 goto no_room;
7880 }
7881
7882 /* Build a CONNECTION_CLOSE frame if needed. */
7883 if (cc) {
7884 if (!qc_build_frm(&pos, end, &cc_frm, pkt, qc))
7885 goto no_room;
7886
7887 pkt->flags |= QUIC_FL_TX_PACKET_CC;
7888 }
7889
7890 /* Build a PADDING frame if needed. */
7891 if (padding_len) {
7892 frm.type = QUIC_FT_PADDING;
7893 frm.padding.len = padding_len;
7894 if (!qc_build_frm(&pos, end, &frm, pkt, qc))
7895 goto no_room;
7896 }
7897
7898 if (pos == payload) {
7899 /* No payload was built because of congestion control */
7900 TRACE_DEVEL("limited by congestion control", QUIC_EV_CONN_TXPKT, qc);
7901 goto no_room;
7902 }
7903
7904 /* If this packet is ack-eliciting and we are probing let's
7905 * decrement the PTO probe counter.
7906 */
7907 if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING &&
7908 qel->pktns->tx.pto_probe)
7909 qel->pktns->tx.pto_probe--;
7910
7911 pkt->len = pos - beg;
7912 LIST_SPLICE(&pkt->frms, &frm_list);
7913
7914 ret = 1;
7915 TRACE_DEVEL("Packet ack-eliciting frames", QUIC_EV_CONN_TXPKT, qc, pkt);
7916 leave:
7917 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
7918 return ret;
7919
7920 no_room:
7921 /* Replace the pre-built frames which could not be add to this packet */
7922 LIST_SPLICE(frms, &frm_list);
7923 TRACE_DEVEL("Remaining ack-eliciting frames", QUIC_EV_CONN_FRMLIST, qc, frms);
7924 goto leave;
7925}
7926
7927static inline void quic_tx_packet_init(struct quic_tx_packet *pkt, int type)
7928{
7929 pkt->type = type;
7930 pkt->len = 0;
7931 pkt->in_flight_len = 0;
7932 pkt->pn_node.key = (uint64_t)-1;
7933 LIST_INIT(&pkt->frms);
7934 pkt->time_sent = TICK_ETERNITY;
7935 pkt->next = NULL;
Frédéric Lécaille814645f2022-11-18 18:15:28 +01007936 pkt->prev = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007937 pkt->largest_acked_pn = -1;
7938 pkt->flags = 0;
7939 pkt->refcnt = 0;
7940}
7941
7942/* Build a packet into <buf> packet buffer with <pkt_type> as packet
7943 * type for <qc> QUIC connection from <qel> encryption level from <frms> list
7944 * of prebuilt frames.
7945 *
7946 * Return -2 if the packet could not be allocated or encrypted for any reason,
7947 * -1 if there was not enough room to build a packet.
7948 * XXX NOTE XXX
7949 * If you provide provide qc_build_pkt() with a big enough buffer to build a packet as big as
7950 * possible (to fill an MTU), the unique reason why this function may fail is the congestion
7951 * control window limitation.
7952 */
7953static struct quic_tx_packet *qc_build_pkt(unsigned char **pos,
7954 const unsigned char *buf_end,
7955 struct quic_enc_level *qel,
7956 struct quic_tls_ctx *tls_ctx, struct list *frms,
7957 struct quic_conn *qc, const struct quic_version *ver,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007958 size_t dglen, int pkt_type, int must_ack,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007959 int padding, int probe, int cc, int *err)
7960{
7961 struct quic_tx_packet *ret_pkt = NULL;
7962 /* The pointer to the packet number field. */
7963 unsigned char *buf_pn;
7964 unsigned char *beg, *end, *payload;
7965 int64_t pn;
7966 size_t pn_len, payload_len, aad_len;
7967 struct quic_tx_packet *pkt;
7968
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007969 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7970 TRACE_PROTO("TX pkt build", QUIC_EV_CONN_TXPKT, qc, NULL, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007971 *err = 0;
7972 pkt = pool_alloc(pool_head_quic_tx_packet);
7973 if (!pkt) {
7974 TRACE_DEVEL("Not enough memory for a new packet", QUIC_EV_CONN_TXPKT, qc);
7975 *err = -2;
7976 goto err;
7977 }
7978
7979 quic_tx_packet_init(pkt, pkt_type);
7980 beg = *pos;
7981 pn_len = 0;
7982 buf_pn = NULL;
7983
7984 pn = qel->pktns->tx.next_pn + 1;
7985 if (!qc_do_build_pkt(*pos, buf_end, dglen, pkt, pn, &pn_len, &buf_pn,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007986 must_ack, padding, cc, probe, qel, qc, ver, frms)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007987 // trace already emitted by function above
7988 *err = -1;
7989 goto err;
7990 }
7991
7992 end = beg + pkt->len;
7993 payload = buf_pn + pn_len;
7994 payload_len = end - payload;
7995 aad_len = payload - beg;
7996
7997 if (!quic_packet_encrypt(payload, payload_len, beg, aad_len, pn, tls_ctx, qc)) {
7998 // trace already emitted by function above
7999 *err = -2;
8000 goto err;
8001 }
8002
8003 end += QUIC_TLS_TAG_LEN;
8004 pkt->len += QUIC_TLS_TAG_LEN;
8005 if (!quic_apply_header_protection(qc, beg, buf_pn, pn_len, tls_ctx)) {
8006 // trace already emitted by function above
8007 *err = -2;
8008 goto err;
8009 }
8010
8011 /* Consume a packet number */
8012 qel->pktns->tx.next_pn++;
8013 qc->tx.prep_bytes += pkt->len;
8014 if (qc->tx.prep_bytes >= 3 * qc->rx.bytes && !quic_peer_validated_addr(qc)) {
8015 qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
8016 TRACE_PROTO("anti-amplification limit reached", QUIC_EV_CONN_TXPKT, qc);
8017 }
8018 /* Now that a correct packet is built, let us consume <*pos> buffer. */
8019 *pos = end;
8020 /* Attach the built packet to its tree. */
8021 pkt->pn_node.key = pn;
8022 /* Set the packet in fligth length for in flight packet only. */
8023 if (pkt->flags & QUIC_FL_TX_PACKET_IN_FLIGHT) {
8024 pkt->in_flight_len = pkt->len;
8025 qc->path->prep_in_flight += pkt->len;
8026 }
Frédéric Lécailled7215712023-03-24 18:13:37 +01008027 /* Always reset this flag */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008028 qc->flags &= ~QUIC_FL_CONN_IMMEDIATE_CLOSE;
8029 if (pkt->flags & QUIC_FL_TX_PACKET_ACK) {
8030 qel->pktns->flags &= ~QUIC_FL_PKTNS_ACK_REQUIRED;
8031 qel->pktns->rx.nb_aepkts_since_last_ack = 0;
Frédéric Lécailled7215712023-03-24 18:13:37 +01008032 qc->flags &= ~QUIC_FL_CONN_ACK_TIMER_FIRED;
8033 if (tick_isset(qc->ack_expire)) {
8034 qc->ack_expire = TICK_ETERNITY;
8035 qc->idle_timer_task->expire = qc->idle_expire;
8036 task_queue(qc->idle_timer_task);
Frédéric Lécaille495968e2023-04-03 17:42:05 +02008037 TRACE_PROTO("ack timer cancelled", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01008038 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008039 }
8040
8041 pkt->pktns = qel->pktns;
8042
8043 ret_pkt = pkt;
8044 leave:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01008045 TRACE_PROTO("TX pkt built", QUIC_EV_CONN_TXPKT, qc, ret_pkt);
8046 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008047 return ret_pkt;
8048
8049 err:
8050 /* TODO: what about the frames which have been built
8051 * for this packet.
8052 */
8053 free_quic_tx_packet(qc, pkt);
8054 goto leave;
8055}
8056
8057
8058static void __quic_conn_init(void)
8059{
8060 ha_quic_meth = BIO_meth_new(0x666, "ha QUIC methods");
8061}
8062INITCALL0(STG_REGISTER, __quic_conn_init);
8063
8064static void __quic_conn_deinit(void)
8065{
8066 BIO_meth_free(ha_quic_meth);
8067}
8068REGISTER_POST_DEINIT(__quic_conn_deinit);
8069
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008070/* Handle a new <dgram> received. Parse each QUIC packets and copied their
8071 * content to a quic-conn instance. The datagram content can be released after
8072 * this function.
8073 *
8074 * If datagram has been received on a quic-conn owned FD, <from_qc> must be set
8075 * to the connection instance. <li> is the attached listener. The caller is
8076 * responsible to ensure that the first packet is destined to this connection
8077 * by comparing CIDs.
8078 *
8079 * If datagram has been received on a receiver FD, <from_qc> will be NULL. This
8080 * function will thus retrieve the connection from the CID tree or allocate a
8081 * new one if possible. <li> is the listener attached to the receiver.
8082 *
8083 * Returns 0 on success else non-zero. If an error happens, some packets from
8084 * the datagram may not have been parsed.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008085 */
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008086int quic_dgram_parse(struct quic_dgram *dgram, struct quic_conn *from_qc,
8087 struct listener *li)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008088{
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008089 struct quic_rx_packet *pkt;
8090 struct quic_conn *qc = NULL;
8091 unsigned char *pos, *end;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008092 struct list *tasklist_head = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008093
8094 TRACE_ENTER(QUIC_EV_CONN_LPKT);
8095
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008096 pos = dgram->buf;
8097 end = pos + dgram->len;
8098 do {
8099 /* TODO replace zalloc -> alloc. */
8100 pkt = pool_zalloc(pool_head_quic_rx_packet);
8101 if (!pkt) {
8102 TRACE_ERROR("RX packet allocation failed", QUIC_EV_CONN_LPKT);
8103 goto err;
8104 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008105
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008106 pkt->version = NULL;
8107 pkt->pn_offset = 0;
Amaury Denoyelle98289692022-10-19 15:37:44 +02008108
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008109 /* Set flag if pkt is the first one in dgram. */
8110 if (pos == dgram->buf)
8111 pkt->flags |= QUIC_FL_RX_PACKET_DGRAM_FIRST;
Amaury Denoyelle98289692022-10-19 15:37:44 +02008112
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008113 LIST_INIT(&pkt->qc_rx_pkt_list);
8114 pkt->time_received = now_ms;
8115 quic_rx_packet_refinc(pkt);
8116 if (quic_rx_pkt_parse(pkt, pos, end, dgram, li))
8117 goto next;
Amaury Denoyelle98289692022-10-19 15:37:44 +02008118
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008119 /* Search quic-conn instance for first packet of the datagram.
8120 * quic_rx_packet_parse() is responsible to discard packets
8121 * with different DCID as the first one in the same datagram.
8122 */
8123 if (!qc) {
8124 qc = from_qc ? from_qc : quic_rx_pkt_retrieve_conn(pkt, dgram, li);
8125 /* qc is NULL if receiving a non Initial packet for an
8126 * unknown connection.
8127 */
8128 if (!qc) {
Amaury Denoyelle98289692022-10-19 15:37:44 +02008129 /* Skip the entire datagram. */
8130 pkt->len = end - pos;
8131 goto next;
8132 }
8133
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008134 dgram->qc = qc;
8135 }
Amaury Denoyelle98289692022-10-19 15:37:44 +02008136
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008137 if (qc_rx_check_closing(qc, pkt)) {
8138 /* Skip the entire datagram. */
8139 pkt->len = end - pos;
8140 goto next;
8141 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008142
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01008143 /* Detect QUIC connection migration. */
Frédéric Lécaillef6769542023-01-12 10:36:26 +01008144 if (ipcmp(&qc->peer_addr, &dgram->saddr, 1)) {
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01008145 if (qc_handle_conn_migration(qc, &dgram->saddr, &dgram->daddr)) {
8146 /* Skip the entire datagram. */
8147 TRACE_ERROR("error during connection migration, datagram dropped", QUIC_EV_CONN_LPKT, qc);
8148 pkt->len = end - pos;
8149 goto next;
8150 }
8151 }
8152
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008153 qc_rx_pkt_handle(qc, pkt, dgram, pos, &tasklist_head);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008154
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008155 next:
8156 pos += pkt->len;
8157 quic_rx_packet_refdec(pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008158
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008159 /* Free rejected packets */
8160 if (!pkt->refcnt) {
8161 BUG_ON(LIST_INLIST(&pkt->qc_rx_pkt_list));
8162 pool_free(pool_head_quic_rx_packet, pkt);
8163 }
8164 } while (pos < end);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008165
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008166 /* Increasing the received bytes counter by the UDP datagram length
8167 * if this datagram could be associated to a connection.
8168 */
8169 if (dgram->qc)
8170 dgram->qc->rx.bytes += dgram->len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008171
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008172 /* This must never happen. */
8173 BUG_ON(pos > end);
8174 BUG_ON(pos < end || pos > dgram->buf + dgram->len);
8175 /* Mark this datagram as consumed */
8176 HA_ATOMIC_STORE(&dgram->buf, NULL);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008177
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008178 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
8179 return 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008180
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008181 err:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008182 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008183 return -1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008184}
8185
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008186/* Check if connection ID <dcid> of length <dcid_len> belongs to <qc> local
8187 * CIDs. This can be used to determine if a datagram is addressed to the right
8188 * connection instance.
8189 *
8190 * Returns a boolean value.
8191 */
8192int qc_check_dcid(struct quic_conn *qc, unsigned char *dcid, size_t dcid_len)
8193{
8194 struct ebmb_node *node;
8195 struct quic_connection_id *id;
8196
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008197 if ((qc->scid.len == dcid_len &&
8198 memcmp(qc->scid.data, dcid, dcid_len) == 0) ||
8199 (qc->odcid.len == dcid_len &&
Frédéric Lécaille07846cb2023-02-13 16:14:24 +01008200 memcmp(qc->odcid.data, dcid, dcid_len) == 0)) {
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008201 return 1;
8202 }
8203
8204 node = ebmb_lookup(&quic_dghdlrs[tid].cids, dcid, dcid_len);
8205 if (node) {
8206 id = ebmb_entry(node, struct quic_connection_id, node);
8207 if (qc == id->qc)
8208 return 1;
8209 }
8210
8211 return 0;
8212}
8213
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008214/* Retrieve the DCID from a QUIC datagram or packet with <buf> as first octet.
8215 * Returns 1 if succeeded, 0 if not.
8216 */
8217int quic_get_dgram_dcid(unsigned char *buf, const unsigned char *end,
8218 unsigned char **dcid, size_t *dcid_len)
8219{
8220 int ret = 0, long_header;
8221 size_t minlen, skip;
8222
8223 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
8224
8225 if (!(*buf & QUIC_PACKET_FIXED_BIT)) {
8226 TRACE_PROTO("fixed bit not set", QUIC_EV_CONN_RXPKT);
8227 goto err;
8228 }
8229
8230 long_header = *buf & QUIC_PACKET_LONG_HEADER_BIT;
8231 minlen = long_header ? QUIC_LONG_PACKET_MINLEN :
8232 QUIC_SHORT_PACKET_MINLEN + QUIC_HAP_CID_LEN + QUIC_TLS_TAG_LEN;
8233 skip = long_header ? QUIC_LONG_PACKET_DCID_OFF : QUIC_SHORT_PACKET_DCID_OFF;
8234 if (end - buf < minlen)
8235 goto err;
8236
8237 buf += skip;
8238 *dcid_len = long_header ? *buf++ : QUIC_HAP_CID_LEN;
8239 if (*dcid_len > QUIC_CID_MAXLEN || end - buf <= *dcid_len)
8240 goto err;
8241
8242 *dcid = buf;
8243
8244 ret = 1;
8245 leave:
8246 TRACE_LEAVE(QUIC_EV_CONN_RXPKT);
8247 return ret;
8248
8249 err:
8250 TRACE_PROTO("wrong datagram", QUIC_EV_CONN_RXPKT);
8251 goto leave;
8252}
8253
8254/* Notify the MUX layer if alive about an imminent close of <qc>. */
8255void qc_notify_close(struct quic_conn *qc)
8256{
8257 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
8258
8259 if (qc->flags & QUIC_FL_CONN_NOTIFY_CLOSE)
8260 goto leave;
8261
8262 qc->flags |= QUIC_FL_CONN_NOTIFY_CLOSE;
8263 /* wake up the MUX */
8264 if (qc->mux_state == QC_MUX_READY && qc->conn->mux->wake) {
8265 TRACE_STATE("connection closure notidfied to mux",
8266 QUIC_FL_CONN_NOTIFY_CLOSE, qc);
8267 qc->conn->mux->wake(qc->conn);
8268 }
8269 else
8270 TRACE_STATE("connection closure not notidfied to mux",
8271 QUIC_FL_CONN_NOTIFY_CLOSE, qc);
8272 leave:
8273 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
8274}
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008275
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01008276/* Wake-up upper layer for sending if all conditions are met :
8277 * - room in congestion window or probe packet to sent
8278 * - socket FD ready to sent or listener socket used
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01008279 *
8280 * Returns 1 if upper layer has been woken up else 0.
8281 */
8282int qc_notify_send(struct quic_conn *qc)
8283{
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01008284 const struct quic_pktns *pktns = &qc->pktns[QUIC_TLS_PKTNS_01RTT];
8285
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01008286 if (qc->subs && qc->subs->events & SUB_RETRY_SEND) {
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01008287 /* RFC 9002 7.5. Probe Timeout
8288 *
8289 * Probe packets MUST NOT be blocked by the congestion controller.
8290 */
8291 if ((quic_path_prep_data(qc->path) || pktns->tx.pto_probe) &&
Amaury Denoyellecaa16542023-02-28 15:11:26 +01008292 (!qc_test_fd(qc) || !fd_send_active(qc->fd))) {
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01008293 tasklet_wakeup(qc->subs->tasklet);
8294 qc->subs->events &= ~SUB_RETRY_SEND;
8295 if (!qc->subs->events)
8296 qc->subs = NULL;
8297
8298 return 1;
8299 }
8300 }
8301
8302 return 0;
8303}
8304
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008305
8306/* appctx context used by "show quic" command */
8307struct show_quic_ctx {
8308 unsigned int epoch;
8309 struct bref bref; /* back-reference to the quic-conn being dumped */
8310 unsigned int thr;
Amaury Denoyelle3f9758e2023-02-01 17:31:02 +01008311 int flags;
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008312};
8313
Amaury Denoyelle3f9758e2023-02-01 17:31:02 +01008314#define QC_CLI_FL_SHOW_ALL 0x1 /* show closing/draining connections */
8315
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008316static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx, void *private)
8317{
8318 struct show_quic_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
8319
8320 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
8321 return 1;
8322
8323 ctx->epoch = _HA_ATOMIC_FETCH_ADD(&qc_epoch, 1);
8324 ctx->thr = 0;
Amaury Denoyelle3f9758e2023-02-01 17:31:02 +01008325 ctx->flags = 0;
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008326
Amaury Denoyelle10a46de2023-02-09 18:18:45 +01008327 if (*args[2] && strcmp(args[2], "all") == 0)
8328 ctx->flags |= QC_CLI_FL_SHOW_ALL;
8329
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008330 LIST_INIT(&ctx->bref.users);
8331
8332 return 0;
8333}
8334
8335static int cli_io_handler_dump_quic(struct appctx *appctx)
8336{
8337 struct show_quic_ctx *ctx = appctx->svcctx;
8338 struct stconn *sc = appctx_sc(appctx);
8339 struct quic_conn *qc;
Frédéric Lécaillea3772e12023-03-21 13:42:43 +01008340 struct quic_pktns *pktns;
Amaury Denoyelle2eda63b2023-02-01 17:05:36 +01008341 struct eb64_node *node;
8342 struct qc_stream_desc *stream;
Amaury Denoyelleb89c0e22023-02-01 17:04:26 +01008343 char bufaddr[INET6_ADDRSTRLEN], bufport[6];
Amaury Denoyelle58d9d5d2023-02-01 11:54:43 +01008344 int expire;
8345 unsigned char cid_len;
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008346
8347 thread_isolate();
8348
8349 if (ctx->thr >= global.nbthread)
8350 goto done;
8351
Christopher Faulet87633c32023-04-03 18:32:50 +02008352 /* FIXME: Don't watch the other side !*/
Christopher Faulet7faac7c2023-04-04 10:05:27 +02008353 if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUTW)) {
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008354 /* If we're forced to shut down, we might have to remove our
8355 * reference to the last stream being dumped.
8356 */
8357 if (!LIST_ISEMPTY(&ctx->bref.users))
8358 LIST_DEL_INIT(&ctx->bref.users);
8359 goto done;
8360 }
8361
8362 chunk_reset(&trash);
8363
8364 if (!LIST_ISEMPTY(&ctx->bref.users)) {
8365 /* Remove show_quic_ctx from previous quic_conn instance. */
8366 LIST_DEL_INIT(&ctx->bref.users);
8367 }
8368 else if (!ctx->bref.ref) {
8369 /* First invocation. */
8370 ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
8371 }
8372
8373 while (1) {
8374 int done = 0;
Amaury Denoyelle2eda63b2023-02-01 17:05:36 +01008375 int i;
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008376
8377 if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns) {
Amaury Denoyelle2d376292023-03-08 09:42:31 +01008378 /* If closing connections requested through "all", move
8379 * to quic_conns_clo list after browsing quic_conns.
8380 * Else move directly to the next quic_conns thread.
8381 */
8382 if (ctx->flags & QC_CLI_FL_SHOW_ALL) {
8383 ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns_clo.n;
8384 continue;
8385 }
8386
8387 done = 1;
8388 }
8389 else if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns_clo) {
8390 /* Closing list entirely browsed, go to next quic_conns
8391 * thread.
8392 */
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008393 done = 1;
8394 }
8395 else {
Amaury Denoyelle2d376292023-03-08 09:42:31 +01008396 /* Retrieve next element of the current list. */
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008397 qc = LIST_ELEM(ctx->bref.ref, struct quic_conn *, el_th_ctx);
8398 if ((int)(qc->qc_epoch - ctx->epoch) > 0)
8399 done = 1;
8400 }
8401
8402 if (done) {
8403 ++ctx->thr;
8404 if (ctx->thr >= global.nbthread)
8405 break;
Amaury Denoyelle2d376292023-03-08 09:42:31 +01008406 /* Switch to next thread quic_conns list. */
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008407 ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
8408 continue;
8409 }
8410
Amaury Denoyelle58d9d5d2023-02-01 11:54:43 +01008411 /* CIDs */
8412 chunk_appendf(&trash, "* %p[%02u]: scid=", qc, qc->tid);
8413 for (cid_len = 0; cid_len < qc->scid.len; ++cid_len)
8414 chunk_appendf(&trash, "%02x", qc->scid.data[cid_len]);
8415 while (cid_len++ < 20)
8416 chunk_appendf(&trash, "..");
8417
8418 chunk_appendf(&trash, " dcid=");
8419 for (cid_len = 0; cid_len < qc->dcid.len; ++cid_len)
8420 chunk_appendf(&trash, "%02x", qc->dcid.data[cid_len]);
8421 while (cid_len++ < 20)
8422 chunk_appendf(&trash, "..");
8423
8424 chunk_appendf(&trash, "\n");
8425
Frédéric Lécaille5e3201e2023-03-07 15:18:02 +01008426 chunk_appendf(&trash, " loc. TPs:");
8427 quic_transport_params_dump(&trash, qc, &qc->rx.params);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01008428 chunk_appendf(&trash, "\n");
Frédéric Lécaille5e3201e2023-03-07 15:18:02 +01008429 chunk_appendf(&trash, " rem. TPs:");
8430 quic_transport_params_dump(&trash, qc, &qc->tx.params);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01008431 chunk_appendf(&trash, "\n");
Frédéric Lécaille5e3201e2023-03-07 15:18:02 +01008432
Amaury Denoyelle58d9d5d2023-02-01 11:54:43 +01008433 /* Connection state */
8434 if (qc->flags & QUIC_FL_CONN_CLOSING)
8435 chunk_appendf(&trash, " st=closing ");
8436 else if (qc->flags & QUIC_FL_CONN_DRAINING)
8437 chunk_appendf(&trash, " st=draining ");
8438 else if (qc->state < QUIC_HS_ST_CONFIRMED)
8439 chunk_appendf(&trash, " st=handshake ");
8440 else
8441 chunk_appendf(&trash, " st=opened ");
8442
8443 if (qc->mux_state == QC_MUX_NULL)
8444 chunk_appendf(&trash, "mux=null ");
8445 else if (qc->mux_state == QC_MUX_READY)
8446 chunk_appendf(&trash, "mux=ready ");
8447 else
8448 chunk_appendf(&trash, "mux=released ");
8449
Frédéric Lécaille92f4a7c2023-04-04 14:31:49 +02008450 expire = qc->idle_expire;
Amaury Denoyelle58d9d5d2023-02-01 11:54:43 +01008451 chunk_appendf(&trash, "expire=%02ds ",
Frédéric Lécaille92f4a7c2023-04-04 14:31:49 +02008452 TICKS_TO_MS(tick_remain(now_ms, expire)) / 1000);
Amaury Denoyelle58d9d5d2023-02-01 11:54:43 +01008453
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008454 chunk_appendf(&trash, "\n");
8455
Amaury Denoyelleb89c0e22023-02-01 17:04:26 +01008456 /* Socket */
8457 chunk_appendf(&trash, " fd=%d", qc->fd);
8458 if (qc->local_addr.ss_family == AF_INET ||
8459 qc->local_addr.ss_family == AF_INET6) {
8460 addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
8461 port_to_str(&qc->local_addr, bufport, sizeof(bufport));
8462 chunk_appendf(&trash, " from=%s:%s", bufaddr, bufport);
8463
8464 addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
8465 port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
8466 chunk_appendf(&trash, " to=%s:%s", bufaddr, bufport);
8467 }
8468
8469 chunk_appendf(&trash, "\n");
8470
Frédéric Lécaillea3772e12023-03-21 13:42:43 +01008471 /* Packet number spaces information */
8472 pktns = &qc->pktns[QUIC_TLS_PKTNS_INITIAL];
Amaury Denoyelle1b0fc432023-02-01 17:05:10 +01008473 chunk_appendf(&trash, " [initl] rx.ackrng=%-6zu tx.inflight=%-6zu",
Frédéric Lécaillea3772e12023-03-21 13:42:43 +01008474 pktns->rx.arngs.sz, pktns->tx.in_flight);
8475 pktns = &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE];
Amaury Denoyelle1b0fc432023-02-01 17:05:10 +01008476 chunk_appendf(&trash, " [hndshk] rx.ackrng=%-6zu tx.inflight=%-6zu\n",
Frédéric Lécaillea3772e12023-03-21 13:42:43 +01008477 pktns->rx.arngs.sz, pktns->tx.in_flight);
8478 pktns = &qc->pktns[QUIC_TLS_PKTNS_01RTT];
8479 chunk_appendf(&trash, " [01rtt] rx.ackrng=%-6zu tx.inflight=%-6zu\n",
8480 pktns->rx.arngs.sz, pktns->tx.in_flight);
Amaury Denoyelle1b0fc432023-02-01 17:05:10 +01008481
Frédéric Lécaillefad0e6c2023-04-06 10:19:17 +02008482 chunk_appendf(&trash, " srtt=%-4u rttvar=%-4u rttmin=%-4u ptoc=%-4u cwnd=%-6llu"
8483 " mcwnd=%-6llu lostpkts=%-6llu\n",
Frédéric Lécaillea3772e12023-03-21 13:42:43 +01008484 qc->path->loss.srtt >> 3, qc->path->loss.rtt_var >> 2,
Frédéric Lécaillefad0e6c2023-04-06 10:19:17 +02008485 qc->path->loss.rtt_min, qc->path->loss.pto_count, (ullong)qc->path->cwnd,
8486 (ullong)qc->path->mcwnd, (ullong)qc->path->loss.nb_lost_pkt);
Frédéric Lécaillea3772e12023-03-21 13:42:43 +01008487
Amaury Denoyelle1b0fc432023-02-01 17:05:10 +01008488
Amaury Denoyelle2eda63b2023-02-01 17:05:36 +01008489 /* Streams */
8490 node = eb64_first(&qc->streams_by_id);
8491 i = 0;
8492 while (node) {
8493 stream = eb64_entry(node, struct qc_stream_desc, by_id);
8494 node = eb64_next(node);
8495
Amaury Denoyellea9de25a2023-02-10 09:25:22 +01008496 chunk_appendf(&trash, " | stream=%-8llu", (unsigned long long)stream->by_id.key);
8497 chunk_appendf(&trash, " off=%-8llu ack=%-8llu",
8498 (unsigned long long)stream->buf_offset,
8499 (unsigned long long)stream->ack_offset);
Amaury Denoyelle2eda63b2023-02-01 17:05:36 +01008500
8501 if (!(++i % 3)) {
8502 chunk_appendf(&trash, "\n");
8503 i = 0;
8504 }
8505 }
8506
8507 chunk_appendf(&trash, "\n");
8508
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008509 if (applet_putchk(appctx, &trash) == -1) {
8510 /* Register show_quic_ctx to quic_conn instance. */
8511 LIST_APPEND(&qc->back_refs, &ctx->bref.users);
8512 goto full;
8513 }
8514
8515 ctx->bref.ref = qc->el_th_ctx.n;
8516 }
8517
8518 done:
8519 thread_release();
8520 return 1;
8521
8522 full:
8523 thread_release();
8524 return 0;
8525}
8526
8527static void cli_release_show_quic(struct appctx *appctx)
8528{
8529 struct show_quic_ctx *ctx = appctx->svcctx;
8530
8531 if (ctx->thr < global.nbthread) {
8532 thread_isolate();
8533 if (!LIST_ISEMPTY(&ctx->bref.users))
8534 LIST_DEL_INIT(&ctx->bref.users);
8535 thread_release();
8536 }
8537}
8538
8539static struct cli_kw_list cli_kws = {{ }, {
8540 { { "show", "quic", NULL }, "show quic : display quic connections status", cli_parse_show_quic, cli_io_handler_dump_quic, cli_release_show_quic },
Frédéric Lécaille91376d62023-02-11 20:24:42 +01008541 {{},}
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008542}};
8543
8544INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
8545
8546static void init_quic()
8547{
8548 int thr;
8549
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01008550 for (thr = 0; thr < MAX_THREADS; ++thr) {
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008551 LIST_INIT(&ha_thread_ctx[thr].quic_conns);
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01008552 LIST_INIT(&ha_thread_ctx[thr].quic_conns_clo);
8553 }
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008554}
8555INITCALL0(STG_INIT, init_quic);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008556
8557/*
8558 * Local variables:
8559 * c-indent-level: 8
8560 * c-basic-offset: 8
8561 * End:
8562 */