blob: a62beee33b25483f02c20fec04c552ab55c80791 [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;
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +0200122/* RFC 8999 5.4. Version
123 * A Version field with a
124 * value of 0x00000000 is reserved for version negotiation
125 */
126const struct quic_version quic_version_VN_reserved = { .num = 0, };
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200127
128/* trace source and events */
129static void quic_trace(enum trace_level level, uint64_t mask, \
130 const struct trace_source *src,
131 const struct ist where, const struct ist func,
132 const void *a1, const void *a2, const void *a3, const void *a4);
133
134static const struct trace_event quic_trace_events[] = {
135 { .mask = QUIC_EV_CONN_NEW, .name = "new_conn", .desc = "new QUIC connection" },
136 { .mask = QUIC_EV_CONN_INIT, .name = "new_conn_init", .desc = "new QUIC connection initialization" },
137 { .mask = QUIC_EV_CONN_ISEC, .name = "init_secs", .desc = "initial secrets derivation" },
138 { .mask = QUIC_EV_CONN_RSEC, .name = "read_secs", .desc = "read secrets derivation" },
139 { .mask = QUIC_EV_CONN_WSEC, .name = "write_secs", .desc = "write secrets derivation" },
140 { .mask = QUIC_EV_CONN_LPKT, .name = "lstnr_packet", .desc = "new listener received packet" },
141 { .mask = QUIC_EV_CONN_SPKT, .name = "srv_packet", .desc = "new server received packet" },
142 { .mask = QUIC_EV_CONN_ENCPKT, .name = "enc_hdshk_pkt", .desc = "handhshake packet encryption" },
143 { .mask = QUIC_EV_CONN_TXPKT, .name = "tx_pkt", .desc = "TX packet" },
144 { .mask = QUIC_EV_CONN_PAPKT, .name = "phdshk_apkt", .desc = "post handhshake application packet preparation" },
145 { .mask = QUIC_EV_CONN_PAPKTS, .name = "phdshk_apkts", .desc = "post handhshake application packets preparation" },
146 { .mask = QUIC_EV_CONN_IO_CB, .name = "qc_io_cb", .desc = "QUIC conn. I/O processing" },
147 { .mask = QUIC_EV_CONN_RMHP, .name = "rm_hp", .desc = "Remove header protection" },
148 { .mask = QUIC_EV_CONN_PRSHPKT, .name = "parse_hpkt", .desc = "parse handshake packet" },
149 { .mask = QUIC_EV_CONN_PRSAPKT, .name = "parse_apkt", .desc = "parse application packet" },
150 { .mask = QUIC_EV_CONN_PRSFRM, .name = "parse_frm", .desc = "parse frame" },
151 { .mask = QUIC_EV_CONN_PRSAFRM, .name = "parse_ack_frm", .desc = "parse ACK frame" },
152 { .mask = QUIC_EV_CONN_BFRM, .name = "build_frm", .desc = "build frame" },
153 { .mask = QUIC_EV_CONN_PHPKTS, .name = "phdshk_pkts", .desc = "handhshake packets preparation" },
154 { .mask = QUIC_EV_CONN_TRMHP, .name = "rm_hp_try", .desc = "header protection removing try" },
155 { .mask = QUIC_EV_CONN_ELRMHP, .name = "el_rm_hp", .desc = "handshake enc. level header protection removing" },
156 { .mask = QUIC_EV_CONN_RXPKT, .name = "rx_pkt", .desc = "RX packet" },
157 { .mask = QUIC_EV_CONN_SSLDATA, .name = "ssl_provide_data", .desc = "CRYPTO data provision to TLS stack" },
158 { .mask = QUIC_EV_CONN_RXCDATA, .name = "el_treat_rx_cfrms",.desc = "enc. level RX CRYPTO frames processing"},
159 { .mask = QUIC_EV_CONN_ADDDATA, .name = "add_hdshk_data", .desc = "TLS stack ->add_handshake_data() call"},
160 { .mask = QUIC_EV_CONN_FFLIGHT, .name = "flush_flight", .desc = "TLS stack ->flush_flight() call"},
161 { .mask = QUIC_EV_CONN_SSLALERT, .name = "send_alert", .desc = "TLS stack ->send_alert() call"},
162 { .mask = QUIC_EV_CONN_RTTUPDT, .name = "rtt_updt", .desc = "RTT sampling" },
163 { .mask = QUIC_EV_CONN_SPPKTS, .name = "sppkts", .desc = "send prepared packets" },
164 { .mask = QUIC_EV_CONN_PKTLOSS, .name = "pktloss", .desc = "detect packet loss" },
165 { .mask = QUIC_EV_CONN_STIMER, .name = "stimer", .desc = "set timer" },
166 { .mask = QUIC_EV_CONN_PTIMER, .name = "ptimer", .desc = "process timer" },
167 { .mask = QUIC_EV_CONN_SPTO, .name = "spto", .desc = "set PTO" },
168 { .mask = QUIC_EV_CONN_BCFRMS, .name = "bcfrms", .desc = "build CRYPTO data frames" },
169 { .mask = QUIC_EV_CONN_XPRTSEND, .name = "xprt_send", .desc = "sending XRPT subscription" },
170 { .mask = QUIC_EV_CONN_XPRTRECV, .name = "xprt_recv", .desc = "receiving XRPT subscription" },
171 { .mask = QUIC_EV_CONN_FREED, .name = "conn_freed", .desc = "releasing conn. memory" },
172 { .mask = QUIC_EV_CONN_CLOSE, .name = "conn_close", .desc = "closing conn." },
173 { .mask = QUIC_EV_CONN_ACKSTRM, .name = "ack_strm", .desc = "STREAM ack."},
174 { .mask = QUIC_EV_CONN_FRMLIST, .name = "frm_list", .desc = "frame list"},
175 { .mask = QUIC_EV_STATELESS_RST, .name = "stateless_reset", .desc = "stateless reset sent"},
176 { .mask = QUIC_EV_TRANSP_PARAMS, .name = "transport_params", .desc = "transport parameters"},
177 { .mask = QUIC_EV_CONN_IDLE_TIMER, .name = "idle_timer", .desc = "idle timer task"},
178 { .mask = QUIC_EV_CONN_SUB, .name = "xprt_sub", .desc = "RX/TX subcription or unsubscription to QUIC xprt"},
Amaury Denoyelle5b414862022-10-24 17:40:37 +0200179 { .mask = QUIC_EV_CONN_RCV, .name = "conn_recv", .desc = "RX on connection" },
Amaury Denoyelle25174d52023-04-05 17:52:05 +0200180 { .mask = QUIC_EV_CONN_SET_AFFINITY, .name = "conn_set_affinity", .desc = "set connection thread affinity" },
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200181 { /* end */ }
182};
183
184static const struct name_desc quic_trace_lockon_args[4] = {
185 /* arg1 */ { /* already used by the connection */ },
186 /* arg2 */ { .name="quic", .desc="QUIC transport" },
187 /* arg3 */ { },
188 /* arg4 */ { }
189};
190
191static const struct name_desc quic_trace_decoding[] = {
192#define QUIC_VERB_CLEAN 1
193 { .name="clean", .desc="only user-friendly stuff, generally suitable for level \"user\"" },
194 { /* end */ }
195};
196
197
198struct trace_source trace_quic = {
199 .name = IST("quic"),
200 .desc = "QUIC xprt",
201 .arg_def = TRC_ARG1_QCON, /* TRACE()'s first argument is always a quic_conn */
202 .default_cb = quic_trace,
203 .known_events = quic_trace_events,
204 .lockon_args = quic_trace_lockon_args,
205 .decoding = quic_trace_decoding,
206 .report_events = ~0, /* report everything by default */
207};
208
209#define TRACE_SOURCE &trace_quic
210INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
211
212static BIO_METHOD *ha_quic_meth;
213
214DECLARE_POOL(pool_head_quic_tx_ring, "quic_tx_ring", QUIC_TX_RING_BUFSZ);
215DECLARE_POOL(pool_head_quic_conn_rxbuf, "quic_conn_rxbuf", QUIC_CONN_RX_BUFSZ);
216DECLARE_STATIC_POOL(pool_head_quic_conn_ctx,
217 "quic_conn_ctx", sizeof(struct ssl_sock_ctx));
218DECLARE_STATIC_POOL(pool_head_quic_conn, "quic_conn", sizeof(struct quic_conn));
219DECLARE_POOL(pool_head_quic_connection_id,
Frédéric Lécaillea9461252023-04-24 18:20:44 +0200220 "quic_connection_id", sizeof(struct quic_connection_id));
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200221DECLARE_POOL(pool_head_quic_dgram, "quic_dgram", sizeof(struct quic_dgram));
222DECLARE_POOL(pool_head_quic_rx_packet, "quic_rx_packet", sizeof(struct quic_rx_packet));
223DECLARE_POOL(pool_head_quic_tx_packet, "quic_tx_packet", sizeof(struct quic_tx_packet));
224DECLARE_STATIC_POOL(pool_head_quic_rx_crypto_frm, "quic_rx_crypto_frm", sizeof(struct quic_rx_crypto_frm));
225DECLARE_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 +0200226DECLARE_STATIC_POOL(pool_head_quic_cstream, "quic_cstream", sizeof(struct quic_cstream));
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200227DECLARE_POOL(pool_head_quic_frame, "quic_frame", sizeof(struct quic_frame));
228DECLARE_STATIC_POOL(pool_head_quic_arng, "quic_arng", sizeof(struct quic_arng_node));
229
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +0100230static struct quic_connection_id *new_quic_cid(struct eb_root *root,
Amaury Denoyelle162baaf2023-04-03 18:49:39 +0200231 struct quic_conn *qc,
232 const struct quic_cid *odcid,
233 const struct sockaddr_storage *saddr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200234static struct quic_tx_packet *qc_build_pkt(unsigned char **pos, const unsigned char *buf_end,
235 struct quic_enc_level *qel, struct quic_tls_ctx *ctx,
236 struct list *frms, struct quic_conn *qc,
237 const struct quic_version *ver, size_t dglen, int pkt_type,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +0200238 int must_ack, int padding, int probe, int cc, int *err);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200239struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state);
Frédéric Lécailled7215712023-03-24 18:13:37 +0100240static void qc_idle_timer_do_rearm(struct quic_conn *qc, int arm_ack);
241static void qc_idle_timer_rearm(struct quic_conn *qc, int read, int arm_ack);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200242static int qc_conn_alloc_ssl_ctx(struct quic_conn *qc);
243static int quic_conn_init_timer(struct quic_conn *qc);
244static int quic_conn_init_idle_timer_task(struct quic_conn *qc);
245
246/* Only for debug purpose */
247struct enc_debug_info {
248 unsigned char *payload;
249 size_t payload_len;
250 unsigned char *aad;
251 size_t aad_len;
252 uint64_t pn;
253};
254
255/* Initializes a enc_debug_info struct (only for debug purpose) */
256static inline void enc_debug_info_init(struct enc_debug_info *edi,
257 unsigned char *payload, size_t payload_len,
258 unsigned char *aad, size_t aad_len, uint64_t pn)
259{
260 edi->payload = payload;
261 edi->payload_len = payload_len;
262 edi->aad = aad;
263 edi->aad_len = aad_len;
264 edi->pn = pn;
265}
266
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100267/* Used only for QUIC TLS key phase traces */
268struct quic_kp_trace {
269 const unsigned char *rx_sec;
270 size_t rx_seclen;
271 const struct quic_tls_kp *rx;
272 const unsigned char *tx_sec;
273 size_t tx_seclen;
274 const struct quic_tls_kp *tx;
275};
276
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200277/* Trace callback for QUIC.
278 * These traces always expect that arg1, if non-null, is of type connection.
279 */
280static void quic_trace(enum trace_level level, uint64_t mask, const struct trace_source *src,
281 const struct ist where, const struct ist func,
282 const void *a1, const void *a2, const void *a3, const void *a4)
283{
284 const struct quic_conn *qc = a1;
285
286 if (qc) {
287 const struct quic_tls_ctx *tls_ctx;
288
Frédéric Lécailleeb3e5172023-04-12 13:41:54 +0200289 chunk_appendf(&trace_buf, " : qc@%p flags=0x%x", qc, qc->flags);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200290 if (mask & QUIC_EV_CONN_INIT) {
291 chunk_appendf(&trace_buf, "\n odcid");
292 quic_cid_dump(&trace_buf, &qc->odcid);
293 chunk_appendf(&trace_buf, "\n dcid");
294 quic_cid_dump(&trace_buf, &qc->dcid);
295 chunk_appendf(&trace_buf, "\n scid");
296 quic_cid_dump(&trace_buf, &qc->scid);
297 }
298
299 if (mask & QUIC_EV_TRANSP_PARAMS) {
300 const struct quic_transport_params *p = a2;
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100301
302 if (p)
303 quic_transport_params_dump(&trace_buf, qc, p);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200304 }
305
306 if (mask & QUIC_EV_CONN_ADDDATA) {
307 const enum ssl_encryption_level_t *level = a2;
308 const size_t *len = a3;
309
310 if (level) {
311 enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
312
313 chunk_appendf(&trace_buf, " el=%c(%d)", quic_enc_level_char(lvl), lvl);
314 }
315 if (len)
316 chunk_appendf(&trace_buf, " len=%llu", (unsigned long long)*len);
317 }
318 if ((mask & QUIC_EV_CONN_ISEC) && qc) {
319 /* Initial read & write secrets. */
320 enum quic_tls_enc_level level = QUIC_TLS_ENC_LEVEL_INITIAL;
321 const unsigned char *rx_sec = a2;
322 const unsigned char *tx_sec = a3;
323
324 tls_ctx = &qc->els[level].tls_ctx;
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200325 chunk_appendf(&trace_buf, "\n RX el=%c", quic_enc_level_char(level));
326 if (rx_sec)
327 quic_tls_secret_hexdump(&trace_buf, rx_sec, 32);
328 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->rx);
329 chunk_appendf(&trace_buf, "\n TX el=%c", quic_enc_level_char(level));
330 if (tx_sec)
331 quic_tls_secret_hexdump(&trace_buf, tx_sec, 32);
332 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->tx);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200333 }
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100334
335 if ((mask & QUIC_EV_CONN_KP) && qc) {
336 /* Initial read & write secrets. */
337 const struct quic_kp_trace *kp = a2;
338
339 if (kp) {
340 if (kp->rx) {
341 chunk_appendf(&trace_buf, "\n RX kp");
342 if (kp->rx_sec)
343 quic_tls_secret_hexdump(&trace_buf, kp->rx_sec, kp->rx_seclen);
344 quic_tls_kp_keys_hexdump(&trace_buf, kp->rx);
345 }
346 if (kp->tx) {
347 chunk_appendf(&trace_buf, "\n TX kp");
348 if (kp->tx_sec)
349 quic_tls_secret_hexdump(&trace_buf, kp->tx_sec, kp->tx_seclen);
350 quic_tls_kp_keys_hexdump(&trace_buf, kp->tx);
351 }
352 }
353 }
354
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200355 if (mask & (QUIC_EV_CONN_RSEC|QUIC_EV_CONN_RWSEC)) {
356 const enum ssl_encryption_level_t *level = a2;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200357
358 if (level) {
359 enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
360
361 chunk_appendf(&trace_buf, "\n RX el=%c", quic_enc_level_char(lvl));
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200362 if (quic_tls_has_rx_sec(&qc->els[lvl])) {
363 tls_ctx = &qc->els[lvl].tls_ctx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200364 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->rx);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200365 }
366 else
367 chunk_appendf(&trace_buf, " (none)");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200368 }
369 }
370
371 if (mask & (QUIC_EV_CONN_WSEC|QUIC_EV_CONN_RWSEC)) {
372 const enum ssl_encryption_level_t *level = a2;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200373
374 if (level) {
375 enum quic_tls_enc_level lvl = ssl_to_quic_enc_level(*level);
376
377 chunk_appendf(&trace_buf, "\n TX el=%c", quic_enc_level_char(lvl));
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200378 if (quic_tls_has_tx_sec(&qc->els[lvl])) {
379 tls_ctx = &qc->els[lvl].tls_ctx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200380 quic_tls_keys_hexdump(&trace_buf, &tls_ctx->tx);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +0200381 }
382 else
383 chunk_appendf(&trace_buf, " (none)");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200384 }
385
386 }
387
388 if (mask & QUIC_EV_CONN_FRMLIST) {
389 const struct list *l = a2;
390
391 if (l) {
392 const struct quic_frame *frm;
393 list_for_each_entry(frm, l, list) {
394 chunk_appendf(&trace_buf, " frm@%p", frm);
395 chunk_frm_appendf(&trace_buf, frm);
396 }
397 }
398 }
399
400 if (mask & (QUIC_EV_CONN_TXPKT|QUIC_EV_CONN_PAPKT)) {
401 const struct quic_tx_packet *pkt = a2;
402 const struct quic_enc_level *qel = a3;
403 const ssize_t *room = a4;
404
405 if (qel) {
406 const struct quic_pktns *pktns = qel->pktns;
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200407 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 +0200408 "if=%llu pp=%u",
409 quic_enc_level_char_from_qel(qel, qc),
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200410 qel->pktns->flags,
Frédéric Lécaille45400532023-02-13 18:39:19 +0100411 qc->path->loss.pto_count,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200412 (unsigned long long)qc->path->cwnd,
413 (unsigned long long)qc->path->prep_in_flight,
414 (unsigned long long)qc->path->in_flight,
415 (unsigned long long)pktns->tx.in_flight,
416 pktns->tx.pto_probe);
417 }
418 if (pkt) {
419 const struct quic_frame *frm;
420 if (pkt->pn_node.key != (uint64_t)-1)
421 chunk_appendf(&trace_buf, " pn=%llu",(ull)pkt->pn_node.key);
422 list_for_each_entry(frm, &pkt->frms, list) {
423 chunk_appendf(&trace_buf, " frm@%p", frm);
424 chunk_frm_appendf(&trace_buf, frm);
425 }
426 }
427
428 if (room) {
429 chunk_appendf(&trace_buf, " room=%lld", (long long)*room);
430 chunk_appendf(&trace_buf, " dcid.len=%llu scid.len=%llu",
431 (unsigned long long)qc->dcid.len, (unsigned long long)qc->scid.len);
432 }
433 }
434
435 if (mask & QUIC_EV_CONN_IO_CB) {
436 const enum quic_handshake_state *state = a2;
437 const int *err = a3;
438
439 if (state)
440 chunk_appendf(&trace_buf, " state=%s", quic_hdshk_state_str(*state));
441 if (err)
442 chunk_appendf(&trace_buf, " err=%s", ssl_error_str(*err));
443 }
444
445 if (mask & (QUIC_EV_CONN_TRMHP|QUIC_EV_CONN_ELRMHP|QUIC_EV_CONN_SPKT)) {
446 const struct quic_rx_packet *pkt = a2;
447 const unsigned long *pktlen = a3;
448 const SSL *ssl = a4;
449
450 if (pkt) {
451 chunk_appendf(&trace_buf, " pkt@%p", pkt);
452 if (pkt->type == QUIC_PACKET_TYPE_SHORT && pkt->data)
453 chunk_appendf(&trace_buf, " kp=%d",
454 !!(*pkt->data & QUIC_PACKET_KEY_PHASE_BIT));
455 chunk_appendf(&trace_buf, " el=%c",
456 quic_packet_type_enc_level_char(pkt->type));
457 if (pkt->pnl)
458 chunk_appendf(&trace_buf, " pnl=%u pn=%llu", pkt->pnl,
459 (unsigned long long)pkt->pn);
460 if (pkt->token_len)
461 chunk_appendf(&trace_buf, " toklen=%llu",
462 (unsigned long long)pkt->token_len);
463 if (pkt->aad_len)
464 chunk_appendf(&trace_buf, " aadlen=%llu",
465 (unsigned long long)pkt->aad_len);
466 chunk_appendf(&trace_buf, " flags=0x%x len=%llu",
467 pkt->flags, (unsigned long long)pkt->len);
468 }
469 if (pktlen)
470 chunk_appendf(&trace_buf, " (%ld)", *pktlen);
471 if (ssl) {
472 enum ssl_encryption_level_t level = SSL_quic_read_level(ssl);
473 chunk_appendf(&trace_buf, " el=%c",
474 quic_enc_level_char(ssl_to_quic_enc_level(level)));
475 }
476 }
477
478 if (mask & (QUIC_EV_CONN_RXPKT|QUIC_EV_CONN_PRSHPKT|QUIC_EV_CONN_SSLDATA)) {
479 const struct quic_rx_packet *pkt = a2;
480 const struct quic_rx_crypto_frm *cf = a3;
481 const SSL *ssl = a4;
482
483 if (pkt)
484 chunk_appendf(&trace_buf, " pkt@%p el=%c pn=%llu", pkt,
485 quic_packet_type_enc_level_char(pkt->type),
486 (unsigned long long)pkt->pn);
487 if (cf)
488 chunk_appendf(&trace_buf, " cfoff=%llu cflen=%llu",
489 (unsigned long long)cf->offset_node.key,
490 (unsigned long long)cf->len);
491 if (ssl) {
492 enum ssl_encryption_level_t level = SSL_quic_read_level(ssl);
493 chunk_appendf(&trace_buf, " rel=%c",
494 quic_enc_level_char(ssl_to_quic_enc_level(level)));
495 }
496
497 if (qc->err.code)
498 chunk_appendf(&trace_buf, " err_code=0x%llx", (ull)qc->err.code);
499 }
500
501 if (mask & (QUIC_EV_CONN_PRSFRM|QUIC_EV_CONN_BFRM)) {
502 const struct quic_frame *frm = a2;
503
504 if (frm)
505 chunk_appendf(&trace_buf, " %s", quic_frame_type_string(frm->type));
506 }
507
508 if (mask & QUIC_EV_CONN_PHPKTS) {
509 const struct quic_enc_level *qel = a2;
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +0200510 const struct list *l = a3;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200511
512 if (qel) {
513 const struct quic_pktns *pktns = qel->pktns;
514 chunk_appendf(&trace_buf,
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200515 " 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 +0200516 quic_enc_level_char_from_qel(qel, qc),
Frédéric Lécaille91369cf2023-04-13 15:55:49 +0200517 qel->pktns->flags,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200518 quic_hdshk_state_str(qc->state),
519 !!(qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED),
Frédéric Lécaille45400532023-02-13 18:39:19 +0100520 qc->path->loss.pto_count,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200521 (unsigned long long)qc->path->cwnd,
522 (unsigned long long)qc->path->prep_in_flight,
523 (unsigned long long)qc->path->in_flight,
524 (unsigned long long)pktns->tx.in_flight,
Amaury Denoyelle2f668f02022-11-18 15:24:08 +0100525 pktns->tx.pto_probe,
526 qel->cstream ? (unsigned long long)qel->cstream->rx.offset : 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200527 }
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +0200528
529 if (l) {
530 const struct quic_frame *frm;
531 list_for_each_entry(frm, l, list) {
532 chunk_appendf(&trace_buf, " frm@%p", frm);
533 chunk_frm_appendf(&trace_buf, frm);
534 }
535 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200536 }
537
538 if (mask & QUIC_EV_CONN_ENCPKT) {
539 const struct enc_debug_info *edi = a2;
540
541 if (edi)
542 chunk_appendf(&trace_buf,
543 " payload=@%p payload_len=%llu"
544 " aad=@%p aad_len=%llu pn=%llu",
545 edi->payload, (unsigned long long)edi->payload_len,
546 edi->aad, (unsigned long long)edi->aad_len,
547 (unsigned long long)edi->pn);
548 }
549
550 if (mask & QUIC_EV_CONN_RMHP) {
551 const struct quic_rx_packet *pkt = a2;
552
553 if (pkt) {
554 const int *ret = a3;
555
556 chunk_appendf(&trace_buf, " pkt@%p", pkt);
557 if (ret && *ret)
558 chunk_appendf(&trace_buf, " pnl=%u pn=%llu",
559 pkt->pnl, (unsigned long long)pkt->pn);
560 }
561 }
562
563 if (mask & QUIC_EV_CONN_PRSAFRM) {
564 const struct quic_frame *frm = a2;
565 const unsigned long *val1 = a3;
566 const unsigned long *val2 = a4;
567
568 if (frm) {
569 chunk_appendf(&trace_buf, " frm@%p", frm);
570 chunk_frm_appendf(&trace_buf, frm);
571 }
572 if (val1)
573 chunk_appendf(&trace_buf, " %lu", *val1);
574 if (val2)
575 chunk_appendf(&trace_buf, "..%lu", *val2);
576 }
577
578 if (mask & QUIC_EV_CONN_ACKSTRM) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200579 const struct qf_stream *strm_frm = a2;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200580 const struct qc_stream_desc *stream = a3;
581
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +0200582 if (strm_frm)
583 chunk_appendf(&trace_buf, " off=%llu len=%llu", (ull)strm_frm->offset.key, (ull)strm_frm->len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200584 if (stream)
585 chunk_appendf(&trace_buf, " ack_offset=%llu", (ull)stream->ack_offset);
586 }
587
588 if (mask & QUIC_EV_CONN_RTTUPDT) {
589 const unsigned int *rtt_sample = a2;
590 const unsigned int *ack_delay = a3;
591 const struct quic_loss *ql = a4;
592
593 if (rtt_sample)
594 chunk_appendf(&trace_buf, " rtt_sample=%ums", *rtt_sample);
595 if (ack_delay)
596 chunk_appendf(&trace_buf, " ack_delay=%ums", *ack_delay);
597 if (ql)
598 chunk_appendf(&trace_buf,
599 " srtt=%ums rttvar=%ums min_rtt=%ums",
Frédéric Lécaille35fb5932023-09-05 15:24:11 +0200600 ql->srtt, ql->rtt_var, ql->rtt_min);
601
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200602 }
603 if (mask & QUIC_EV_CONN_CC) {
604 const struct quic_cc_event *ev = a2;
605 const struct quic_cc *cc = a3;
606
607 if (a2)
608 quic_cc_event_trace(&trace_buf, ev);
609 if (a3)
610 quic_cc_state_trace(&trace_buf, cc);
611 }
612
613 if (mask & QUIC_EV_CONN_PKTLOSS) {
614 const struct quic_pktns *pktns = a2;
615 const struct list *lost_pkts = a3;
616
617 if (pktns) {
618 chunk_appendf(&trace_buf, " pktns=%s",
619 pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL] ? "I" :
620 pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT] ? "01RTT": "H");
621 if (pktns->tx.loss_time)
622 chunk_appendf(&trace_buf, " loss_time=%dms",
623 TICKS_TO_MS(tick_remain(now_ms, pktns->tx.loss_time)));
624 }
625 if (lost_pkts && !LIST_ISEMPTY(lost_pkts)) {
626 struct quic_tx_packet *pkt;
627
628 chunk_appendf(&trace_buf, " lost_pkts:");
629 list_for_each_entry(pkt, lost_pkts, list)
630 chunk_appendf(&trace_buf, " %lu", (unsigned long)pkt->pn_node.key);
631 }
632 }
633
634 if (mask & (QUIC_EV_CONN_STIMER|QUIC_EV_CONN_PTIMER|QUIC_EV_CONN_SPTO)) {
635 const struct quic_pktns *pktns = a2;
636 const int *duration = a3;
637 const uint64_t *ifae_pkts = a4;
638
639 if (ifae_pkts)
640 chunk_appendf(&trace_buf, " ifae_pkts=%llu",
641 (unsigned long long)*ifae_pkts);
642 if (pktns) {
643 chunk_appendf(&trace_buf, " pktns=%s pp=%d",
644 pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL] ? "I" :
645 pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT] ? "01RTT": "H",
646 pktns->tx.pto_probe);
647 if (mask & (QUIC_EV_CONN_STIMER|QUIC_EV_CONN_SPTO)) {
648 if (pktns->tx.in_flight)
649 chunk_appendf(&trace_buf, " if=%llu", (ull)pktns->tx.in_flight);
650 if (pktns->tx.loss_time)
651 chunk_appendf(&trace_buf, " loss_time=%dms",
652 TICKS_TO_MS(pktns->tx.loss_time - now_ms));
653 }
654 if (mask & QUIC_EV_CONN_SPTO) {
655 if (pktns->tx.time_of_last_eliciting)
656 chunk_appendf(&trace_buf, " tole=%dms",
657 TICKS_TO_MS(pktns->tx.time_of_last_eliciting - now_ms));
658 if (duration)
659 chunk_appendf(&trace_buf, " dur=%dms", TICKS_TO_MS(*duration));
660 }
661 }
662
663 if (!(mask & (QUIC_EV_CONN_SPTO|QUIC_EV_CONN_PTIMER)) && qc->timer_task) {
664 chunk_appendf(&trace_buf,
665 " expire=%dms", TICKS_TO_MS(qc->timer - now_ms));
666 }
667 }
668
669 if (mask & QUIC_EV_CONN_SPPKTS) {
670 const struct quic_tx_packet *pkt = a2;
671
Frédéric Lécaille45400532023-02-13 18:39:19 +0100672 chunk_appendf(&trace_buf, " pto_count=%d cwnd=%llu ppif=%llu pif=%llu",
673 qc->path->loss.pto_count,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200674 (unsigned long long)qc->path->cwnd,
675 (unsigned long long)qc->path->prep_in_flight,
676 (unsigned long long)qc->path->in_flight);
677 if (pkt) {
678 const struct quic_frame *frm;
Frédéric Lécaille6fd25762023-04-07 19:01:33 +0200679 if (pkt->flags & QUIC_FL_TX_PACKET_ACK)
680 chunk_appendf(&trace_buf, " ack");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200681 chunk_appendf(&trace_buf, " pn=%lu(%s) iflen=%llu",
682 (unsigned long)pkt->pn_node.key,
683 pkt->pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL] ? "I" :
684 pkt->pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT] ? "01RTT": "H",
685 (unsigned long long)pkt->in_flight_len);
686 chunk_appendf(&trace_buf, " rx.bytes=%llu tx.bytes=%llu",
687 (unsigned long long)qc->rx.bytes,
688 (unsigned long long)qc->tx.bytes);
689 list_for_each_entry(frm, &pkt->frms, list) {
690 chunk_appendf(&trace_buf, " frm@%p", frm);
691 chunk_frm_appendf(&trace_buf, frm);
692 }
Frédéric Lécaillebc09f742023-02-13 17:45:36 +0100693
694 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
695 chunk_appendf(&trace_buf, " with scid");
696 quic_cid_dump(&trace_buf, &qc->scid);
697 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200698 }
699 }
700
701 if (mask & QUIC_EV_CONN_SSLALERT) {
702 const uint8_t *alert = a2;
703 const enum ssl_encryption_level_t *level = a3;
704
705 if (alert)
706 chunk_appendf(&trace_buf, " alert=0x%02x", *alert);
707 if (level)
708 chunk_appendf(&trace_buf, " el=%c",
709 quic_enc_level_char(ssl_to_quic_enc_level(*level)));
710 }
711
712 if (mask & QUIC_EV_CONN_BCFRMS) {
713 const size_t *sz1 = a2;
714 const size_t *sz2 = a3;
715 const size_t *sz3 = a4;
716
717 if (sz1)
718 chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz1);
719 if (sz2)
720 chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz2);
721 if (sz3)
722 chunk_appendf(&trace_buf, " %llu", (unsigned long long)*sz3);
723 }
724
725 if (mask & QUIC_EV_CONN_PSTRM) {
726 const struct quic_frame *frm = a2;
727
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100728 if (frm)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200729 chunk_frm_appendf(&trace_buf, frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200730 }
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +0200731
732 if (mask & QUIC_EV_CONN_ELEVELSEL) {
733 const enum quic_handshake_state *state = a2;
734 const enum quic_tls_enc_level *level = a3;
735 const enum quic_tls_enc_level *next_level = a4;
736
737 if (state)
738 chunk_appendf(&trace_buf, " state=%s", quic_hdshk_state_str(qc->state));
739 if (level)
740 chunk_appendf(&trace_buf, " level=%c", quic_enc_level_char(*level));
741 if (next_level)
742 chunk_appendf(&trace_buf, " next_level=%c", quic_enc_level_char(*next_level));
743
744 }
Amaury Denoyelle5b414862022-10-24 17:40:37 +0200745
Frédéric Lécaille495968e2023-04-03 17:42:05 +0200746 if (mask & QUIC_EV_CONN_IDLE_TIMER) {
747 if (tick_isset(qc->ack_expire))
748 chunk_appendf(&trace_buf, " ack_expire=%ums",
749 TICKS_TO_MS(tick_remain(now_ms, qc->ack_expire)));
750 if (tick_isset(qc->idle_expire))
751 chunk_appendf(&trace_buf, " idle_expire=%ums",
752 TICKS_TO_MS(tick_remain(now_ms, qc->idle_expire)));
Frédéric Lécaillece5c1452023-04-05 09:44:21 +0200753 if (qc->idle_timer_task && tick_isset(qc->idle_timer_task->expire))
Frédéric Lécaille495968e2023-04-03 17:42:05 +0200754 chunk_appendf(&trace_buf, " expire=%ums",
755 TICKS_TO_MS(tick_remain(now_ms, qc->idle_timer_task->expire)));
756 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200757 }
Frédéric Lécailleaaf32f02023-05-12 17:37:29 +0200758
759 if (mask & QUIC_EV_CONN_RCV) {
760 int i;
761 const struct quic_dgram *dgram = a2;
762 char bufaddr[INET6_ADDRSTRLEN], bufport[6];
763
764 if (qc) {
765 addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
766 port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
767 chunk_appendf(&trace_buf, " peer_addr=%s:%s ", bufaddr, bufport);
768 }
769
770 if (dgram) {
771 chunk_appendf(&trace_buf, " dgram.len=%zu", dgram->len);
772 /* Socket */
773 if (dgram->saddr.ss_family == AF_INET ||
774 dgram->saddr.ss_family == AF_INET6) {
775 addr_to_str(&dgram->saddr, bufaddr, sizeof(bufaddr));
776 port_to_str(&dgram->saddr, bufport, sizeof(bufport));
777 chunk_appendf(&trace_buf, "saddr=%s:%s ", bufaddr, bufport);
778
779 addr_to_str(&dgram->daddr, bufaddr, sizeof(bufaddr));
780 port_to_str(&dgram->daddr, bufport, sizeof(bufport));
781 chunk_appendf(&trace_buf, "daddr=%s:%s ", bufaddr, bufport);
782 }
783 /* DCID */
784 for (i = 0; i < dgram->dcid_len; ++i)
785 chunk_appendf(&trace_buf, "%02x", dgram->dcid[i]);
786
787 }
788 }
789
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200790 if (mask & QUIC_EV_CONN_LPKT) {
791 const struct quic_rx_packet *pkt = a2;
792 const uint64_t *len = a3;
793 const struct quic_version *ver = a4;
794
795 if (pkt) {
796 chunk_appendf(&trace_buf, " pkt@%p type=0x%02x %s",
797 pkt, pkt->type, qc_pkt_long(pkt) ? "long" : "short");
798 if (pkt->pn_node.key != (uint64_t)-1)
799 chunk_appendf(&trace_buf, " pn=%llu", pkt->pn_node.key);
800 }
801
802 if (len)
803 chunk_appendf(&trace_buf, " len=%llu", (ull)*len);
804
805 if (ver)
806 chunk_appendf(&trace_buf, " ver=0x%08x", ver->num);
807 }
808
809 if (mask & QUIC_EV_STATELESS_RST) {
810 const struct quic_cid *cid = a2;
811
812 if (cid)
813 quic_cid_dump(&trace_buf, cid);
814 }
815
816}
817
818/* Returns 1 if the peer has validated <qc> QUIC connection address, 0 if not. */
819static inline int quic_peer_validated_addr(struct quic_conn *qc)
820{
821 struct quic_pktns *hdshk_pktns, *app_pktns;
822
823 if (!qc_is_listener(qc))
824 return 1;
825
826 hdshk_pktns = qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns;
827 app_pktns = qc->els[QUIC_TLS_ENC_LEVEL_APP].pktns;
828 if ((hdshk_pktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED) ||
829 (app_pktns->flags & QUIC_FL_PKTNS_PKT_RECEIVED) ||
830 qc->state >= QUIC_HS_ST_COMPLETE)
831 return 1;
832
833 return 0;
834}
835
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100836/* To be called to kill a connection as soon as possible (without sending any packet). */
837void qc_kill_conn(struct quic_conn *qc)
838{
Frédéric Lécaille2f531112023-02-10 14:44:51 +0100839 TRACE_ENTER(QUIC_EV_CONN_KILL, qc);
Frédéric Lécaille495968e2023-04-03 17:42:05 +0200840 TRACE_PROTO("killing the connection", QUIC_EV_CONN_KILL, qc);
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100841 qc->flags |= QUIC_FL_CONN_TO_KILL;
842 task_wakeup(qc->idle_timer_task, TASK_WOKEN_OTHER);
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +0200843
844 qc_notify_err(qc);
845
Frédéric Lécaille2f531112023-02-10 14:44:51 +0100846 TRACE_LEAVE(QUIC_EV_CONN_KILL, qc);
Frédéric Lécaille0aa79952023-02-03 16:15:08 +0100847}
848
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200849/* Set the timer attached to the QUIC connection with <ctx> as I/O handler and used for
850 * both loss detection and PTO and schedule the task assiated to this timer if needed.
851 */
852static inline void qc_set_timer(struct quic_conn *qc)
853{
854 struct quic_pktns *pktns;
855 unsigned int pto;
Frédéric Lécailleb75eecc2023-01-26 15:18:17 +0100856 int handshake_confirmed;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200857
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100858 TRACE_ENTER(QUIC_EV_CONN_STIMER, qc);
859 TRACE_PROTO("set timer", QUIC_EV_CONN_STIMER, qc, NULL, NULL, &qc->path->ifae_pkts);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200860
Frédéric Lécailledd41a452023-02-09 07:48:33 +0100861 pktns = NULL;
862 if (!qc->timer_task) {
863 TRACE_PROTO("already released timer task", QUIC_EV_CONN_STIMER, qc);
864 goto leave;
865 }
866
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200867 pktns = quic_loss_pktns(qc);
868 if (tick_isset(pktns->tx.loss_time)) {
869 qc->timer = pktns->tx.loss_time;
870 goto out;
871 }
872
873 /* anti-amplification: the timer must be
874 * cancelled for a server which reached the anti-amplification limit.
875 */
876 if (!quic_peer_validated_addr(qc) &&
877 (qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED)) {
878 TRACE_PROTO("anti-amplification reached", QUIC_EV_CONN_STIMER, qc);
879 qc->timer = TICK_ETERNITY;
880 goto out;
881 }
882
883 if (!qc->path->ifae_pkts && quic_peer_validated_addr(qc)) {
884 TRACE_PROTO("timer cancellation", QUIC_EV_CONN_STIMER, qc);
885 /* Timer cancellation. */
886 qc->timer = TICK_ETERNITY;
887 goto out;
888 }
889
Frédéric Lécailleb75eecc2023-01-26 15:18:17 +0100890 handshake_confirmed = qc->state >= QUIC_HS_ST_CONFIRMED;
891 pktns = quic_pto_pktns(qc, handshake_confirmed, &pto);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200892 if (tick_isset(pto))
893 qc->timer = pto;
894 out:
Frédéric Lécailledd41a452023-02-09 07:48:33 +0100895 if (qc->timer == TICK_ETERNITY) {
896 qc->timer_task->expire = TICK_ETERNITY;
897 }
898 else if (tick_is_expired(qc->timer, now_ms)) {
899 TRACE_DEVEL("wakeup asap timer task", QUIC_EV_CONN_STIMER, qc);
900 task_wakeup(qc->timer_task, TASK_WOKEN_MSG);
901 }
902 else {
903 TRACE_DEVEL("timer task scheduling", QUIC_EV_CONN_STIMER, qc);
904 task_schedule(qc->timer_task, qc->timer);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200905 }
Frédéric Lécailledd41a452023-02-09 07:48:33 +0100906 leave:
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100907 TRACE_PROTO("set timer", QUIC_EV_CONN_STIMER, qc, pktns);
908 TRACE_LEAVE(QUIC_EV_CONN_STIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200909}
910
911/* Derive new keys and ivs required for Key Update feature for <qc> QUIC
912 * connection.
913 * Return 1 if succeeded, 0 if not.
914 */
915static int quic_tls_key_update(struct quic_conn *qc)
916{
917 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 +0100918 struct quic_tls_secrets *rx = &tls_ctx->rx;
919 struct quic_tls_secrets *tx = &tls_ctx->tx;
920 /* Used only for the traces */
921 struct quic_kp_trace kp_trace = {
922 .rx_sec = rx->secret,
923 .rx_seclen = rx->secretlen,
924 .tx_sec = tx->secret,
925 .tx_seclen = tx->secretlen,
926 };
927 /* The next key phase secrets to be derived */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200928 struct quic_tls_kp *nxt_rx = &qc->ku.nxt_rx;
929 struct quic_tls_kp *nxt_tx = &qc->ku.nxt_tx;
930 const struct quic_version *ver =
931 qc->negotiated_version ? qc->negotiated_version : qc->original_version;
932 int ret = 0;
933
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100934 TRACE_ENTER(QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200935
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200936 nxt_rx = &qc->ku.nxt_rx;
937 nxt_tx = &qc->ku.nxt_tx;
938
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100939 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
940 "nxt_rx->secretlen=%llu rx->secretlen=%llu",
941 (ull)nxt_rx->secretlen, (ull)rx->secretlen);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200942 /* Prepare new RX secrets */
943 if (!quic_tls_sec_update(rx->md, ver, nxt_rx->secret, nxt_rx->secretlen,
944 rx->secret, rx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100945 TRACE_ERROR("New RX secret update failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200946 goto leave;
947 }
948
949 if (!quic_tls_derive_keys(rx->aead, NULL, rx->md, ver,
950 nxt_rx->key, nxt_rx->keylen,
951 nxt_rx->iv, nxt_rx->ivlen, NULL, 0,
952 nxt_rx->secret, nxt_rx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100953 TRACE_ERROR("New RX key derivation failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200954 goto leave;
955 }
956
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100957 kp_trace.rx = nxt_rx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200958 /* Prepare new TX secrets */
959 if (!quic_tls_sec_update(tx->md, ver, nxt_tx->secret, nxt_tx->secretlen,
960 tx->secret, tx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100961 TRACE_ERROR("New TX secret update failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200962 goto leave;
963 }
964
965 if (!quic_tls_derive_keys(tx->aead, NULL, tx->md, ver,
966 nxt_tx->key, nxt_tx->keylen,
967 nxt_tx->iv, nxt_tx->ivlen, NULL, 0,
968 nxt_tx->secret, nxt_tx->secretlen)) {
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100969 TRACE_ERROR("New TX key derivation failed", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200970 goto leave;
971 }
972
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +0100973 kp_trace.tx = nxt_tx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200974 if (nxt_rx->ctx) {
975 EVP_CIPHER_CTX_free(nxt_rx->ctx);
976 nxt_rx->ctx = NULL;
977 }
978
979 if (!quic_tls_rx_ctx_init(&nxt_rx->ctx, tls_ctx->rx.aead, nxt_rx->key)) {
Frédéric Lécaille7a01ff72023-05-02 20:03:19 +0200980 TRACE_ERROR("could not initialize RX TLS cipher context", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200981 goto leave;
982 }
983
984 if (nxt_tx->ctx) {
985 EVP_CIPHER_CTX_free(nxt_tx->ctx);
986 nxt_tx->ctx = NULL;
987 }
988
Frédéric Lécaille7a01ff72023-05-02 20:03:19 +0200989 if (!quic_tls_tx_ctx_init(&nxt_tx->ctx, tls_ctx->tx.aead, nxt_tx->key)) {
990 TRACE_ERROR("could not initialize TX TLS cipher context", QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200991 goto leave;
992 }
993
994 ret = 1;
995 leave:
Frédéric Lécaille8f991942023-03-24 15:14:45 +0100996 TRACE_PROTO("key update", QUIC_EV_CONN_KP, qc, &kp_trace);
997 TRACE_LEAVE(QUIC_EV_CONN_KP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200998 return ret;
999}
1000
1001/* Rotate the Key Update information for <qc> QUIC connection.
1002 * Must be used after having updated them.
1003 * Always succeeds.
1004 */
1005static void quic_tls_rotate_keys(struct quic_conn *qc)
1006{
1007 struct quic_tls_ctx *tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
1008 unsigned char *curr_secret, *curr_iv, *curr_key;
1009 EVP_CIPHER_CTX *curr_ctx;
1010
1011 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
1012
1013 /* Rotate the RX secrets */
1014 curr_ctx = tls_ctx->rx.ctx;
1015 curr_secret = tls_ctx->rx.secret;
1016 curr_iv = tls_ctx->rx.iv;
1017 curr_key = tls_ctx->rx.key;
1018
1019 tls_ctx->rx.ctx = qc->ku.nxt_rx.ctx;
1020 tls_ctx->rx.secret = qc->ku.nxt_rx.secret;
1021 tls_ctx->rx.iv = qc->ku.nxt_rx.iv;
1022 tls_ctx->rx.key = qc->ku.nxt_rx.key;
1023
1024 qc->ku.nxt_rx.ctx = qc->ku.prv_rx.ctx;
1025 qc->ku.nxt_rx.secret = qc->ku.prv_rx.secret;
1026 qc->ku.nxt_rx.iv = qc->ku.prv_rx.iv;
1027 qc->ku.nxt_rx.key = qc->ku.prv_rx.key;
1028
1029 qc->ku.prv_rx.ctx = curr_ctx;
1030 qc->ku.prv_rx.secret = curr_secret;
1031 qc->ku.prv_rx.iv = curr_iv;
1032 qc->ku.prv_rx.key = curr_key;
1033 qc->ku.prv_rx.pn = tls_ctx->rx.pn;
1034
1035 /* Update the TX secrets */
1036 curr_ctx = tls_ctx->tx.ctx;
1037 curr_secret = tls_ctx->tx.secret;
1038 curr_iv = tls_ctx->tx.iv;
1039 curr_key = tls_ctx->tx.key;
1040
1041 tls_ctx->tx.ctx = qc->ku.nxt_tx.ctx;
1042 tls_ctx->tx.secret = qc->ku.nxt_tx.secret;
1043 tls_ctx->tx.iv = qc->ku.nxt_tx.iv;
1044 tls_ctx->tx.key = qc->ku.nxt_tx.key;
1045
1046 qc->ku.nxt_tx.ctx = curr_ctx;
1047 qc->ku.nxt_tx.secret = curr_secret;
1048 qc->ku.nxt_tx.iv = curr_iv;
1049 qc->ku.nxt_tx.key = curr_key;
1050
1051 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
1052}
1053
1054/* returns 0 on error, 1 on success */
1055int ha_quic_set_encryption_secrets(SSL *ssl, enum ssl_encryption_level_t level,
1056 const uint8_t *read_secret,
1057 const uint8_t *write_secret, size_t secret_len)
1058{
1059 struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1060 struct quic_tls_ctx *tls_ctx = &qc->els[ssl_to_quic_enc_level(level)].tls_ctx;
1061 const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001062 struct quic_tls_secrets *rx = NULL, *tx = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001063 const struct quic_version *ver =
1064 qc->negotiated_version ? qc->negotiated_version : qc->original_version;
1065 int ret = 0;
1066
1067 TRACE_ENTER(QUIC_EV_CONN_RWSEC, qc);
1068 BUG_ON(secret_len > QUIC_TLS_SECRET_LEN);
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01001069
1070 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
1071 TRACE_PROTO("connection to be killed", QUIC_EV_CONN_ADDDATA, qc);
1072 goto out;
1073 }
1074
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001075 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) {
1076 TRACE_PROTO("CC required", QUIC_EV_CONN_RWSEC, qc);
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001077 goto out;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001078 }
1079
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001080 if (!read_secret)
1081 goto write;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001082
1083 rx = &tls_ctx->rx;
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001084 if (!quic_tls_secrets_keys_alloc(rx)) {
1085 TRACE_ERROR("RX keys allocation failed", QUIC_EV_CONN_RWSEC, qc);
1086 goto leave;
1087 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001088
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001089 rx->aead = tls_aead(cipher);
1090 rx->md = tls_md(cipher);
1091 rx->hp = tls_hp(cipher);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001092
1093 if (!quic_tls_derive_keys(rx->aead, rx->hp, rx->md, ver, rx->key, rx->keylen,
1094 rx->iv, rx->ivlen, rx->hp_key, sizeof rx->hp_key,
1095 read_secret, secret_len)) {
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001096 TRACE_ERROR("TX key derivation failed", QUIC_EV_CONN_RWSEC, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001097 goto leave;
1098 }
1099
1100 if (!quic_tls_rx_ctx_init(&rx->ctx, rx->aead, rx->key)) {
1101 TRACE_ERROR("could not initial RX TLS cipher context", QUIC_EV_CONN_RWSEC, qc);
1102 goto leave;
1103 }
1104
1105 if (!quic_tls_dec_aes_ctx_init(&rx->hp_ctx, rx->hp, rx->hp_key)) {
1106 TRACE_ERROR("could not initial RX TLS cipher context for HP", QUIC_EV_CONN_RWSEC, qc);
1107 goto leave;
1108 }
1109
1110 /* Enqueue this connection asap if we could derive O-RTT secrets as
1111 * listener. Note that a listener derives only RX secrets for this
1112 * level.
1113 */
1114 if (qc_is_listener(qc) && level == ssl_encryption_early_data) {
1115 TRACE_DEVEL("pushing connection into accept queue", QUIC_EV_CONN_RWSEC, qc);
1116 quic_accept_push_qc(qc);
1117 }
1118
1119write:
1120
1121 if (!write_secret)
Frédéric Lécailleaada8812023-06-06 17:40:41 +02001122 goto keyupdate_init;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001123
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001124 tx = &tls_ctx->tx;
1125 if (!quic_tls_secrets_keys_alloc(tx)) {
1126 TRACE_ERROR("TX keys allocation failed", QUIC_EV_CONN_RWSEC, qc);
1127 goto leave;
1128 }
1129
1130 tx->aead = tls_aead(cipher);
1131 tx->md = tls_md(cipher);
1132 tx->hp = tls_hp(cipher);
1133
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001134 if (!quic_tls_derive_keys(tx->aead, tx->hp, tx->md, ver, tx->key, tx->keylen,
1135 tx->iv, tx->ivlen, tx->hp_key, sizeof tx->hp_key,
1136 write_secret, secret_len)) {
1137 TRACE_ERROR("TX key derivation failed", QUIC_EV_CONN_RWSEC, qc);
1138 goto leave;
1139 }
1140
1141 if (!quic_tls_tx_ctx_init(&tx->ctx, tx->aead, tx->key)) {
1142 TRACE_ERROR("could not initial RX TLS cipher context", QUIC_EV_CONN_RWSEC, qc);
1143 goto leave;
1144 }
1145
1146 if (!quic_tls_enc_aes_ctx_init(&tx->hp_ctx, tx->hp, tx->hp_key)) {
1147 TRACE_ERROR("could not initial TX TLS cipher context for HP", QUIC_EV_CONN_RWSEC, qc);
1148 goto leave;
1149 }
1150
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01001151 if (level == ssl_encryption_handshake && qc_is_listener(qc)) {
1152 qc->enc_params_len =
1153 quic_transport_params_encode(qc->enc_params,
1154 qc->enc_params + sizeof qc->enc_params,
1155 &qc->rx.params, ver, 1);
1156 if (!qc->enc_params_len) {
1157 TRACE_ERROR("quic_transport_params_encode() failed", QUIC_EV_CONN_RWSEC);
1158 goto leave;
1159 }
1160
1161 if (!SSL_set_quic_transport_params(qc->xprt_ctx->ssl, qc->enc_params, qc->enc_params_len)) {
1162 TRACE_ERROR("SSL_set_quic_transport_params() failed", QUIC_EV_CONN_RWSEC);
1163 goto leave;
1164 }
1165 }
1166
Frédéric Lécailleaada8812023-06-06 17:40:41 +02001167 keyupdate_init:
1168 /* Store the secret provided by the TLS stack, required for keyupdate. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001169 if (level == ssl_encryption_application) {
1170 struct quic_tls_kp *prv_rx = &qc->ku.prv_rx;
1171 struct quic_tls_kp *nxt_rx = &qc->ku.nxt_rx;
1172 struct quic_tls_kp *nxt_tx = &qc->ku.nxt_tx;
1173
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001174 if (rx) {
1175 if (!(rx->secret = pool_alloc(pool_head_quic_tls_secret))) {
1176 TRACE_ERROR("Could not allocate RX Application secrete keys", QUIC_EV_CONN_RWSEC, qc);
1177 goto leave;
1178 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001179
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001180 memcpy(rx->secret, read_secret, secret_len);
1181 rx->secretlen = secret_len;
1182 }
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001183
1184 if (tx) {
1185 if (!(tx->secret = pool_alloc(pool_head_quic_tls_secret))) {
1186 TRACE_ERROR("Could not allocate TX Application secrete keys", QUIC_EV_CONN_RWSEC, qc);
1187 goto leave;
1188 }
1189
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001190 memcpy(tx->secret, write_secret, secret_len);
1191 tx->secretlen = secret_len;
1192 }
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02001193
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001194 /* Initialize all the secret keys lengths */
1195 prv_rx->secretlen = nxt_rx->secretlen = nxt_tx->secretlen = secret_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001196 }
1197
1198 out:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001199 ret = 1;
1200 leave:
1201 TRACE_LEAVE(QUIC_EV_CONN_RWSEC, qc, &level);
1202 return ret;
1203}
1204
1205/* This function copies the CRYPTO data provided by the TLS stack found at <data>
1206 * with <len> as size in CRYPTO buffers dedicated to store the information about
1207 * outgoing CRYPTO frames so that to be able to replay the CRYPTO data streams.
1208 * It fails (returns 0) only if it could not managed to allocate enough CRYPTO
1209 * buffers to store all the data.
1210 * Note that CRYPTO data may exist at any encryption level except at 0-RTT.
1211 */
1212static int quic_crypto_data_cpy(struct quic_conn *qc, struct quic_enc_level *qel,
1213 const unsigned char *data, size_t len)
1214{
1215 struct quic_crypto_buf **qcb;
1216 /* The remaining byte to store in CRYPTO buffers. */
1217 size_t cf_offset, cf_len, *nb_buf;
1218 unsigned char *pos;
1219 int ret = 0;
1220
1221 nb_buf = &qel->tx.crypto.nb_buf;
1222 qcb = &qel->tx.crypto.bufs[*nb_buf - 1];
1223 cf_offset = (*nb_buf - 1) * QUIC_CRYPTO_BUF_SZ + (*qcb)->sz;
1224 cf_len = len;
1225
1226 TRACE_ENTER(QUIC_EV_CONN_ADDDATA, qc);
1227
1228 while (len) {
1229 size_t to_copy, room;
1230
1231 pos = (*qcb)->data + (*qcb)->sz;
1232 room = QUIC_CRYPTO_BUF_SZ - (*qcb)->sz;
1233 to_copy = len > room ? room : len;
1234 if (to_copy) {
1235 memcpy(pos, data, to_copy);
1236 /* Increment the total size of this CRYPTO buffers by <to_copy>. */
1237 qel->tx.crypto.sz += to_copy;
1238 (*qcb)->sz += to_copy;
1239 len -= to_copy;
1240 data += to_copy;
1241 }
1242 else {
1243 struct quic_crypto_buf **tmp;
1244
1245 // FIXME: realloc!
1246 tmp = realloc(qel->tx.crypto.bufs,
1247 (*nb_buf + 1) * sizeof *qel->tx.crypto.bufs);
1248 if (tmp) {
1249 qel->tx.crypto.bufs = tmp;
1250 qcb = &qel->tx.crypto.bufs[*nb_buf];
1251 *qcb = pool_alloc(pool_head_quic_crypto_buf);
1252 if (!*qcb) {
1253 TRACE_ERROR("Could not allocate crypto buf", QUIC_EV_CONN_ADDDATA, qc);
1254 goto leave;
1255 }
1256
1257 (*qcb)->sz = 0;
1258 ++*nb_buf;
1259 }
1260 else {
1261 break;
1262 }
1263 }
1264 }
1265
1266 /* Allocate a TX CRYPTO frame only if all the CRYPTO data
1267 * have been buffered.
1268 */
1269 if (!len) {
1270 struct quic_frame *frm;
1271 struct quic_frame *found = NULL;
1272
1273 /* There is at most one CRYPTO frame in this packet number
1274 * space. Let's look for it.
1275 */
1276 list_for_each_entry(frm, &qel->pktns->tx.frms, list) {
1277 if (frm->type != QUIC_FT_CRYPTO)
1278 continue;
1279
1280 /* Found */
1281 found = frm;
1282 break;
1283 }
1284
1285 if (found) {
1286 found->crypto.len += cf_len;
1287 }
1288 else {
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01001289 frm = qc_frm_alloc(QUIC_FT_CRYPTO);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001290 if (!frm) {
1291 TRACE_ERROR("Could not allocate quic frame", QUIC_EV_CONN_ADDDATA, qc);
1292 goto leave;
1293 }
1294
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001295 frm->crypto.offset = cf_offset;
1296 frm->crypto.len = cf_len;
1297 frm->crypto.qel = qel;
1298 LIST_APPEND(&qel->pktns->tx.frms, &frm->list);
1299 }
1300 }
1301 ret = len == 0;
1302 leave:
1303 TRACE_LEAVE(QUIC_EV_CONN_ADDDATA, qc);
1304 return ret;
1305}
1306
1307/* Prepare the emission of CONNECTION_CLOSE with error <err>. All send/receive
1308 * activity for <qc> will be interrupted.
1309 */
1310void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err)
1311{
1312 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
1313 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)
1314 goto leave;
1315
1316 TRACE_STATE("setting immediate close", QUIC_EV_CONN_CLOSE, qc);
1317 qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
1318 qc->err.code = err.code;
1319 qc->err.app = err.app;
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02001320
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001321 leave:
1322 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
1323}
1324
1325/* Set <alert> TLS alert as QUIC CRYPTO_ERROR error */
1326void quic_set_tls_alert(struct quic_conn *qc, int alert)
1327{
1328 TRACE_ENTER(QUIC_EV_CONN_SSLALERT, qc);
1329
1330 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
1331 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
1332 TRACE_DEVEL("dec half open counter", QUIC_EV_CONN_SSLALERT, qc);
1333 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
1334 }
1335 quic_set_connection_close(qc, quic_err_tls(alert));
1336 qc->flags |= QUIC_FL_CONN_TLS_ALERT;
1337 TRACE_STATE("Alert set", QUIC_EV_CONN_SSLALERT, qc);
1338
1339 TRACE_LEAVE(QUIC_EV_CONN_SSLALERT, qc);
1340}
1341
1342/* Set the application for <qc> QUIC connection.
1343 * Return 1 if succeeded, 0 if not.
1344 */
1345int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len)
1346{
1347 if (alpn_len >= 2 && memcmp(alpn, "h3", 2) == 0)
1348 qc->app_ops = &h3_ops;
1349 else if (alpn_len >= 10 && memcmp(alpn, "hq-interop", 10) == 0)
1350 qc->app_ops = &hq_interop_ops;
1351 else
1352 return 0;
1353
1354 return 1;
1355}
1356
1357/* ->add_handshake_data QUIC TLS callback used by the QUIC TLS stack when it
1358 * wants to provide the QUIC layer with CRYPTO data.
1359 * Returns 1 if succeeded, 0 if not.
1360 */
1361int ha_quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level,
1362 const uint8_t *data, size_t len)
1363{
1364 struct quic_conn *qc;
1365 enum quic_tls_enc_level tel;
1366 struct quic_enc_level *qel;
1367 int ret = 0;
1368
1369 qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1370 TRACE_ENTER(QUIC_EV_CONN_ADDDATA, qc);
1371
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01001372 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
1373 TRACE_PROTO("connection to be killed", QUIC_EV_CONN_ADDDATA, qc);
1374 goto out;
1375 }
1376
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001377 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) {
1378 TRACE_PROTO("CC required", QUIC_EV_CONN_ADDDATA, qc);
1379 goto out;
1380 }
1381
1382 tel = ssl_to_quic_enc_level(level);
1383 if (tel == -1) {
1384 TRACE_ERROR("Wrong encryption level", QUIC_EV_CONN_ADDDATA, qc);
1385 goto leave;
1386 }
1387
1388 qel = &qc->els[tel];
1389 if (!quic_crypto_data_cpy(qc, qel, data, len)) {
1390 TRACE_ERROR("Could not bufferize", QUIC_EV_CONN_ADDDATA, qc);
1391 goto leave;
1392 }
1393
1394 TRACE_DEVEL("CRYPTO data buffered", QUIC_EV_CONN_ADDDATA,
1395 qc, &level, &len);
1396 out:
1397 ret = 1;
1398 leave:
1399 TRACE_LEAVE(QUIC_EV_CONN_ADDDATA, qc);
1400 return ret;
1401}
1402
1403int ha_quic_flush_flight(SSL *ssl)
1404{
1405 struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1406
1407 TRACE_ENTER(QUIC_EV_CONN_FFLIGHT, qc);
1408 TRACE_LEAVE(QUIC_EV_CONN_FFLIGHT, qc);
1409
1410 return 1;
1411}
1412
1413int ha_quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert)
1414{
1415 struct quic_conn *qc = SSL_get_ex_data(ssl, ssl_qc_app_data_index);
1416
1417 TRACE_ENTER(QUIC_EV_CONN_SSLALERT, qc);
1418
1419 TRACE_PROTO("Received TLS alert", QUIC_EV_CONN_SSLALERT, qc, &alert, &level);
1420
1421 quic_set_tls_alert(qc, alert);
1422 TRACE_LEAVE(QUIC_EV_CONN_SSLALERT, qc);
1423 return 1;
1424}
1425
1426/* QUIC TLS methods */
1427static SSL_QUIC_METHOD ha_quic_method = {
1428 .set_encryption_secrets = ha_quic_set_encryption_secrets,
1429 .add_handshake_data = ha_quic_add_handshake_data,
1430 .flush_flight = ha_quic_flush_flight,
1431 .send_alert = ha_quic_send_alert,
1432};
1433
1434/* Initialize the TLS context of a listener with <bind_conf> as configuration.
1435 * Returns an error count.
1436 */
1437int ssl_quic_initial_ctx(struct bind_conf *bind_conf)
1438{
1439 struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
1440 int cfgerr = 0;
1441
1442 long options =
1443 (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
1444 SSL_OP_SINGLE_ECDH_USE |
1445 SSL_OP_CIPHER_SERVER_PREFERENCE;
1446 SSL_CTX *ctx;
1447
1448 ctx = SSL_CTX_new(TLS_server_method());
1449 bind_conf->initial_ctx = ctx;
1450
1451 SSL_CTX_set_options(ctx, options);
1452 SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
1453 SSL_CTX_set_min_proto_version(ctx, TLS1_3_VERSION);
1454 SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
1455
1456#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1457# if defined(HAVE_SSL_CLIENT_HELLO_CB)
1458# if defined(SSL_OP_NO_ANTI_REPLAY)
1459 if (bind_conf->ssl_conf.early_data) {
1460 SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY);
William Lallemand3ccfc102023-08-21 13:51:56 +02001461# ifdef USE_QUIC_OPENSSL_COMPAT
1462 ha_warning("Binding [%s:%d] for %s %s: 0-RTT is not supported in limited QUIC compatibility mode, ignored.\n",
1463 bind_conf->file, bind_conf->line, proxy_type_str(bind_conf->frontend), bind_conf->frontend->id);
1464# else
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001465 SSL_CTX_set_max_early_data(ctx, 0xffffffff);
William Lallemand3ccfc102023-08-21 13:51:56 +02001466# endif /* ! USE_QUIC_OPENSSL_COMPAT */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001467 }
1468# endif /* !SSL_OP_NO_ANTI_REPLAY */
1469 SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL);
1470 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk);
1471# else /* ! HAVE_SSL_CLIENT_HELLO_CB */
1472 SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_cbk);
1473# endif
1474 SSL_CTX_set_tlsext_servername_arg(ctx, bind_conf);
1475#endif
Frédéric Lécaille29d2ce32023-06-08 09:28:31 +02001476#ifdef USE_QUIC_OPENSSL_COMPAT
1477 if (!quic_tls_compat_init(bind_conf, ctx))
William Lallemand48d3c302023-08-21 15:22:57 +02001478 cfgerr++;
Frédéric Lécaille29d2ce32023-06-08 09:28:31 +02001479#endif
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001480
1481 return cfgerr;
1482}
1483
1484/* Decode an expected packet number from <truncated_on> its truncated value,
1485 * depending on <largest_pn> the largest received packet number, and <pn_nbits>
1486 * the number of bits used to encode this packet number (its length in bytes * 8).
1487 * See https://quicwg.org/base-drafts/draft-ietf-quic-transport.html#packet-encoding
1488 */
1489static uint64_t decode_packet_number(uint64_t largest_pn,
1490 uint32_t truncated_pn, unsigned int pn_nbits)
1491{
1492 uint64_t expected_pn = largest_pn + 1;
1493 uint64_t pn_win = (uint64_t)1 << pn_nbits;
1494 uint64_t pn_hwin = pn_win / 2;
1495 uint64_t pn_mask = pn_win - 1;
1496 uint64_t candidate_pn;
1497
1498
1499 candidate_pn = (expected_pn & ~pn_mask) | truncated_pn;
1500 /* Note that <pn_win> > <pn_hwin>. */
1501 if (candidate_pn < QUIC_MAX_PACKET_NUM - pn_win &&
1502 candidate_pn + pn_hwin <= expected_pn)
1503 return candidate_pn + pn_win;
1504
1505 if (candidate_pn > expected_pn + pn_hwin && candidate_pn >= pn_win)
1506 return candidate_pn - pn_win;
1507
1508 return candidate_pn;
1509}
1510
1511/* Remove the header protection of <pkt> QUIC packet using <tls_ctx> as QUIC TLS
1512 * cryptographic context.
1513 * <largest_pn> is the largest received packet number and <pn> the address of
1514 * the packet number field for this packet with <byte0> address of its first byte.
1515 * <end> points to one byte past the end of this packet.
1516 * Returns 1 if succeeded, 0 if not.
1517 */
1518static int qc_do_rm_hp(struct quic_conn *qc,
1519 struct quic_rx_packet *pkt, struct quic_tls_ctx *tls_ctx,
1520 int64_t largest_pn, unsigned char *pn, unsigned char *byte0)
1521{
1522 int ret, i, pnlen;
1523 uint64_t packet_number;
1524 uint32_t truncated_pn = 0;
1525 unsigned char mask[5] = {0};
1526 unsigned char *sample;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001527
1528 TRACE_ENTER(QUIC_EV_CONN_RMHP, qc);
1529
1530 ret = 0;
1531
1532 /* Check there is enough data in this packet. */
1533 if (pkt->len - (pn - byte0) < QUIC_PACKET_PN_MAXLEN + sizeof mask) {
1534 TRACE_PROTO("too short packet", QUIC_EV_CONN_RMHP, qc, pkt);
1535 goto leave;
1536 }
1537
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001538 sample = pn + QUIC_PACKET_PN_MAXLEN;
1539
1540 if (!quic_tls_aes_decrypt(mask, sample, sizeof mask, tls_ctx->rx.hp_ctx)) {
1541 TRACE_ERROR("HP removing failed", QUIC_EV_CONN_RMHP, qc, pkt);
1542 goto leave;
1543 }
1544
1545 *byte0 ^= mask[0] & (*byte0 & QUIC_PACKET_LONG_HEADER_BIT ? 0xf : 0x1f);
1546 pnlen = (*byte0 & QUIC_PACKET_PNL_BITMASK) + 1;
1547 for (i = 0; i < pnlen; i++) {
1548 pn[i] ^= mask[i + 1];
1549 truncated_pn = (truncated_pn << 8) | pn[i];
1550 }
1551
1552 packet_number = decode_packet_number(largest_pn, truncated_pn, pnlen * 8);
1553 /* Store remaining information for this unprotected header */
1554 pkt->pn = packet_number;
1555 pkt->pnl = pnlen;
1556
1557 ret = 1;
1558 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001559 TRACE_LEAVE(QUIC_EV_CONN_RMHP, qc);
1560 return ret;
1561}
1562
1563/* Encrypt the payload of a QUIC packet with <pn> as number found at <payload>
1564 * address, with <payload_len> as payload length, <aad> as address of
1565 * the ADD and <aad_len> as AAD length depending on the <tls_ctx> QUIC TLS
1566 * context.
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02001567 *
1568 * TODO no error is expected as encryption is done in place but encryption
1569 * manual is unclear. <fail> will be set to true if an error is detected.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001570 */
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02001571static void quic_packet_encrypt(unsigned char *payload, size_t payload_len,
1572 unsigned char *aad, size_t aad_len, uint64_t pn,
1573 struct quic_tls_ctx *tls_ctx, struct quic_conn *qc,
1574 int *fail)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001575{
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001576 unsigned char iv[QUIC_TLS_IV_LEN];
1577 unsigned char *tx_iv = tls_ctx->tx.iv;
1578 size_t tx_iv_sz = tls_ctx->tx.ivlen;
1579 struct enc_debug_info edi;
1580
1581 TRACE_ENTER(QUIC_EV_CONN_ENCPKT, qc);
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02001582 *fail = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001583
Amaury Denoyelle5eadc272023-05-16 18:11:01 +02001584 quic_aead_iv_build(iv, sizeof iv, tx_iv, tx_iv_sz, pn);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001585
1586 if (!quic_tls_encrypt(payload, payload_len, aad, aad_len,
Emeric Brune0190c62023-07-11 14:53:41 +02001587 tls_ctx->tx.ctx, tls_ctx->tx.aead, iv)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001588 TRACE_ERROR("QUIC packet encryption failed", QUIC_EV_CONN_ENCPKT, qc);
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02001589 *fail = 1;
1590 enc_debug_info_init(&edi, payload, payload_len, aad, aad_len, pn);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001591 }
1592
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001593 TRACE_LEAVE(QUIC_EV_CONN_ENCPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001594}
1595
Frédéric Lécaille72027782023-02-22 16:20:09 +01001596/* Select the correct TLS cipher context to used to decipher <pkt> packet
1597 * attached to <qc> connection from <qel> encryption level.
1598 */
1599static inline struct quic_tls_ctx *qc_select_tls_ctx(struct quic_conn *qc,
1600 struct quic_enc_level *qel,
1601 struct quic_rx_packet *pkt)
1602{
1603 return pkt->type != QUIC_PACKET_TYPE_INITIAL ? &qel->tls_ctx :
1604 pkt->version == qc->negotiated_version ? &qc->negotiated_ictx : &qel->tls_ctx;
1605}
1606
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001607/* Decrypt <pkt> packet using encryption level <qel> for <qc> connection.
1608 * Decryption is done in place in packet buffer.
1609 *
Ilya Shipitsin5fa29b82022-12-07 09:46:19 +05001610 * Returns 1 on success else 0.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001611 */
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001612static int qc_pkt_decrypt(struct quic_conn *qc, struct quic_enc_level *qel,
1613 struct quic_rx_packet *pkt)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001614{
1615 int ret, kp_changed;
1616 unsigned char iv[QUIC_TLS_IV_LEN];
Frédéric Lécaille72027782023-02-22 16:20:09 +01001617 struct quic_tls_ctx *tls_ctx = qc_select_tls_ctx(qc, qel, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001618 EVP_CIPHER_CTX *rx_ctx = tls_ctx->rx.ctx;
1619 unsigned char *rx_iv = tls_ctx->rx.iv;
1620 size_t rx_iv_sz = tls_ctx->rx.ivlen;
1621 unsigned char *rx_key = tls_ctx->rx.key;
1622
1623 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
1624
1625 ret = 0;
1626 kp_changed = 0;
1627
1628 if (pkt->type == QUIC_PACKET_TYPE_SHORT) {
1629 /* The two tested bits are not at the same position,
1630 * this is why they are first both inversed.
1631 */
1632 if (!(*pkt->data & QUIC_PACKET_KEY_PHASE_BIT) ^ !(tls_ctx->flags & QUIC_FL_TLS_KP_BIT_SET)) {
1633 if (pkt->pn < tls_ctx->rx.pn) {
1634 /* The lowest packet number of a previous key phase
1635 * cannot be null if it really stores previous key phase
1636 * secrets.
1637 */
1638 // TODO: check if BUG_ON() more suitable
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001639 if (!qc->ku.prv_rx.pn) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001640 TRACE_ERROR("null previous packet number", QUIC_EV_CONN_RXPKT, qc);
1641 goto leave;
1642 }
1643
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001644 rx_ctx = qc->ku.prv_rx.ctx;
1645 rx_iv = qc->ku.prv_rx.iv;
1646 rx_key = qc->ku.prv_rx.key;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001647 }
1648 else if (pkt->pn > qel->pktns->rx.largest_pn) {
1649 /* Next key phase */
Frédéric Lécaille51a7caf2023-02-23 20:38:23 +01001650 TRACE_PROTO("Key phase changed", QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001651 kp_changed = 1;
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001652 rx_ctx = qc->ku.nxt_rx.ctx;
1653 rx_iv = qc->ku.nxt_rx.iv;
1654 rx_key = qc->ku.nxt_rx.key;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001655 }
1656 }
1657 }
1658
Amaury Denoyelle5eadc272023-05-16 18:11:01 +02001659 quic_aead_iv_build(iv, sizeof iv, rx_iv, rx_iv_sz, pkt->pn);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001660
1661 ret = quic_tls_decrypt(pkt->data + pkt->aad_len, pkt->len - pkt->aad_len,
1662 pkt->data, pkt->aad_len,
1663 rx_ctx, tls_ctx->rx.aead, rx_key, iv);
1664 if (!ret) {
1665 TRACE_ERROR("quic_tls_decrypt() failed", QUIC_EV_CONN_RXPKT, qc);
1666 goto leave;
1667 }
1668
1669 /* Update the keys only if the packet decryption succeeded. */
1670 if (kp_changed) {
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001671 quic_tls_rotate_keys(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001672 /* Toggle the Key Phase bit */
1673 tls_ctx->flags ^= QUIC_FL_TLS_KP_BIT_SET;
1674 /* Store the lowest packet number received for the current key phase */
1675 tls_ctx->rx.pn = pkt->pn;
1676 /* Prepare the next key update */
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01001677 if (!quic_tls_key_update(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001678 TRACE_ERROR("quic_tls_key_update() failed", QUIC_EV_CONN_RXPKT, qc);
1679 goto leave;
1680 }
1681 }
1682
1683 /* Update the packet length (required to parse the frames). */
1684 pkt->len -= QUIC_TLS_TAG_LEN;
1685 ret = 1;
1686 leave:
1687 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
1688 return ret;
1689}
1690
1691
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001692/* Release <frm> frame and mark its copies as acknowledged */
1693void qc_release_frm(struct quic_conn *qc, struct quic_frame *frm)
1694{
1695 uint64_t pn;
1696 struct quic_frame *origin, *f, *tmp;
1697
1698 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1699
1700 /* Identify this frame: a frame copy or one of its copies */
1701 origin = frm->origin ? frm->origin : frm;
1702 /* Ensure the source of the copies is flagged as acked, <frm> being
1703 * possibly a copy of <origin>
1704 */
1705 origin->flags |= QUIC_FL_TX_FRAME_ACKED;
1706 /* Mark all the copy of <origin> as acknowledged. We must
1707 * not release the packets (releasing the frames) at this time as
1708 * they are possibly also to be acknowledged alongside the
1709 * the current one.
1710 */
1711 list_for_each_entry_safe(f, tmp, &origin->reflist, ref) {
1712 if (f->pkt) {
1713 f->flags |= QUIC_FL_TX_FRAME_ACKED;
1714 f->origin = NULL;
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001715 LIST_DEL_INIT(&f->ref);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001716 pn = f->pkt->pn_node.key;
1717 TRACE_DEVEL("mark frame as acked from packet",
1718 QUIC_EV_CONN_PRSAFRM, qc, f, &pn);
1719 }
1720 else {
1721 TRACE_DEVEL("freeing unsent frame",
1722 QUIC_EV_CONN_PRSAFRM, qc, f);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001723 LIST_DEL_INIT(&f->ref);
1724 qc_frm_free(&f);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001725 }
1726 }
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001727 LIST_DEL_INIT(&frm->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001728 pn = frm->pkt->pn_node.key;
1729 quic_tx_packet_refdec(frm->pkt);
1730 TRACE_DEVEL("freeing frame from packet",
1731 QUIC_EV_CONN_PRSAFRM, qc, frm, &pn);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001732 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001733
1734 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1735}
1736
1737/* Schedule a CONNECTION_CLOSE emission on <qc> if the MUX has been released
1738 * and all STREAM data are acknowledged. The MUX is responsible to have set
1739 * <qc.err> before as it is reused for the CONNECTION_CLOSE frame.
1740 *
1741 * TODO this should also be called on lost packet detection
1742 */
1743void qc_check_close_on_released_mux(struct quic_conn *qc)
1744{
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001745 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
1746
1747 if (qc->mux_state == QC_MUX_RELEASED && eb_is_empty(&qc->streams_by_id)) {
1748 /* Reuse errcode which should have been previously set by the MUX on release. */
1749 quic_set_connection_close(qc, qc->err);
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02001750 tasklet_wakeup(qc->wait_event.tasklet);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001751 }
1752
1753 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
1754}
1755
1756/* Remove from <stream> the acknowledged frames.
1757 *
1758 * Returns 1 if at least one frame was removed else 0.
1759 */
1760static int quic_stream_try_to_consume(struct quic_conn *qc,
1761 struct qc_stream_desc *stream)
1762{
1763 int ret;
1764 struct eb64_node *frm_node;
1765
1766 TRACE_ENTER(QUIC_EV_CONN_ACKSTRM, qc);
1767
1768 ret = 0;
1769 frm_node = eb64_first(&stream->acked_frms);
1770 while (frm_node) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02001771 struct qf_stream *strm_frm;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001772 struct quic_frame *frm;
1773 size_t offset, len;
1774
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02001775 strm_frm = eb64_entry(frm_node, struct qf_stream, offset);
1776 offset = strm_frm->offset.key;
1777 len = strm_frm->len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001778
1779 if (offset > stream->ack_offset)
1780 break;
1781
1782 if (qc_stream_desc_ack(&stream, offset, len)) {
1783 /* cf. next comment : frame may be freed at this stage. */
1784 TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02001785 qc, stream ? strm_frm : NULL, stream);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001786 ret = 1;
1787 }
1788
1789 /* If stream is NULL after qc_stream_desc_ack(), it means frame
1790 * has been freed. with the stream frames tree. Nothing to do
1791 * anymore in here.
1792 */
1793 if (!stream) {
1794 qc_check_close_on_released_mux(qc);
1795 ret = 1;
1796 goto leave;
1797 }
1798
1799 frm_node = eb64_next(frm_node);
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02001800 eb64_delete(&strm_frm->offset);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001801
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02001802 frm = container_of(strm_frm, struct quic_frame, stream);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001803 qc_release_frm(qc, frm);
1804 }
1805
1806 leave:
1807 TRACE_LEAVE(QUIC_EV_CONN_ACKSTRM, qc);
1808 return ret;
1809}
1810
1811/* Treat <frm> frame whose packet it is attached to has just been acknowledged. */
1812static inline void qc_treat_acked_tx_frm(struct quic_conn *qc,
1813 struct quic_frame *frm)
1814{
Frédéric Lécaille8f991942023-03-24 15:14:45 +01001815 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1816 TRACE_PROTO("RX ack TX frm", QUIC_EV_CONN_PRSAFRM, qc, frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001817
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001818 switch (frm->type) {
1819 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
1820 {
Amaury Denoyelle888c5f22023-04-24 14:26:30 +02001821 struct qf_stream *strm_frm = &frm->stream;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001822 struct eb64_node *node = NULL;
1823 struct qc_stream_desc *stream = NULL;
1824 const size_t offset = strm_frm->offset.key;
1825 const size_t len = strm_frm->len;
1826
1827 /* do not use strm_frm->stream as the qc_stream_desc instance
1828 * might be freed at this stage. Use the id to do a proper
1829 * lookup.
1830 *
1831 * TODO if lookup operation impact on the perf is noticeable,
1832 * implement a refcount on qc_stream_desc instances.
1833 */
1834 node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
1835 if (!node) {
1836 TRACE_DEVEL("acked stream for released stream", QUIC_EV_CONN_ACKSTRM, qc, strm_frm);
1837 qc_release_frm(qc, frm);
1838 /* early return */
1839 goto leave;
1840 }
1841 stream = eb64_entry(node, struct qc_stream_desc, by_id);
1842
1843 TRACE_DEVEL("acked stream", QUIC_EV_CONN_ACKSTRM, qc, strm_frm, stream);
1844 if (offset <= stream->ack_offset) {
1845 if (qc_stream_desc_ack(&stream, offset, len)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001846 TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
1847 qc, strm_frm, stream);
1848 }
1849
1850 if (!stream) {
1851 /* no need to continue if stream freed. */
1852 TRACE_DEVEL("stream released and freed", QUIC_EV_CONN_ACKSTRM, qc);
1853 qc_release_frm(qc, frm);
1854 qc_check_close_on_released_mux(qc);
1855 break;
1856 }
1857
1858 TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
1859 qc, strm_frm, stream);
1860 qc_release_frm(qc, frm);
1861 }
1862 else {
1863 eb64_insert(&stream->acked_frms, &strm_frm->offset);
1864 }
1865
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01001866 quic_stream_try_to_consume(qc, stream);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001867 }
1868 break;
1869 default:
1870 qc_release_frm(qc, frm);
1871 }
1872
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001873 leave:
1874 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1875}
1876
Frédéric Lécaille39bde282023-08-29 14:48:54 +02001877/* Collect newly acknowledged TX packets from <pkts> ebtree into <newly_acked_pkts>
1878 * list depending on <largest> and <smallest> packet number of a range of acknowledged
1879 * packets announced in an ACK frame. <largest_node> may be provided to start
1880 * looking from this packet node.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001881 */
Frédéric Lécaille39bde282023-08-29 14:48:54 +02001882static void qc_newly_acked_pkts(struct quic_conn *qc, struct eb_root *pkts,
1883 struct list *newly_acked_pkts,
1884 struct eb64_node *largest_node,
1885 uint64_t largest, uint64_t smallest)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001886{
1887 struct eb64_node *node;
1888 struct quic_tx_packet *pkt;
1889
1890 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1891
Frédéric Lécaillec664e642023-03-15 17:21:13 +01001892 node = eb64_lookup_ge(pkts, smallest);
1893 if (!node)
1894 goto leave;
1895
1896 largest_node = largest_node ? largest_node : eb64_lookup_le(pkts, largest);
1897 if (!largest_node)
1898 goto leave;
1899
1900 while (node && node->key <= largest_node->key) {
Frédéric Lécaille39bde282023-08-29 14:48:54 +02001901 pkt = eb64_entry(node, struct quic_tx_packet, pn_node);
1902 LIST_APPEND(newly_acked_pkts, &pkt->list);
1903 node = eb64_next(node);
1904 eb64_delete(&pkt->pn_node);
1905 }
1906
1907 leave:
1908 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1909}
1910
1911/* Remove <largest> down to <smallest> node entries from <pkts> tree of TX packet,
1912 * deallocating them, and their TX frames.
1913 * May be NULL if <largest> node could not be found.
1914 */
1915static void qc_ackrng_pkts(struct quic_conn *qc,
1916 unsigned int *pkt_flags, struct list *newly_acked_pkts)
1917{
1918 struct quic_tx_packet *pkt, *tmp;
1919
1920 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1921
1922 list_for_each_entry_safe(pkt, tmp, newly_acked_pkts, list) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001923 struct quic_frame *frm, *frmbak;
1924
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001925 *pkt_flags |= pkt->flags;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001926 TRACE_DEVEL("Removing packet #", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
1927 list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
1928 qc_treat_acked_tx_frm(qc, frm);
Frédéric Lécaille814645f2022-11-18 18:15:28 +01001929 /* If there are others packet in the same datagram <pkt> is attached to,
1930 * detach the previous one and the next one from <pkt>.
1931 */
Frédéric Lécaille74b5f7b2022-11-20 18:35:35 +01001932 quic_tx_packet_dgram_detach(pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001933 eb64_delete(&pkt->pn_node);
1934 }
1935
Frédéric Lécaillec664e642023-03-15 17:21:13 +01001936 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001937 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001938}
1939
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001940/* Remove all frames from <pkt_frm_list> and reinsert them in the same order
1941 * they have been sent into <pktns_frm_list>. The loss counter of each frame is
1942 * incremented and checked if it does not exceed retransmission limit.
1943 *
1944 * Returns 1 on success, 0 if a frame loss limit is exceeded. A
1945 * CONNECTION_CLOSE is scheduled in this case.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001946 */
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001947static inline int qc_requeue_nacked_pkt_tx_frms(struct quic_conn *qc,
1948 struct quic_tx_packet *pkt,
1949 struct list *pktns_frm_list)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001950{
1951 struct quic_frame *frm, *frmbak;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001952 struct list *pkt_frm_list = &pkt->frms;
1953 uint64_t pn = pkt->pn_node.key;
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01001954 int close = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001955
1956 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1957
1958 list_for_each_entry_safe(frm, frmbak, pkt_frm_list, list) {
1959 /* First remove this frame from the packet it was attached to */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001960 LIST_DEL_INIT(&frm->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001961 quic_tx_packet_refdec(pkt);
1962 /* At this time, this frame is not freed but removed from its packet */
1963 frm->pkt = NULL;
1964 /* Remove any reference to this frame */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001965 qc_frm_unref(frm, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001966 switch (frm->type) {
1967 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
1968 {
Amaury Denoyelle888c5f22023-04-24 14:26:30 +02001969 struct qf_stream *strm_frm = &frm->stream;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001970 struct eb64_node *node = NULL;
1971 struct qc_stream_desc *stream_desc;
1972
1973 node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
1974 if (!node) {
1975 TRACE_DEVEL("released stream", QUIC_EV_CONN_PRSAFRM, qc, frm);
1976 TRACE_DEVEL("freeing frame from packet", QUIC_EV_CONN_PRSAFRM,
1977 qc, frm, &pn);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001978 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001979 continue;
1980 }
1981
1982 stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
1983 /* Do not resend this frame if in the "already acked range" */
1984 if (strm_frm->offset.key + strm_frm->len <= stream_desc->ack_offset) {
1985 TRACE_DEVEL("ignored frame in already acked range",
1986 QUIC_EV_CONN_PRSAFRM, qc, frm);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01001987 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001988 continue;
1989 }
1990 else if (strm_frm->offset.key < stream_desc->ack_offset) {
Frédéric Lécailleca079792023-03-17 08:56:50 +01001991 uint64_t diff = stream_desc->ack_offset - strm_frm->offset.key;
1992
Frédéric Lécaillec425e032023-03-20 14:32:59 +01001993 qc_stream_frm_mv_fwd(frm, diff);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02001994 TRACE_DEVEL("updated partially acked frame",
1995 QUIC_EV_CONN_PRSAFRM, qc, frm);
1996 }
1997 break;
1998 }
1999
2000 default:
2001 break;
2002 }
2003
2004 /* Do not resend probing packet with old data */
2005 if (pkt->flags & QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA) {
2006 TRACE_DEVEL("ignored frame with old data from packet", QUIC_EV_CONN_PRSAFRM,
2007 qc, frm, &pn);
2008 if (frm->origin)
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01002009 LIST_DEL_INIT(&frm->ref);
2010 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002011 continue;
2012 }
2013
2014 if (frm->flags & QUIC_FL_TX_FRAME_ACKED) {
2015 TRACE_DEVEL("already acked frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
2016 TRACE_DEVEL("freeing frame from packet", QUIC_EV_CONN_PRSAFRM,
2017 qc, frm, &pn);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01002018 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002019 }
2020 else {
Amaury Denoyelle24d5b722023-01-31 11:44:50 +01002021 if (++frm->loss_count >= global.tune.quic_max_frame_loss) {
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002022 TRACE_ERROR("retransmission limit reached, closing the connection", QUIC_EV_CONN_PRSAFRM, qc);
2023 quic_set_connection_close(qc, quic_err_transport(QC_ERR_INTERNAL_ERROR));
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02002024 qc_notify_err(qc);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002025 close = 1;
2026 }
2027
Frédéric Lécaillebe795ce2023-03-08 18:23:13 +01002028 LIST_APPEND(pktns_frm_list, &frm->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002029 TRACE_DEVEL("frame requeued", QUIC_EV_CONN_PRSAFRM, qc, frm);
2030 }
2031 }
2032
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002033 end:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002034 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002035 return !close;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002036}
2037
2038/* Free <pkt> TX packet and its attached frames.
2039 * This is the responsibility of the caller to remove this packet of
2040 * any data structure it was possibly attached to.
2041 */
2042static inline void free_quic_tx_packet(struct quic_conn *qc,
2043 struct quic_tx_packet *pkt)
2044{
2045 struct quic_frame *frm, *frmbak;
2046
2047 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
2048
2049 if (!pkt)
2050 goto leave;
2051
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01002052 list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
2053 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002054 pool_free(pool_head_quic_tx_packet, pkt);
2055
2056 leave:
2057 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
2058}
2059
2060/* Free the TX packets of <pkts> list */
Frédéric Lécaille39bde282023-08-29 14:48:54 +02002061static inline __maybe_unused void free_quic_tx_pkts(struct quic_conn *qc, struct list *pkts)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002062{
2063 struct quic_tx_packet *pkt, *tmp;
2064
2065 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
2066
2067 list_for_each_entry_safe(pkt, tmp, pkts, list) {
2068 LIST_DELETE(&pkt->list);
2069 eb64_delete(&pkt->pn_node);
2070 free_quic_tx_packet(qc, pkt);
2071 }
2072
2073 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
2074}
2075
2076/* Remove already sent ranges of acknowledged packet numbers from
2077 * <pktns> packet number space tree below <largest_acked_pn> possibly
2078 * updating the range which contains <largest_acked_pn>.
2079 * Never fails.
2080 */
2081static void qc_treat_ack_of_ack(struct quic_conn *qc,
2082 struct quic_pktns *pktns,
2083 int64_t largest_acked_pn)
2084{
2085 struct eb64_node *ar, *next_ar;
2086 struct quic_arngs *arngs = &pktns->rx.arngs;
2087
2088 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2089
2090 ar = eb64_first(&arngs->root);
2091 while (ar) {
2092 struct quic_arng_node *ar_node;
2093
2094 next_ar = eb64_next(ar);
2095 ar_node = eb64_entry(ar, struct quic_arng_node, first);
2096
2097 if ((int64_t)ar_node->first.key > largest_acked_pn) {
2098 TRACE_DEVEL("first.key > largest", QUIC_EV_CONN_PRSAFRM, qc);
2099 break;
2100 }
2101
2102 if (largest_acked_pn < ar_node->last) {
2103 eb64_delete(ar);
2104 ar_node->first.key = largest_acked_pn + 1;
2105 eb64_insert(&arngs->root, ar);
2106 break;
2107 }
2108
Frédéric Lécaille0dd4fa52023-05-02 08:57:37 +02002109 /* Do not empty the tree: the first ACK range contains the
2110 * largest acknowledged packet number.
2111 */
2112 if (arngs->sz == 1)
2113 break;
2114
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002115 eb64_delete(ar);
2116 pool_free(pool_head_quic_arng, ar_node);
2117 arngs->sz--;
2118 ar = next_ar;
2119 }
2120
2121 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2122}
2123
2124/* Send a packet ack event nofication for each newly acked packet of
2125 * <newly_acked_pkts> list and free them.
2126 * Always succeeds.
2127 */
2128static inline void qc_treat_newly_acked_pkts(struct quic_conn *qc,
2129 struct list *newly_acked_pkts)
2130{
2131 struct quic_tx_packet *pkt, *tmp;
2132 struct quic_cc_event ev = { .type = QUIC_CC_EVT_ACK, };
2133
2134 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2135
2136 list_for_each_entry_safe(pkt, tmp, newly_acked_pkts, list) {
2137 pkt->pktns->tx.in_flight -= pkt->in_flight_len;
2138 qc->path->prep_in_flight -= pkt->in_flight_len;
2139 qc->path->in_flight -= pkt->in_flight_len;
2140 if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
2141 qc->path->ifae_pkts--;
2142 /* If this packet contained an ACK frame, proceed to the
2143 * acknowledging of range of acks from the largest acknowledged
2144 * packet number which was sent in an ACK frame by this packet.
2145 */
2146 if (pkt->largest_acked_pn != -1)
2147 qc_treat_ack_of_ack(qc, pkt->pktns, pkt->largest_acked_pn);
2148 ev.ack.acked = pkt->in_flight_len;
2149 ev.ack.time_sent = pkt->time_sent;
2150 quic_cc_event(&qc->path->cc, &ev);
Frédéric Lécaille39bde282023-08-29 14:48:54 +02002151 LIST_DEL_INIT(&pkt->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002152 quic_tx_packet_refdec(pkt);
2153 }
2154
2155 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2156
2157}
2158
2159/* Release all the frames attached to <pktns> packet number space */
2160static inline void qc_release_pktns_frms(struct quic_conn *qc,
2161 struct quic_pktns *pktns)
2162{
2163 struct quic_frame *frm, *frmbak;
2164
2165 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
2166
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01002167 list_for_each_entry_safe(frm, frmbak, &pktns->tx.frms, list)
2168 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002169
2170 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
2171}
2172
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002173/* Handle <pkts> list of lost packets detected at <now_us> handling their TX
2174 * frames. Send a packet loss event to the congestion controller if in flight
2175 * packet have been lost. Also frees the packet in <pkts> list.
2176 *
2177 * Returns 1 on success else 0 if loss limit has been exceeded. A
2178 * CONNECTION_CLOSE was prepared to close the connection ASAP.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002179 */
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002180static inline int qc_release_lost_pkts(struct quic_conn *qc,
2181 struct quic_pktns *pktns,
2182 struct list *pkts,
2183 uint64_t now_us)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002184{
2185 struct quic_tx_packet *pkt, *tmp, *oldest_lost, *newest_lost;
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002186 int close = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002187
2188 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2189
2190 if (LIST_ISEMPTY(pkts))
2191 goto leave;
2192
2193 oldest_lost = newest_lost = NULL;
2194 list_for_each_entry_safe(pkt, tmp, pkts, list) {
2195 struct list tmp = LIST_HEAD_INIT(tmp);
2196
2197 pkt->pktns->tx.in_flight -= pkt->in_flight_len;
2198 qc->path->prep_in_flight -= pkt->in_flight_len;
2199 qc->path->in_flight -= pkt->in_flight_len;
2200 if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
2201 qc->path->ifae_pkts--;
2202 /* Treat the frames of this lost packet. */
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002203 if (!qc_requeue_nacked_pkt_tx_frms(qc, pkt, &pktns->tx.frms))
2204 close = 1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002205 LIST_DELETE(&pkt->list);
2206 if (!oldest_lost) {
2207 oldest_lost = newest_lost = pkt;
2208 }
2209 else {
2210 if (newest_lost != oldest_lost)
2211 quic_tx_packet_refdec(newest_lost);
2212 newest_lost = pkt;
2213 }
2214 }
2215
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002216 if (!close) {
2217 if (newest_lost) {
2218 /* Sent a congestion event to the controller */
2219 struct quic_cc_event ev = { };
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002220
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002221 ev.type = QUIC_CC_EVT_LOSS;
2222 ev.loss.time_sent = newest_lost->time_sent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002223
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002224 quic_cc_event(&qc->path->cc, &ev);
2225 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002226
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002227 /* If an RTT have been already sampled, <rtt_min> has been set.
2228 * We must check if we are experiencing a persistent congestion.
2229 * If this is the case, the congestion controller must re-enter
2230 * slow start state.
2231 */
2232 if (qc->path->loss.rtt_min && newest_lost != oldest_lost) {
2233 unsigned int period = newest_lost->time_sent - oldest_lost->time_sent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002234
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002235 if (quic_loss_persistent_congestion(&qc->path->loss, period,
2236 now_ms, qc->max_ack_delay))
2237 qc->path->cc.algo->slow_start(&qc->path->cc);
2238 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002239 }
2240
Amaury Denoyelle3a72ba22022-11-14 11:41:34 +01002241 /* <oldest_lost> cannot be NULL at this stage because we have ensured
2242 * that <pkts> list is not empty. Without this, GCC 12.2.0 reports a
2243 * possible overflow on a 0 byte region with O2 optimization.
2244 */
2245 ALREADY_CHECKED(oldest_lost);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002246 quic_tx_packet_refdec(oldest_lost);
2247 if (newest_lost != oldest_lost)
2248 quic_tx_packet_refdec(newest_lost);
2249
2250 leave:
2251 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002252 return !close;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002253}
2254
2255/* Parse ACK frame into <frm> from a buffer at <buf> address with <end> being at
2256 * one byte past the end of this buffer. Also update <rtt_sample> if needed, i.e.
2257 * if the largest acked packet was newly acked and if there was at least one newly
2258 * acked ack-eliciting packet.
2259 * Return 1, if succeeded, 0 if not.
2260 */
2261static inline int qc_parse_ack_frm(struct quic_conn *qc,
2262 struct quic_frame *frm,
2263 struct quic_enc_level *qel,
2264 unsigned int *rtt_sample,
2265 const unsigned char **pos, const unsigned char *end)
2266{
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002267 struct qf_ack *ack_frm = &frm->ack;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002268 uint64_t smallest, largest;
2269 struct eb_root *pkts;
2270 struct eb64_node *largest_node;
2271 unsigned int time_sent, pkt_flags;
2272 struct list newly_acked_pkts = LIST_HEAD_INIT(newly_acked_pkts);
2273 struct list lost_pkts = LIST_HEAD_INIT(lost_pkts);
Frédéric Lécaillef078d782023-08-29 11:01:19 +02002274 int ret = 0, new_largest_acked_pn = 0;
Frédéric Lécaille39bde282023-08-29 14:48:54 +02002275 struct quic_tx_packet *pkt, *tmp;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002276
2277 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2278
Frédéric Lécaille39bde282023-08-29 14:48:54 +02002279 pkts = &qel->pktns->tx.pkts;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002280 if (ack_frm->largest_ack > qel->pktns->tx.next_pn) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002281 TRACE_DEVEL("ACK for not sent packet", QUIC_EV_CONN_PRSAFRM,
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002282 qc, NULL, &ack_frm->largest_ack);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002283 goto err;
2284 }
2285
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002286 if (ack_frm->first_ack_range > ack_frm->largest_ack) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002287 TRACE_DEVEL("too big first ACK range", QUIC_EV_CONN_PRSAFRM,
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002288 qc, NULL, &ack_frm->first_ack_range);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002289 goto err;
2290 }
2291
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002292 largest = ack_frm->largest_ack;
2293 smallest = largest - ack_frm->first_ack_range;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002294 pkt_flags = 0;
2295 largest_node = NULL;
2296 time_sent = 0;
2297
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002298 if ((int64_t)ack_frm->largest_ack > qel->pktns->rx.largest_acked_pn) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002299 largest_node = eb64_lookup(pkts, largest);
2300 if (!largest_node) {
2301 TRACE_DEVEL("Largest acked packet not found",
2302 QUIC_EV_CONN_PRSAFRM, qc);
2303 }
2304 else {
2305 time_sent = eb64_entry(largest_node,
2306 struct quic_tx_packet, pn_node)->time_sent;
Frédéric Lécaillef078d782023-08-29 11:01:19 +02002307 new_largest_acked_pn = 1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002308 }
2309 }
2310
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002311 TRACE_PROTO("RX ack range", QUIC_EV_CONN_PRSAFRM,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002312 qc, NULL, &largest, &smallest);
2313 do {
2314 uint64_t gap, ack_range;
2315
Frédéric Lécaille39bde282023-08-29 14:48:54 +02002316 qc_newly_acked_pkts(qc, pkts, &newly_acked_pkts,
2317 largest_node, largest, smallest);
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002318 if (!ack_frm->ack_range_num--)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002319 break;
2320
2321 if (!quic_dec_int(&gap, pos, end)) {
2322 TRACE_ERROR("quic_dec_int(gap) failed", QUIC_EV_CONN_PRSAFRM, qc);
2323 goto err;
2324 }
2325
2326 if (smallest < gap + 2) {
2327 TRACE_DEVEL("wrong gap value", QUIC_EV_CONN_PRSAFRM,
2328 qc, NULL, &gap, &smallest);
2329 goto err;
2330 }
2331
2332 largest = smallest - gap - 2;
2333 if (!quic_dec_int(&ack_range, pos, end)) {
2334 TRACE_ERROR("quic_dec_int(ack_range) failed", QUIC_EV_CONN_PRSAFRM, qc);
2335 goto err;
2336 }
2337
2338 if (largest < ack_range) {
2339 TRACE_DEVEL("wrong ack range value", QUIC_EV_CONN_PRSAFRM,
2340 qc, NULL, &largest, &ack_range);
2341 goto err;
2342 }
2343
2344 /* Do not use this node anymore. */
2345 largest_node = NULL;
2346 /* Next range */
2347 smallest = largest - ack_range;
2348
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002349 TRACE_PROTO("RX next ack range", QUIC_EV_CONN_PRSAFRM,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002350 qc, NULL, &largest, &smallest);
2351 } while (1);
2352
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002353 if (!LIST_ISEMPTY(&newly_acked_pkts)) {
Frédéric Lécaille39bde282023-08-29 14:48:54 +02002354 qc_ackrng_pkts(qc, &pkt_flags, &newly_acked_pkts);
2355 if (new_largest_acked_pn && (pkt_flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
2356 *rtt_sample = tick_remain(time_sent, now_ms);
2357 qel->pktns->rx.largest_acked_pn = ack_frm->largest_ack;
2358 }
2359
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002360 if (!eb_is_empty(&qel->pktns->tx.pkts)) {
2361 qc_packet_loss_lookup(qel->pktns, qc, &lost_pkts);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01002362 if (!qc_release_lost_pkts(qc, qel->pktns, &lost_pkts, now_ms))
2363 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002364 }
2365 qc_treat_newly_acked_pkts(qc, &newly_acked_pkts);
2366 if (quic_peer_validated_addr(qc))
2367 qc->path->loss.pto_count = 0;
2368 qc_set_timer(qc);
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01002369 qc_notify_send(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002370 }
2371
2372 ret = 1;
2373 leave:
2374 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2375 return ret;
2376
2377 err:
Frédéric Lécaille39bde282023-08-29 14:48:54 +02002378 /* Move back these packets into their tree. */
2379 list_for_each_entry_safe(pkt, tmp, &newly_acked_pkts, list) {
2380 LIST_DEL_INIT(&pkt->list);
2381 eb64_insert(pkts, &pkt->pn_node);
2382 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002383 goto leave;
2384}
2385
2386/* This function gives the detail of the SSL error. It is used only
2387 * if the debug mode and the verbose mode are activated. It dump all
2388 * the SSL error until the stack was empty.
2389 */
2390static forceinline void qc_ssl_dump_errors(struct connection *conn)
2391{
2392 if (unlikely(global.mode & MODE_DEBUG)) {
2393 while (1) {
2394 const char *func = NULL;
2395 unsigned long ret;
2396
2397 ERR_peek_error_func(&func);
2398 ret = ERR_get_error();
2399 if (!ret)
2400 return;
2401
2402 fprintf(stderr, "conn. @%p OpenSSL error[0x%lx] %s: %s\n", conn, ret,
2403 func, ERR_reason_error_string(ret));
2404 }
2405 }
2406}
2407
2408int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx,
2409 const char **str, int *len);
2410
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002411/* Finalize <qc> QUIC connection:
2412 * - initialize the Initial QUIC TLS context for negotiated version,
2413 * - derive the secrets for this context,
2414 * - set them into the TLS stack,
2415 *
2416 * MUST be called after having received the remote transport parameters which
2417 * are parsed when the TLS callback for the ClientHello message is called upon
2418 * SSL_do_handshake() calls, not necessarily at the first time as this TLS
Ilya Shipitsin07be66d2023-04-01 12:26:42 +02002419 * message may be split between packets
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002420 * Return 1 if succeeded, 0 if not.
2421 */
2422static int qc_conn_finalize(struct quic_conn *qc, int server)
2423{
2424 int ret = 0;
2425
2426 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
2427
2428 if (qc->flags & QUIC_FL_CONN_FINALIZED)
2429 goto finalized;
2430
2431 if (qc->negotiated_version &&
2432 !qc_new_isecs(qc, &qc->negotiated_ictx, qc->negotiated_version,
2433 qc->odcid.data, qc->odcid.len, server))
2434 goto out;
2435
2436 /* This connection is functional (ready to send/receive) */
2437 qc->flags |= QUIC_FL_CONN_FINALIZED;
2438
2439 finalized:
2440 ret = 1;
2441 out:
2442 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
2443 return ret;
2444}
2445
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002446/* Provide CRYPTO data to the TLS stack found at <data> with <len> as length
2447 * from <qel> encryption level with <ctx> as QUIC connection context.
2448 * Remaining parameter are there for debugging purposes.
2449 * Return 1 if succeeded, 0 if not.
2450 */
2451static inline int qc_provide_cdata(struct quic_enc_level *el,
2452 struct ssl_sock_ctx *ctx,
2453 const unsigned char *data, size_t len,
2454 struct quic_rx_packet *pkt,
2455 struct quic_rx_crypto_frm *cf)
2456{
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01002457#ifdef DEBUG_STRICT
2458 enum ncb_ret ncb_ret;
2459#endif
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002460 int ssl_err, state;
2461 struct quic_conn *qc;
2462 int ret = 0;
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002463 struct ncbuf *ncbuf = &el->cstream->rx.ncbuf;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002464
2465 ssl_err = SSL_ERROR_NONE;
2466 qc = ctx->qc;
2467
2468 TRACE_ENTER(QUIC_EV_CONN_SSLDATA, qc);
2469
2470 if (SSL_provide_quic_data(ctx->ssl, el->level, data, len) != 1) {
2471 TRACE_ERROR("SSL_provide_quic_data() error",
2472 QUIC_EV_CONN_SSLDATA, qc, pkt, cf, ctx->ssl);
2473 goto leave;
2474 }
2475
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002476 TRACE_PROTO("in order CRYPTO data",
2477 QUIC_EV_CONN_SSLDATA, qc, NULL, cf, ctx->ssl);
2478
2479 state = qc->state;
2480 if (state < QUIC_HS_ST_COMPLETE) {
2481 ssl_err = SSL_do_handshake(ctx->ssl);
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002482
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01002483 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
2484 TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_IO_CB, qc);
2485 goto leave;
2486 }
2487
Frédéric Lécailleaf25a692023-02-01 17:56:57 +01002488 /* Finalize the connection as soon as possible if the peer transport parameters
2489 * have been received. This may be useful to send packets even if this
2490 * handshake fails.
2491 */
2492 if ((qc->flags & QUIC_FL_CONN_TX_TP_RECEIVED) && !qc_conn_finalize(qc, 1)) {
2493 TRACE_ERROR("connection finalization failed", QUIC_EV_CONN_IO_CB, qc, &state);
2494 goto leave;
2495 }
2496
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002497 if (ssl_err != 1) {
2498 ssl_err = SSL_get_error(ctx->ssl, ssl_err);
2499 if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
2500 TRACE_PROTO("SSL handshake in progress",
2501 QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2502 goto out;
2503 }
2504
2505 /* TODO: Should close the connection asap */
2506 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
2507 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
2508 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
2509 HA_ATOMIC_INC(&qc->prx_counters->hdshk_fail);
2510 }
2511 TRACE_ERROR("SSL handshake error", QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2512 qc_ssl_dump_errors(ctx->conn);
2513 ERR_clear_error();
2514 goto leave;
2515 }
2516
2517 TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
2518
2519 /* Check the alpn could be negotiated */
2520 if (!qc->app_ops) {
2521 TRACE_ERROR("No negotiated ALPN", QUIC_EV_CONN_IO_CB, qc, &state);
2522 quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL);
2523 goto leave;
2524 }
2525
2526 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
2527 TRACE_DEVEL("dec half open counter", QUIC_EV_CONN_IO_CB, qc, &state);
2528 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
2529 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
2530 }
2531 /* I/O callback switch */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02002532 qc->wait_event.tasklet->process = quic_conn_app_io_cb;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002533 if (qc_is_listener(ctx->qc)) {
Amaury Denoyelle1304d192023-04-11 16:46:03 +02002534 qc->flags |= QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002535 qc->state = QUIC_HS_ST_CONFIRMED;
2536 /* The connection is ready to be accepted. */
2537 quic_accept_push_qc(qc);
2538 }
2539 else {
2540 qc->state = QUIC_HS_ST_COMPLETE;
2541 }
2542
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02002543 /* Prepare the next key update */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002544 if (!quic_tls_key_update(qc)) {
2545 TRACE_ERROR("quic_tls_key_update() failed", QUIC_EV_CONN_IO_CB, qc);
2546 goto leave;
2547 }
2548 } else {
2549 ssl_err = SSL_process_quic_post_handshake(ctx->ssl);
2550 if (ssl_err != 1) {
2551 ssl_err = SSL_get_error(ctx->ssl, ssl_err);
2552 if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
2553 TRACE_PROTO("SSL post handshake in progress",
2554 QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2555 goto out;
2556 }
2557
2558 TRACE_ERROR("SSL post handshake error",
2559 QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
2560 goto leave;
2561 }
2562
2563 TRACE_STATE("SSL post handshake succeeded", QUIC_EV_CONN_IO_CB, qc, &state);
2564 }
2565
2566 out:
2567 ret = 1;
2568 leave:
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002569 /* The CRYPTO data are consumed even in case of an error to release
2570 * the memory asap.
2571 */
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01002572 if (!ncb_is_null(ncbuf)) {
2573#ifdef DEBUG_STRICT
2574 ncb_ret = ncb_advance(ncbuf, len);
2575 /* ncb_advance() must always succeed. This is guaranteed as
2576 * this is only done inside a data block. If false, this will
2577 * lead to handshake failure with quic_enc_level offset shifted
2578 * from buffer data.
2579 */
2580 BUG_ON(ncb_ret != NCB_RET_OK);
2581#else
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002582 ncb_advance(ncbuf, len);
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01002583#endif
2584 }
2585
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002586 TRACE_LEAVE(QUIC_EV_CONN_SSLDATA, qc);
2587 return ret;
2588}
2589
Amaury Denoyelle2216b082023-02-02 14:59:36 +01002590/* Parse a STREAM frame <strm_frm> received in <pkt> packet for <qc>
2591 * connection. <fin> is true if FIN bit is set on frame type.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002592 *
2593 * Return 1 on success. On error, 0 is returned. In this case, the packet
2594 * containing the frame must not be acknowledged.
2595 */
2596static inline int qc_handle_strm_frm(struct quic_rx_packet *pkt,
Amaury Denoyelle888c5f22023-04-24 14:26:30 +02002597 struct qf_stream *strm_frm,
Amaury Denoyelle2216b082023-02-02 14:59:36 +01002598 struct quic_conn *qc, char fin)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002599{
2600 int ret;
2601
2602 /* RFC9000 13.1. Packet Processing
2603 *
2604 * A packet MUST NOT be acknowledged until packet protection has been
2605 * successfully removed and all frames contained in the packet have
2606 * been processed. For STREAM frames, this means the data has been
2607 * enqueued in preparation to be received by the application protocol,
2608 * but it does not require that data be delivered and consumed.
2609 */
2610 TRACE_ENTER(QUIC_EV_CONN_PRSFRM, qc);
2611
2612 ret = qcc_recv(qc->qcc, strm_frm->id, strm_frm->len,
Amaury Denoyelle2216b082023-02-02 14:59:36 +01002613 strm_frm->offset.key, fin, (char *)strm_frm->data);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002614
2615 /* frame rejected - packet must not be acknowledeged */
2616 TRACE_LEAVE(QUIC_EV_CONN_PRSFRM, qc);
2617 return !ret;
2618}
2619
2620/* Duplicate all frames from <pkt_frm_list> list into <out_frm_list> list
2621 * for <qc> QUIC connection.
2622 * This is a best effort function which never fails even if no memory could be
2623 * allocated to duplicate these frames.
2624 */
2625static void qc_dup_pkt_frms(struct quic_conn *qc,
2626 struct list *pkt_frm_list, struct list *out_frm_list)
2627{
2628 struct quic_frame *frm, *frmbak;
2629 struct list tmp = LIST_HEAD_INIT(tmp);
2630
2631 TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
2632
2633 list_for_each_entry_safe(frm, frmbak, pkt_frm_list, list) {
2634 struct quic_frame *dup_frm, *origin;
2635
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002636 if (frm->flags & QUIC_FL_TX_FRAME_ACKED) {
2637 TRACE_DEVEL("already acknowledged frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
2638 continue;
2639 }
2640
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002641 switch (frm->type) {
2642 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
2643 {
Amaury Denoyelle888c5f22023-04-24 14:26:30 +02002644 struct qf_stream *strm_frm = &frm->stream;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002645 struct eb64_node *node = NULL;
2646 struct qc_stream_desc *stream_desc;
2647
2648 node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
2649 if (!node) {
2650 TRACE_DEVEL("ignored frame for a released stream", QUIC_EV_CONN_PRSAFRM, qc, frm);
2651 continue;
2652 }
2653
2654 stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
2655 /* Do not resend this frame if in the "already acked range" */
2656 if (strm_frm->offset.key + strm_frm->len <= stream_desc->ack_offset) {
2657 TRACE_DEVEL("ignored frame in already acked range",
2658 QUIC_EV_CONN_PRSAFRM, qc, frm);
2659 continue;
2660 }
2661 else if (strm_frm->offset.key < stream_desc->ack_offset) {
Frédéric Lécailleca079792023-03-17 08:56:50 +01002662 uint64_t diff = stream_desc->ack_offset - strm_frm->offset.key;
2663
Frédéric Lécaillec425e032023-03-20 14:32:59 +01002664 qc_stream_frm_mv_fwd(frm, diff);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002665 TRACE_DEVEL("updated partially acked frame",
2666 QUIC_EV_CONN_PRSAFRM, qc, frm);
2667 }
Amaury Denoyellec8a0efb2023-02-22 10:44:27 +01002668
2669 strm_frm->dup = 1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002670 break;
2671 }
2672
2673 default:
2674 break;
2675 }
2676
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002677 /* If <frm> is already a copy of another frame, we must take
2678 * its original frame as source for the copy.
2679 */
2680 origin = frm->origin ? frm->origin : frm;
2681 dup_frm = qc_frm_dup(origin);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002682 if (!dup_frm) {
2683 TRACE_ERROR("could not duplicate frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
2684 break;
2685 }
2686
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002687 TRACE_DEVEL("built probing frame", QUIC_EV_CONN_PRSAFRM, qc, origin);
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002688 if (origin->pkt) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002689 TRACE_DEVEL("duplicated from packet", QUIC_EV_CONN_PRSAFRM,
2690 qc, NULL, &origin->pkt->pn_node.key);
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002691 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002692 else {
2693 /* <origin> is a frame which was sent from a packet detected as lost. */
2694 TRACE_DEVEL("duplicated from lost packet", QUIC_EV_CONN_PRSAFRM, qc);
2695 }
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01002696
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002697 LIST_APPEND(&tmp, &dup_frm->list);
2698 }
2699
2700 LIST_SPLICE(out_frm_list, &tmp);
2701
2702 TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
2703}
2704
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002705/* Boolean function which return 1 if <pkt> TX packet is only made of
2706 * already acknowledged frame.
2707 */
2708static inline int qc_pkt_with_only_acked_frms(struct quic_tx_packet *pkt)
2709{
2710 struct quic_frame *frm;
2711
2712 list_for_each_entry(frm, &pkt->frms, list)
2713 if (!(frm->flags & QUIC_FL_TX_FRAME_ACKED))
2714 return 0;
2715
2716 return 1;
2717}
2718
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002719/* Prepare a fast retransmission from <qel> encryption level */
2720static void qc_prep_fast_retrans(struct quic_conn *qc,
2721 struct quic_enc_level *qel,
2722 struct list *frms1, struct list *frms2)
2723{
2724 struct eb_root *pkts = &qel->pktns->tx.pkts;
2725 struct list *frms = frms1;
2726 struct eb64_node *node;
2727 struct quic_tx_packet *pkt;
2728
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002729 TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002730
2731 BUG_ON(frms1 == frms2);
2732
2733 pkt = NULL;
2734 node = eb64_first(pkts);
2735 start:
2736 while (node) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002737 struct quic_tx_packet *p;
2738
2739 p = eb64_entry(node, struct quic_tx_packet, pn_node);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002740 node = eb64_next(node);
2741 /* Skip the empty and coalesced packets */
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002742 TRACE_PRINTF(TRACE_LEVEL_PROTO, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002743 "--> pn=%llu (%d %d %d)", (ull)p->pn_node.key,
2744 LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED),
2745 qc_pkt_with_only_acked_frms(p));
2746 if (!LIST_ISEMPTY(&p->frms) && !qc_pkt_with_only_acked_frms(p)) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002747 pkt = p;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002748 break;
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002749 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002750 }
2751
2752 if (!pkt)
2753 goto leave;
2754
2755 /* When building a packet from another one, the field which may increase the
2756 * packet size is the packet number. And the maximum increase is 4 bytes.
2757 */
2758 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc) &&
2759 pkt->len + 4 > 3 * qc->rx.bytes - qc->tx.prep_bytes) {
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01002760 qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002761 TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt);
2762 goto leave;
2763 }
2764
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002765 TRACE_PROTO("duplicating packet", QUIC_EV_CONN_SPPKTS, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002766 qc_dup_pkt_frms(qc, &pkt->frms, frms);
2767 if (frms == frms1 && frms2) {
2768 frms = frms2;
2769 goto start;
2770 }
2771 leave:
2772 TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
2773}
2774
2775/* Prepare a fast retransmission during a handshake after a client
2776 * has resent Initial packets. According to the RFC a server may retransmit
2777 * Initial packets send them coalescing with others (Handshake here).
2778 * (Listener only function).
2779 */
2780static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc,
2781 struct list *ifrms, struct list *hfrms)
2782{
2783 struct list itmp = LIST_HEAD_INIT(itmp);
2784 struct list htmp = LIST_HEAD_INIT(htmp);
2785
2786 struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
2787 struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
2788 struct quic_enc_level *qel = iqel;
2789 struct eb_root *pkts;
2790 struct eb64_node *node;
2791 struct quic_tx_packet *pkt;
2792 struct list *tmp = &itmp;
2793
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002794 TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002795 start:
2796 pkt = NULL;
2797 pkts = &qel->pktns->tx.pkts;
2798 node = eb64_first(pkts);
2799 /* Skip the empty packet (they have already been retransmitted) */
2800 while (node) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002801 struct quic_tx_packet *p;
2802
2803 p = eb64_entry(node, struct quic_tx_packet, pn_node);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002804 TRACE_PRINTF(TRACE_LEVEL_PROTO, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002805 "--> pn=%llu (%d %d)", (ull)p->pn_node.key,
2806 LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED));
Frédéric Lécaillee6359b62023-03-02 14:49:22 +01002807 if (!LIST_ISEMPTY(&p->frms) && !(p->flags & QUIC_FL_TX_PACKET_COALESCED) &&
2808 !qc_pkt_with_only_acked_frms(p)) {
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002809 pkt = p;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002810 break;
Frédéric Lécaille21564be2023-03-02 11:53:43 +01002811 }
2812
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002813 node = eb64_next(node);
2814 }
2815
2816 if (!pkt)
2817 goto end;
2818
2819 /* When building a packet from another one, the field which may increase the
2820 * packet size is the packet number. And the maximum increase is 4 bytes.
2821 */
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002822 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
2823 size_t dglen = pkt->len + 4;
2824
2825 dglen += pkt->next ? pkt->next->len + 4 : 0;
2826 if (dglen > 3 * qc->rx.bytes - qc->tx.prep_bytes) {
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01002827 qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002828 TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt);
2829 if (pkt->next)
2830 TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt->next);
2831 goto end;
2832 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002833 }
2834
2835 qel->pktns->tx.pto_probe += 1;
2836
2837 /* No risk to loop here, #packet per datagram is bounded */
2838 requeue:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01002839 TRACE_PROTO("duplicating packet", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002840 qc_dup_pkt_frms(qc, &pkt->frms, tmp);
2841 if (qel == iqel) {
2842 if (pkt->next && pkt->next->type == QUIC_PACKET_TYPE_HANDSHAKE) {
2843 pkt = pkt->next;
2844 tmp = &htmp;
2845 hqel->pktns->tx.pto_probe += 1;
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002846 TRACE_DEVEL("looping for next packet", QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002847 goto requeue;
2848 }
2849 }
2850
2851 end:
2852 LIST_SPLICE(ifrms, &itmp);
2853 LIST_SPLICE(hfrms, &htmp);
2854
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01002855 TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002856}
2857
2858static void qc_cc_err_count_inc(struct quic_conn *qc, struct quic_frame *frm)
2859{
2860 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
2861
2862 if (frm->type == QUIC_FT_CONNECTION_CLOSE)
2863 quic_stats_transp_err_count_inc(qc->prx_counters, frm->connection_close.error_code);
2864 else if (frm->type == QUIC_FT_CONNECTION_CLOSE_APP) {
2865 if (qc->mux_state != QC_MUX_READY || !qc->qcc->app_ops->inc_err_cnt)
2866 goto out;
2867
2868 qc->qcc->app_ops->inc_err_cnt(qc->qcc->ctx, frm->connection_close_app.error_code);
2869 }
2870
2871 out:
2872 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
2873}
2874
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002875/* Cancel a request on connection <qc> for stream id <id>. This is useful when
2876 * the client opens a new stream but the MUX has already been released. A
Amaury Denoyelle75463012023-02-20 10:31:27 +01002877 * STOP_SENDING + RESET_STREAM frames are prepared for emission.
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002878 *
2879 * TODO this function is closely related to H3. Its place should be in H3 layer
2880 * instead of quic-conn but this requires an architecture adjustment.
2881 *
Ilya Shipitsin07be66d2023-04-01 12:26:42 +02002882 * Returns 1 on success else 0.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002883 */
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002884static int qc_h3_request_reject(struct quic_conn *qc, uint64_t id)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002885{
2886 int ret = 0;
Amaury Denoyelle75463012023-02-20 10:31:27 +01002887 struct quic_frame *ss, *rs;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002888 struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002889 const uint64_t app_error_code = H3_REQUEST_REJECTED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002890
2891 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2892
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002893 /* Do not emit rejection for unknown unidirectional stream as it is
2894 * forbidden to close some of them (H3 control stream and QPACK
2895 * encoder/decoder streams).
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002896 */
Amaury Denoyelle38836b62023-02-07 14:24:54 +01002897 if (quic_stream_is_uni(id)) {
2898 ret = 1;
2899 goto out;
2900 }
2901
Amaury Denoyelle75463012023-02-20 10:31:27 +01002902 ss = qc_frm_alloc(QUIC_FT_STOP_SENDING);
2903 if (!ss) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002904 TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
2905 goto out;
2906 }
2907
Amaury Denoyelle75463012023-02-20 10:31:27 +01002908 ss->stop_sending.id = id;
2909 ss->stop_sending.app_error_code = app_error_code;
2910
2911 rs = qc_frm_alloc(QUIC_FT_RESET_STREAM);
2912 if (!rs) {
2913 TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
2914 qc_frm_free(&ss);
2915 goto out;
2916 }
2917
2918 rs->reset_stream.id = id;
2919 rs->reset_stream.app_error_code = app_error_code;
2920 rs->reset_stream.final_size = 0;
2921
2922 LIST_APPEND(&qel->pktns->tx.frms, &ss->list);
2923 LIST_APPEND(&qel->pktns->tx.frms, &rs->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02002924 ret = 1;
2925 out:
2926 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2927 return ret;
2928}
2929
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002930/* Release the underlying memory use by <ncbuf> non-contiguous buffer */
2931static void quic_free_ncbuf(struct ncbuf *ncbuf)
2932{
2933 struct buffer buf;
2934
2935 if (ncb_is_null(ncbuf))
2936 return;
2937
2938 buf = b_make(ncbuf->area, ncbuf->size, 0, 0);
2939 b_free(&buf);
2940 offer_buffers(NULL, 1);
2941
2942 *ncbuf = NCBUF_NULL;
2943}
2944
2945/* Allocate the underlying required memory for <ncbuf> non-contiguous buffer */
2946static struct ncbuf *quic_get_ncbuf(struct ncbuf *ncbuf)
2947{
2948 struct buffer buf = BUF_NULL;
2949
2950 if (!ncb_is_null(ncbuf))
2951 return ncbuf;
2952
2953 b_alloc(&buf);
2954 BUG_ON(b_is_null(&buf));
2955
2956 *ncbuf = ncb_make(buf.area, buf.size, 0);
2957 ncb_init(ncbuf, 0);
2958
2959 return ncbuf;
2960}
2961
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002962/* Parse <frm> CRYPTO frame coming with <pkt> packet at <qel> <qc> connectionn.
2963 * Returns 1 if succeeded, 0 if not. Also set <*fast_retrans> to 1 if the
2964 * speed up handshake completion may be run after having received duplicated
2965 * CRYPTO data.
2966 */
2967static int qc_handle_crypto_frm(struct quic_conn *qc,
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002968 struct qf_crypto *crypto_frm, struct quic_rx_packet *pkt,
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002969 struct quic_enc_level *qel, int *fast_retrans)
2970{
2971 int ret = 0;
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002972 enum ncb_ret ncb_ret;
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002973 /* XXX TO DO: <cfdebug> is used only for the traces. */
2974 struct quic_rx_crypto_frm cfdebug = {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002975 .offset_node.key = crypto_frm->offset,
2976 .len = crypto_frm->len,
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002977 };
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02002978 struct quic_cstream *cstream = qel->cstream;
2979 struct ncbuf *ncbuf = &qel->cstream->rx.ncbuf;
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002980
2981 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2982 if (unlikely(qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD)) {
2983 TRACE_PROTO("CRYPTO data discarded",
2984 QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2985 goto done;
2986 }
2987
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002988 if (unlikely(crypto_frm->offset < cstream->rx.offset)) {
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002989 size_t diff;
2990
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02002991 if (crypto_frm->offset + crypto_frm->len <= cstream->rx.offset) {
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02002992 /* Nothing to do */
2993 TRACE_PROTO("Already received CRYPTO data",
2994 QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2995 if (qc_is_listener(qc) && qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] &&
2996 !(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP))
2997 *fast_retrans = 1;
2998 goto done;
2999 }
3000
3001 TRACE_PROTO("Partially already received CRYPTO data",
3002 QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
3003
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003004 diff = cstream->rx.offset - crypto_frm->offset;
3005 crypto_frm->len -= diff;
3006 crypto_frm->data += diff;
3007 crypto_frm->offset = cstream->rx.offset;
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02003008 }
3009
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003010 if (crypto_frm->offset == cstream->rx.offset && ncb_is_empty(ncbuf)) {
3011 if (!qc_provide_cdata(qel, qc->xprt_ctx, crypto_frm->data, crypto_frm->len,
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02003012 pkt, &cfdebug)) {
3013 // trace already emitted by function above
3014 goto leave;
3015 }
3016
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003017 cstream->rx.offset += crypto_frm->len;
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01003018 TRACE_DEVEL("increment crypto level offset", QUIC_EV_CONN_PHPKTS, qc, qel);
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02003019 goto done;
3020 }
3021
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02003022 if (!quic_get_ncbuf(ncbuf) ||
3023 ncb_is_null(ncbuf)) {
3024 TRACE_ERROR("CRYPTO ncbuf allocation failed", QUIC_EV_CONN_PRSHPKT, qc);
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02003025 goto leave;
3026 }
3027
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003028 /* crypto_frm->offset > cstream-trx.offset */
3029 ncb_ret = ncb_add(ncbuf, crypto_frm->offset - cstream->rx.offset,
3030 (const char *)crypto_frm->data, crypto_frm->len, NCB_ADD_COMPARE);
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02003031 if (ncb_ret != NCB_RET_OK) {
3032 if (ncb_ret == NCB_RET_DATA_REJ) {
3033 TRACE_ERROR("overlapping data rejected", QUIC_EV_CONN_PRSHPKT, qc);
3034 quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02003035 qc_notify_err(qc);
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02003036 }
3037 else if (ncb_ret == NCB_RET_GAP_SIZE) {
3038 TRACE_ERROR("cannot bufferize frame due to gap size limit",
3039 QUIC_EV_CONN_PRSHPKT, qc);
3040 }
3041 goto leave;
3042 }
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02003043
3044 done:
3045 ret = 1;
3046 leave:
3047 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
3048 return ret;
3049}
3050
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003051/* Build a NEW_CONNECTION_ID frame for <conn_id> CID of <qc> connection.
3052 *
3053 * Returns 1 on success else 0.
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003054 */
3055static int qc_build_new_connection_id_frm(struct quic_conn *qc,
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003056 struct quic_connection_id *conn_id)
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003057{
3058 int ret = 0;
3059 struct quic_frame *frm;
3060 struct quic_enc_level *qel;
3061
3062 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
3063
3064 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
3065 frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID);
3066 if (!frm) {
3067 TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
3068 goto leave;
3069 }
3070
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003071 quic_connection_id_to_frm_cpy(frm, conn_id);
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003072 LIST_APPEND(&qel->pktns->tx.frms, &frm->list);
3073 ret = 1;
3074 leave:
3075 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
3076 return ret;
3077}
3078
3079
3080/* Handle RETIRE_CONNECTION_ID frame from <frm> frame.
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003081 * Return 1 if succeeded, 0 if not. If succeeded, also set <to_retire>
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003082 * to the CID to be retired if not already retired.
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003083 */
3084static int qc_handle_retire_connection_id_frm(struct quic_conn *qc,
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003085 struct quic_frame *frm,
3086 struct quic_cid *dcid,
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003087 struct quic_connection_id **to_retire)
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003088{
3089 int ret = 0;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003090 struct qf_retire_connection_id *rcid_frm = &frm->retire_connection_id;
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003091 struct eb64_node *node;
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003092 struct quic_connection_id *conn_id;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003093
3094 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
3095
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003096 /* RFC 9000 19.16. RETIRE_CONNECTION_ID Frames:
3097 * Receipt of a RETIRE_CONNECTION_ID frame containing a sequence number greater
3098 * than any previously sent to the peer MUST be treated as a connection error
3099 * of type PROTOCOL_VIOLATION.
3100 */
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003101 if (rcid_frm->seq_num >= qc->next_cid_seq_num) {
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003102 TRACE_PROTO("CID seq. number too big", QUIC_EV_CONN_PSTRM, qc, frm);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003103 goto protocol_violation;
3104 }
3105
3106 /* RFC 9000 19.16. RETIRE_CONNECTION_ID Frames:
3107 * The sequence number specified in a RETIRE_CONNECTION_ID frame MUST NOT refer to
3108 * the Destination Connection ID field of the packet in which the frame is contained.
3109 * The peer MAY treat this as a connection error of type PROTOCOL_VIOLATION.
3110 */
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003111 node = eb64_lookup(&qc->cids, rcid_frm->seq_num);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003112 if (!node) {
3113 TRACE_PROTO("CID already retired", QUIC_EV_CONN_PSTRM, qc, frm);
3114 goto out;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003115 }
3116
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003117 conn_id = eb64_entry(node, struct quic_connection_id, seq_num);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003118 /* Note that the length of <dcid> has already been checked. It must match the
3119 * length of the CIDs which have been provided to the peer.
3120 */
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003121 if (!memcmp(dcid->data, conn_id->cid.data, QUIC_HAP_CID_LEN)) {
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003122 TRACE_PROTO("cannot retire the current CID", QUIC_EV_CONN_PSTRM, qc, frm);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003123 goto protocol_violation;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003124 }
3125
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003126 *to_retire = conn_id;
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003127 out:
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003128 ret = 1;
3129 leave:
3130 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
3131 return ret;
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003132 protocol_violation:
3133 quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02003134 qc_notify_err(qc);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003135 goto leave;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003136}
3137
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01003138/* Remove a <qc> quic-conn from its ha_thread_ctx list. If <closing> is true,
3139 * it will immediately be reinserted in the ha_thread_ctx quic_conns_clo list.
3140 */
3141static void qc_detach_th_ctx_list(struct quic_conn *qc, int closing)
3142{
3143 struct bref *bref, *back;
3144
3145 /* Detach CLI context watchers currently dumping this connection.
3146 * Reattach them to the next quic_conn instance.
3147 */
3148 list_for_each_entry_safe(bref, back, &qc->back_refs, users) {
3149 /* Remove watcher from this quic_conn instance. */
3150 LIST_DEL_INIT(&bref->users);
3151
3152 /* Attach it to next instance unless it was the last list element. */
3153 if (qc->el_th_ctx.n != &th_ctx->quic_conns &&
3154 qc->el_th_ctx.n != &th_ctx->quic_conns_clo) {
3155 struct quic_conn *next = LIST_NEXT(&qc->el_th_ctx,
3156 struct quic_conn *,
3157 el_th_ctx);
3158 LIST_APPEND(&next->back_refs, &bref->users);
3159 }
3160 bref->ref = qc->el_th_ctx.n;
3161 __ha_barrier_store();
3162 }
3163
3164 /* Remove quic_conn from global ha_thread_ctx list. */
3165 LIST_DEL_INIT(&qc->el_th_ctx);
3166
3167 if (closing)
3168 LIST_APPEND(&th_ctx->quic_conns_clo, &qc->el_th_ctx);
3169}
3170
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003171/* Parse all the frames of <pkt> QUIC packet for QUIC connection <qc> and <qel>
3172 * as encryption level.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003173 * Returns 1 if succeeded, 0 if failed.
3174 */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003175static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003176 struct quic_enc_level *qel)
3177{
3178 struct quic_frame frm;
3179 const unsigned char *pos, *end;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003180 int fast_retrans = 0, ret = 0;
3181
3182 TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
3183 /* Skip the AAD */
3184 pos = pkt->data + pkt->aad_len;
3185 end = pkt->data + pkt->len;
3186
3187 while (pos < end) {
3188 if (!qc_parse_frm(&frm, pkt, &pos, end, qc)) {
3189 // trace already emitted by function above
3190 goto leave;
3191 }
3192
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003193 switch (frm.type) {
3194 case QUIC_FT_PADDING:
3195 break;
3196 case QUIC_FT_PING:
3197 break;
3198 case QUIC_FT_ACK:
3199 {
3200 unsigned int rtt_sample;
3201
Frédéric Lécaille809bd9f2023-04-06 13:13:08 +02003202 rtt_sample = UINT_MAX;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003203 if (!qc_parse_ack_frm(qc, &frm, qel, &rtt_sample, &pos, end)) {
3204 // trace already emitted by function above
3205 goto leave;
3206 }
3207
Frédéric Lécaille809bd9f2023-04-06 13:13:08 +02003208 if (rtt_sample != UINT_MAX) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003209 unsigned int ack_delay;
3210
3211 ack_delay = !quic_application_pktns(qel->pktns, qc) ? 0 :
3212 qc->state >= QUIC_HS_ST_CONFIRMED ?
3213 MS_TO_TICKS(QUIC_MIN(quic_ack_delay_ms(&frm.ack, qc), qc->max_ack_delay)) :
3214 MS_TO_TICKS(quic_ack_delay_ms(&frm.ack, qc));
3215 quic_loss_srtt_update(&qc->path->loss, rtt_sample, ack_delay, qc);
3216 }
3217 break;
3218 }
3219 case QUIC_FT_RESET_STREAM:
Amaury Denoyelle5854fc02022-12-09 16:25:48 +01003220 if (qc->mux_state == QC_MUX_READY) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003221 struct qf_reset_stream *rs_frm = &frm.reset_stream;
3222 qcc_recv_reset_stream(qc->qcc, rs_frm->id, rs_frm->app_error_code, rs_frm->final_size);
Amaury Denoyelle5854fc02022-12-09 16:25:48 +01003223 }
3224 break;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003225 case QUIC_FT_STOP_SENDING:
3226 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003227 struct qf_stop_sending *ss_frm = &frm.stop_sending;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003228 if (qc->mux_state == QC_MUX_READY) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003229 if (qcc_recv_stop_sending(qc->qcc, ss_frm->id,
3230 ss_frm->app_error_code)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003231 TRACE_ERROR("qcc_recv_stop_sending() failed", QUIC_EV_CONN_PRSHPKT, qc);
3232 goto leave;
3233 }
3234 }
3235 break;
3236 }
3237 case QUIC_FT_CRYPTO:
Frédéric Lécaillea20c93e2022-09-12 14:54:45 +02003238 if (!qc_handle_crypto_frm(qc, &frm.crypto, pkt, qel, &fast_retrans))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003239 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003240 break;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003241 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
3242 {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003243 struct qf_stream *strm_frm = &frm.stream;
3244 unsigned nb_streams = qc->rx.strms[qcs_id_type(strm_frm->id)].nb_streams;
Amaury Denoyelle2216b082023-02-02 14:59:36 +01003245 const char fin = frm.type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003246
3247 /* The upper layer may not be allocated. */
3248 if (qc->mux_state != QC_MUX_READY) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003249 if ((strm_frm->id >> QCS_ID_TYPE_SHIFT) < nb_streams) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003250 TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003251 }
3252 else {
3253 TRACE_DEVEL("No mux for new stream", QUIC_EV_CONN_PRSHPKT, qc);
Amaury Denoyelle38836b62023-02-07 14:24:54 +01003254 if (qc->app_ops == &h3_ops) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003255 if (!qc_h3_request_reject(qc, strm_frm->id)) {
Amaury Denoyelle156a89a2023-02-20 10:32:16 +01003256 TRACE_ERROR("error on request rejection", QUIC_EV_CONN_PRSHPKT, qc);
3257 /* This packet will not be acknowledged */
3258 goto leave;
3259 }
3260 }
3261 else {
3262 /* This packet will not be acknowledged */
3263 goto leave;
Frédéric Lécailled18025e2023-01-20 15:33:50 +01003264 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003265 }
Amaury Denoyelle315a4f62023-03-06 09:10:53 +01003266
3267 break;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003268 }
3269
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003270 if (!qc_handle_strm_frm(pkt, strm_frm, qc, fin)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003271 TRACE_ERROR("qc_handle_strm_frm() failed", QUIC_EV_CONN_PRSHPKT, qc);
3272 goto leave;
3273 }
3274
3275 break;
3276 }
3277 case QUIC_FT_MAX_DATA:
3278 if (qc->mux_state == QC_MUX_READY) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003279 struct qf_max_data *md_frm = &frm.max_data;
3280 qcc_recv_max_data(qc->qcc, md_frm->max_data);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003281 }
3282 break;
3283 case QUIC_FT_MAX_STREAM_DATA:
3284 if (qc->mux_state == QC_MUX_READY) {
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02003285 struct qf_max_stream_data *msd_frm = &frm.max_stream_data;
3286 if (qcc_recv_max_stream_data(qc->qcc, msd_frm->id,
3287 msd_frm->max_stream_data)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003288 TRACE_ERROR("qcc_recv_max_stream_data() failed", QUIC_EV_CONN_PRSHPKT, qc);
3289 goto leave;
3290 }
3291 }
3292 break;
3293 case QUIC_FT_MAX_STREAMS_BIDI:
3294 case QUIC_FT_MAX_STREAMS_UNI:
3295 break;
3296 case QUIC_FT_DATA_BLOCKED:
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02003297 qc->cntrs.data_blocked++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003298 break;
3299 case QUIC_FT_STREAM_DATA_BLOCKED:
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02003300 qc->cntrs.stream_data_blocked++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003301 break;
3302 case QUIC_FT_STREAMS_BLOCKED_BIDI:
Amaury Denoyelle6d6ee0d2023-05-25 10:36:04 +02003303 qc->cntrs.streams_blocked_bidi++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003304 break;
3305 case QUIC_FT_STREAMS_BLOCKED_UNI:
Amaury Denoyelle6d6ee0d2023-05-25 10:36:04 +02003306 qc->cntrs.streams_blocked_uni++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003307 break;
3308 case QUIC_FT_NEW_CONNECTION_ID:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003309 /* XXX TO DO XXX */
3310 break;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003311 case QUIC_FT_RETIRE_CONNECTION_ID:
3312 {
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003313 struct quic_connection_id *conn_id = NULL;
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003314
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003315 if (!qc_handle_retire_connection_id_frm(qc, &frm, &pkt->dcid, &conn_id))
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003316 goto leave;
3317
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003318 if (!conn_id)
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003319 break;
3320
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003321 ebmb_delete(&conn_id->node);
3322 eb64_delete(&conn_id->seq_num);
3323 pool_free(pool_head_quic_connection_id, conn_id);
Frédéric Lécaillecc101cd2023-03-08 11:01:58 +01003324 TRACE_PROTO("CID retired", QUIC_EV_CONN_PSTRM, qc);
3325
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003326 conn_id = new_quic_cid(&qc->cids, qc, NULL, NULL);
3327 if (!conn_id) {
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003328 TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc);
3329 }
3330 else {
Amaury Denoyellee83f9372023-04-18 11:10:54 +02003331 quic_cid_insert(conn_id);
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003332 qc_build_new_connection_id_frm(qc, conn_id);
Frédéric Lécaille8ac8a872023-03-06 18:16:34 +01003333 }
3334 break;
3335 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003336 case QUIC_FT_CONNECTION_CLOSE:
3337 case QUIC_FT_CONNECTION_CLOSE_APP:
3338 /* Increment the error counters */
3339 qc_cc_err_count_inc(qc, &frm);
3340 if (!(qc->flags & QUIC_FL_CONN_DRAINING)) {
3341 if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
3342 qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
3343 HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
3344 }
3345 TRACE_STATE("Entering draining state", QUIC_EV_CONN_PRSHPKT, qc);
3346 /* RFC 9000 10.2. Immediate Close:
3347 * The closing and draining connection states exist to ensure
3348 * that connections close cleanly and that delayed or reordered
3349 * packets are properly discarded. These states SHOULD persist
3350 * for at least three times the current PTO interval...
3351 *
3352 * Rearm the idle timeout only one time when entering draining
3353 * state.
3354 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003355 qc->flags |= QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_IMMEDIATE_CLOSE;
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01003356 qc_detach_th_ctx_list(qc, 1);
Frédéric Lécailled7215712023-03-24 18:13:37 +01003357 qc_idle_timer_do_rearm(qc, 0);
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02003358 qc_notify_err(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003359 }
3360 break;
3361 case QUIC_FT_HANDSHAKE_DONE:
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003362 if (qc_is_listener(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003363 TRACE_ERROR("non accepted QUIC_FT_HANDSHAKE_DONE frame",
3364 QUIC_EV_CONN_PRSHPKT, qc);
3365 goto leave;
3366 }
3367
3368 qc->state = QUIC_HS_ST_CONFIRMED;
3369 break;
3370 default:
3371 TRACE_ERROR("unknosw frame type", QUIC_EV_CONN_PRSHPKT, qc);
3372 goto leave;
3373 }
3374 }
3375
3376 /* Flag this packet number space as having received a packet. */
3377 qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED;
3378
3379 if (fast_retrans) {
3380 struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
3381 struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
3382
3383 TRACE_PROTO("speeding up handshake completion", QUIC_EV_CONN_PRSHPKT, qc);
3384 qc_prep_hdshk_fast_retrans(qc, &iqel->pktns->tx.frms, &hqel->pktns->tx.frms);
3385 qc->flags |= QUIC_FL_CONN_HANDSHAKE_SPEED_UP;
3386 }
3387
3388 /* The server must switch from INITIAL to HANDSHAKE handshake state when it
3389 * has successfully parse a Handshake packet. The Initial encryption must also
3390 * be discarded.
3391 */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003392 if (pkt->type == QUIC_PACKET_TYPE_HANDSHAKE && qc_is_listener(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003393 if (qc->state >= QUIC_HS_ST_SERVER_INITIAL) {
3394 if (!(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx.flags &
3395 QUIC_FL_TLS_SECRETS_DCD)) {
3396 quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
3397 TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PRSHPKT, qc);
3398 quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, qc);
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003399 qc_set_timer(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003400 qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
3401 qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns);
3402 }
3403 if (qc->state < QUIC_HS_ST_SERVER_HANDSHAKE)
3404 qc->state = QUIC_HS_ST_SERVER_HANDSHAKE;
3405 }
3406 }
3407
3408 ret = 1;
3409 leave:
3410 TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
3411 return ret;
3412}
3413
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02003414
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003415/* Allocate Tx buffer from <qc> quic-conn if needed.
3416 *
3417 * Returns allocated buffer or NULL on error.
3418 */
3419static struct buffer *qc_txb_alloc(struct quic_conn *qc)
3420{
3421 struct buffer *buf = &qc->tx.buf;
3422 if (!b_alloc(buf))
3423 return NULL;
3424
3425 return buf;
3426}
3427
3428/* Free Tx buffer from <qc> if it is empty. */
3429static void qc_txb_release(struct quic_conn *qc)
3430{
3431 struct buffer *buf = &qc->tx.buf;
3432
3433 /* For the moment sending function is responsible to purge the buffer
3434 * entirely. It may change in the future but this requires to be able
3435 * to reuse old data.
Frédéric Lécaillebbf86be2023-02-20 09:28:58 +01003436 * For the momemt we do not care to leave data in the buffer for
3437 * a connection which is supposed to be killed asap.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003438 */
3439 BUG_ON_HOT(buf && b_data(buf));
3440
3441 if (!b_data(buf)) {
3442 b_free(buf);
3443 offer_buffers(NULL, 1);
3444 }
3445}
3446
3447/* Commit a datagram payload written into <buf> of length <length>. <first_pkt>
3448 * must contains the address of the first packet stored in the payload.
3449 *
3450 * Caller is responsible that there is enough space in the buffer.
3451 */
3452static void qc_txb_store(struct buffer *buf, uint16_t length,
3453 struct quic_tx_packet *first_pkt)
3454{
3455 const size_t hdlen = sizeof(uint16_t) + sizeof(void *);
3456 BUG_ON_HOT(b_contig_space(buf) < hdlen); /* this must not happen */
3457
3458 write_u16(b_tail(buf), length);
3459 write_ptr(b_tail(buf) + sizeof(length), first_pkt);
3460 b_add(buf, hdlen + length);
3461}
3462
3463/* Returns 1 if a packet may be built for <qc> from <qel> encryption level
3464 * with <frms> as ack-eliciting frame list to send, 0 if not.
3465 * <cc> must equal to 1 if an immediate close was asked, 0 if not.
3466 * <probe> must equalt to 1 if a probing packet is required, 0 if not.
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003467 * Also set <*must_ack> to inform the caller if an acknowledgement should be sent.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003468 */
3469static int qc_may_build_pkt(struct quic_conn *qc, struct list *frms,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003470 struct quic_enc_level *qel, int cc, int probe,
3471 int *must_ack)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003472{
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003473 int force_ack =
3474 qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] ||
3475 qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
3476 int nb_aepkts_since_last_ack = qel->pktns->rx.nb_aepkts_since_last_ack;
3477
3478 /* An acknowledgement must be sent if this has been forced by the caller,
3479 * typically during the handshake when the packets must be acknowledged as
3480 * soon as possible. This is also the case when the ack delay timer has been
3481 * triggered, or at least every QUIC_MAX_RX_AEPKTS_SINCE_LAST_ACK packets.
3482 */
3483 *must_ack = (qc->flags & QUIC_FL_CONN_ACK_TIMER_FIRED) ||
3484 ((qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) &&
3485 (force_ack || nb_aepkts_since_last_ack >= QUIC_MAX_RX_AEPKTS_SINCE_LAST_ACK));
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003486
3487 /* Do not build any more packet if the TX secrets are not available or
3488 * if there is nothing to send, i.e. if no CONNECTION_CLOSE or ACK are required
3489 * and if there is no more packets to send upon PTO expiration
3490 * and if there is no more ack-eliciting frames to send or in flight
3491 * congestion control limit is reached for prepared data
3492 */
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02003493 if (!quic_tls_has_tx_sec(qel) ||
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003494 (!cc && !probe && !*must_ack &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003495 (LIST_ISEMPTY(frms) || qc->path->prep_in_flight >= qc->path->cwnd))) {
3496 return 0;
3497 }
3498
3499 return 1;
3500}
3501
3502/* Prepare as much as possible QUIC packets for sending from prebuilt frames
3503 * <frms>. Each packet is stored in a distinct datagram written to <buf>.
3504 *
3505 * Each datagram is prepended by a two fields header : the datagram length and
3506 * the address of the packet contained in the datagram.
3507 *
3508 * Returns the number of bytes prepared in packets if succeeded (may be 0), or
3509 * -1 if something wrong happened.
3510 */
3511static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf,
3512 struct list *frms)
3513{
3514 int ret = -1;
3515 struct quic_enc_level *qel;
3516 unsigned char *end, *pos;
3517 struct quic_tx_packet *pkt;
3518 size_t total;
3519 /* Each datagram is prepended with its length followed by the address
3520 * of the first packet in the datagram.
3521 */
3522 const size_t dg_headlen = sizeof(uint16_t) + sizeof(pkt);
3523
3524 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
3525
3526 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
3527 total = 0;
3528 pos = (unsigned char *)b_tail(buf);
3529 while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen) {
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003530 int err, probe, cc, must_ack;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003531
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02003532 TRACE_PROTO("TX prep app pkts", QUIC_EV_CONN_PHPKTS, qc, qel, frms);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003533 probe = 0;
3534 cc = qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE;
3535 /* We do not probe if an immediate close was asked */
3536 if (!cc)
3537 probe = qel->pktns->tx.pto_probe;
3538
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003539 if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003540 break;
3541
3542 /* Leave room for the datagram header */
3543 pos += dg_headlen;
3544 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
3545 end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
3546 }
3547 else {
3548 end = pos + qc->path->mtu;
3549 }
3550
3551 pkt = qc_build_pkt(&pos, end, qel, &qel->tls_ctx, frms, qc, NULL, 0,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003552 QUIC_PACKET_TYPE_SHORT, must_ack, 0, probe, cc, &err);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003553 switch (err) {
3554 case -2:
3555 // trace already emitted by function above
3556 goto leave;
3557 case -1:
3558 /* As we provide qc_build_pkt() with an enough big buffer to fulfill an
3559 * MTU, we are here because of the congestion control window. There is
3560 * no need to try to reuse this buffer.
3561 */
Frédéric Lécaillee47adca2023-04-07 18:12:00 +02003562 TRACE_PROTO("could not prepare anymore packet", QUIC_EV_CONN_PHPKTS, qc, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003563 goto out;
3564 default:
3565 break;
3566 }
3567
3568 /* This is to please to GCC. We cannot have (err >= 0 && !pkt) */
3569 BUG_ON(!pkt);
3570
3571 if (qc->flags & QUIC_FL_CONN_RETRANS_OLD_DATA)
3572 pkt->flags |= QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA;
3573
3574 total += pkt->len;
3575
3576 /* Write datagram header. */
3577 qc_txb_store(buf, pkt->len, pkt);
3578 }
3579
3580 out:
3581 ret = total;
3582 leave:
3583 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
3584 return ret;
3585}
3586
3587/* Prepare as much as possible QUIC packets for sending from prebuilt frames
3588 * <frms>. Several packets can be regrouped in a single datagram. The result is
3589 * written into <buf>.
3590 *
3591 * Each datagram is prepended by a two fields header : the datagram length and
3592 * the address of first packet in the datagram.
3593 *
3594 * Returns the number of bytes prepared in packets if succeeded (may be 0), or
3595 * -1 if something wrong happened.
3596 */
3597static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
3598 enum quic_tls_enc_level tel, struct list *tel_frms,
3599 enum quic_tls_enc_level next_tel, struct list *next_tel_frms)
3600{
3601 struct quic_enc_level *qel;
3602 unsigned char *end, *pos;
3603 struct quic_tx_packet *first_pkt, *cur_pkt, *prv_pkt;
3604 /* length of datagrams */
3605 uint16_t dglen;
3606 size_t total;
3607 int ret = -1, padding;
3608 /* Each datagram is prepended with its length followed by the address
3609 * of the first packet in the datagram.
3610 */
3611 const size_t dg_headlen = sizeof(uint16_t) + sizeof(first_pkt);
3612 struct list *frms;
3613
3614 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
3615
3616 /* Currently qc_prep_pkts() does not handle buffer wrapping so the
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05003617 * caller must ensure that buf is reset.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003618 */
3619 BUG_ON_HOT(buf->head || buf->data);
3620
3621 total = 0;
3622 qel = &qc->els[tel];
3623 frms = tel_frms;
3624 dglen = 0;
3625 padding = 0;
3626 pos = (unsigned char *)b_head(buf);
3627 first_pkt = prv_pkt = NULL;
3628 while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen || prv_pkt) {
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003629 int err, probe, cc, must_ack;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003630 enum quic_pkt_type pkt_type;
3631 struct quic_tls_ctx *tls_ctx;
3632 const struct quic_version *ver;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003633
Frédéric Lécaillee47adca2023-04-07 18:12:00 +02003634 TRACE_PROTO("TX prep pkts", QUIC_EV_CONN_PHPKTS, qc, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003635 probe = 0;
3636 cc = qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE;
3637 /* We do not probe if an immediate close was asked */
3638 if (!cc)
3639 probe = qel->pktns->tx.pto_probe;
3640
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003641 if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003642 if (prv_pkt)
3643 qc_txb_store(buf, dglen, first_pkt);
3644 /* Let's select the next encryption level */
3645 if (tel != next_tel && next_tel != QUIC_TLS_ENC_LEVEL_NONE) {
3646 tel = next_tel;
3647 frms = next_tel_frms;
3648 qel = &qc->els[tel];
3649 /* Build a new datagram */
3650 prv_pkt = NULL;
3651 TRACE_DEVEL("next encryption level selected", QUIC_EV_CONN_PHPKTS, qc);
3652 continue;
3653 }
3654 break;
3655 }
3656
3657 pkt_type = quic_tls_level_pkt_type(tel);
3658 if (!prv_pkt) {
3659 /* Leave room for the datagram header */
3660 pos += dg_headlen;
3661 if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
3662 end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
3663 }
3664 else {
3665 end = pos + qc->path->mtu;
3666 }
3667 }
3668
Frédéric Lécaille69e71182023-02-20 14:39:41 +01003669 /* RFC 9000 14.1 Initial datagram size
3670 * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
3671 * Initial packets to at least the smallest allowed maximum datagram size of
3672 * 1200 bytes.
3673 *
3674 * Ensure that no ack-eliciting packets are sent into too small datagrams
3675 */
3676 if (pkt_type == QUIC_PACKET_TYPE_INITIAL && !LIST_ISEMPTY(tel_frms)) {
3677 if (end - pos < QUIC_INITIAL_PACKET_MINLEN) {
Frédéric Lécailled30a04a2023-02-21 16:44:05 +01003678 TRACE_PROTO("No more enough room to build an Initial packet",
Frédéric Lécaille69e71182023-02-20 14:39:41 +01003679 QUIC_EV_CONN_PHPKTS, qc);
3680 goto out;
3681 }
3682
3683 /* Pad this Initial packet if there is no ack-eliciting frames to send from
3684 * the next packet number space.
3685 */
Frédéric Lécailleec937212023-03-03 17:34:41 +01003686 if (!next_tel_frms || LIST_ISEMPTY(next_tel_frms))
Frédéric Lécaille69e71182023-02-20 14:39:41 +01003687 padding = 1;
3688 }
3689
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003690 if (qc->negotiated_version) {
3691 ver = qc->negotiated_version;
3692 if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL])
3693 tls_ctx = &qc->negotiated_ictx;
3694 else
3695 tls_ctx = &qel->tls_ctx;
3696 }
3697 else {
3698 ver = qc->original_version;
3699 tls_ctx = &qel->tls_ctx;
3700 }
3701
3702 cur_pkt = qc_build_pkt(&pos, end, qel, tls_ctx, frms,
3703 qc, ver, dglen, pkt_type,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02003704 must_ack, padding, probe, cc, &err);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003705 switch (err) {
3706 case -2:
3707 // trace already emitted by function above
3708 goto leave;
3709 case -1:
3710 /* If there was already a correct packet present, set the
3711 * current datagram as prepared into <cbuf>.
3712 */
3713 if (prv_pkt)
3714 qc_txb_store(buf, dglen, first_pkt);
Frédéric Lécaillee47adca2023-04-07 18:12:00 +02003715 TRACE_PROTO("could not prepare anymore packet", QUIC_EV_CONN_PHPKTS, qc, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003716 goto out;
3717 default:
3718 break;
3719 }
3720
3721 /* This is to please to GCC. We cannot have (err >= 0 && !cur_pkt) */
3722 BUG_ON(!cur_pkt);
3723
3724 if (qc->flags & QUIC_FL_CONN_RETRANS_OLD_DATA)
3725 cur_pkt->flags |= QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA;
3726
3727 total += cur_pkt->len;
3728 /* keep trace of the first packet in the datagram */
3729 if (!first_pkt)
3730 first_pkt = cur_pkt;
Frédéric Lécaille74b5f7b2022-11-20 18:35:35 +01003731 /* Attach the current one to the previous one and vice versa */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003732 if (prv_pkt) {
3733 prv_pkt->next = cur_pkt;
Frédéric Lécaille814645f2022-11-18 18:15:28 +01003734 cur_pkt->prev = prv_pkt;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003735 cur_pkt->flags |= QUIC_FL_TX_PACKET_COALESCED;
3736 }
3737 /* Let's say we have to build a new dgram */
3738 prv_pkt = NULL;
3739 dglen += cur_pkt->len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003740 /* If the data for the current encryption level have all been sent,
3741 * select the next level.
3742 */
3743 if ((tel == QUIC_TLS_ENC_LEVEL_INITIAL || tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE) &&
Frédéric Lécaillea576c1b2023-04-13 15:59:02 +02003744 next_tel != QUIC_TLS_ENC_LEVEL_NONE && (LIST_ISEMPTY(frms))) {
Frédéric Lécailleb5461932023-06-14 08:54:51 +02003745 /* If QUIC_TLS_ENC_LEVEL_HANDSHAKE was already reached let's try QUIC_TLS_ENC_LEVEL_APP */
3746 if (tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE && next_tel == tel)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003747 next_tel = QUIC_TLS_ENC_LEVEL_APP;
3748 tel = next_tel;
3749 if (tel == QUIC_TLS_ENC_LEVEL_APP)
3750 frms = &qc->els[tel].pktns->tx.frms;
3751 else
3752 frms = next_tel_frms;
3753 qel = &qc->els[tel];
3754 if (!LIST_ISEMPTY(frms)) {
3755 /* If there is data for the next level, do not
3756 * consume a datagram.
3757 */
3758 prv_pkt = cur_pkt;
3759 }
3760 }
3761
3762 /* If we have to build a new datagram, set the current datagram as
3763 * prepared into <cbuf>.
3764 */
3765 if (!prv_pkt) {
3766 qc_txb_store(buf, dglen, first_pkt);
3767 first_pkt = NULL;
3768 dglen = 0;
3769 padding = 0;
3770 }
3771 else if (prv_pkt->type == QUIC_TLS_ENC_LEVEL_INITIAL &&
3772 (!qc_is_listener(qc) ||
3773 prv_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
3774 padding = 1;
3775 }
3776 }
3777
3778 out:
3779 ret = total;
3780 leave:
3781 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
3782 return ret;
3783}
3784
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003785/* Free all frames in <l> list. In addition also remove all these frames
3786 * from the original ones if they are the results of duplications.
3787 */
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02003788static inline void qc_free_frm_list(struct list *l)
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003789{
3790 struct quic_frame *frm, *frmbak;
3791
3792 list_for_each_entry_safe(frm, frmbak, l, list) {
3793 LIST_DEL_INIT(&frm->ref);
3794 qc_frm_free(&frm);
3795 }
3796}
3797
3798/* Free <pkt> TX packet and all the packets coalesced to it. */
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02003799static inline void qc_free_tx_coalesced_pkts(struct quic_tx_packet *p)
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003800{
3801 struct quic_tx_packet *pkt, *nxt_pkt;
3802
3803 for (pkt = p; pkt; pkt = nxt_pkt) {
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02003804 qc_free_frm_list(&pkt->frms);
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003805 nxt_pkt = pkt->next;
3806 pool_free(pool_head_quic_tx_packet, pkt);
3807 }
3808}
3809
3810/* Purge <buf> TX buffer from its prepare packets. */
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02003811static void qc_purge_tx_buf(struct buffer *buf)
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003812{
3813 while (b_contig_data(buf, 0)) {
3814 uint16_t dglen;
3815 struct quic_tx_packet *pkt;
3816 size_t headlen = sizeof dglen + sizeof pkt;
3817
3818 dglen = read_u16(b_head(buf));
3819 pkt = read_ptr(b_head(buf) + sizeof dglen);
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02003820 qc_free_tx_coalesced_pkts(pkt);
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003821 b_del(buf, dglen + headlen);
3822 }
3823
3824 BUG_ON(b_data(buf));
3825}
3826
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003827/* Send datagrams stored in <buf>.
3828 *
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003829 * This function returns 1 for success. On error, there is several behavior
3830 * depending on underlying sendto() error :
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01003831 * - for an unrecoverable error, 0 is returned and connection is killed.
3832 * - a transient error is handled differently if connection has its owned
3833 * socket. If this is the case, 0 is returned and socket is subscribed on the
3834 * poller. The other case is assimilated to a success case with 1 returned.
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003835 * Remaining data are purged from the buffer and will eventually be detected
3836 * as lost which gives the opportunity to retry sending.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003837 */
3838int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
3839{
Frédéric Lécaillea2c62c32023-02-10 14:13:43 +01003840 int ret = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003841 struct quic_conn *qc;
3842 char skip_sendto = 0;
3843
3844 qc = ctx->qc;
3845 TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
3846 while (b_contig_data(buf, 0)) {
3847 unsigned char *pos;
3848 struct buffer tmpbuf = { };
3849 struct quic_tx_packet *first_pkt, *pkt, *next_pkt;
3850 uint16_t dglen;
3851 size_t headlen = sizeof dglen + sizeof first_pkt;
3852 unsigned int time_sent;
3853
3854 pos = (unsigned char *)b_head(buf);
3855 dglen = read_u16(pos);
3856 BUG_ON_HOT(!dglen); /* this should not happen */
3857
3858 pos += sizeof dglen;
3859 first_pkt = read_ptr(pos);
3860 pos += sizeof first_pkt;
3861 tmpbuf.area = (char *)pos;
3862 tmpbuf.size = tmpbuf.data = dglen;
3863
Frédéric Lécaille8f991942023-03-24 15:14:45 +01003864 TRACE_PROTO("TX dgram", QUIC_EV_CONN_SPPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003865 /* If sendto is on error just skip the call to it for the rest
3866 * of the loop but continue to purge the buffer. Data will be
3867 * transmitted when QUIC packets are detected as lost on our
3868 * side.
3869 *
3870 * TODO use fd-monitoring to detect when send operation can be
3871 * retry. This should improve the bandwidth without relying on
3872 * retransmission timer. However, it requires a major rework on
3873 * quic-conn fd management.
3874 */
3875 if (!skip_sendto) {
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003876 int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0);
3877 if (ret < 0) {
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003878 TRACE_ERROR("sendto fatal error", QUIC_EV_CONN_SPPKTS, qc, first_pkt);
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003879 qc_kill_conn(qc);
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02003880 qc_free_tx_coalesced_pkts(first_pkt);
Frédéric Lécaillece0bb332023-04-24 11:11:55 +02003881 b_del(buf, dglen + headlen);
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02003882 qc_purge_tx_buf(buf);
Amaury Denoyelle1febc2d2023-02-23 11:18:38 +01003883 goto leave;
3884 }
3885 else if (!ret) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01003886 /* Connection owned socket : poller will wake us up when transient error is cleared. */
3887 if (qc_test_fd(qc)) {
3888 TRACE_ERROR("sendto error, subscribe to poller", QUIC_EV_CONN_SPPKTS, qc);
3889 goto leave;
3890 }
3891
3892 /* No connection owned-socket : rely on retransmission to retry sending. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003893 skip_sendto = 1;
3894 TRACE_ERROR("sendto error, simulate sending for the rest of data", QUIC_EV_CONN_SPPKTS, qc);
3895 }
3896 }
3897
3898 b_del(buf, dglen + headlen);
3899 qc->tx.bytes += tmpbuf.data;
3900 time_sent = now_ms;
3901
3902 for (pkt = first_pkt; pkt; pkt = next_pkt) {
Frédéric Lécailleceb88b82023-02-20 14:43:55 +01003903 /* RFC 9000 14.1 Initial datagram size
3904 * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
3905 * Initial packets to at least the smallest allowed maximum datagram size of
3906 * 1200 bytes.
3907 */
Frédéric Lécaille12a815a2023-05-24 15:55:14 +02003908 qc->cntrs.sent_pkt++;
Frédéric Lécailleceb88b82023-02-20 14:43:55 +01003909 BUG_ON_HOT(pkt->type == QUIC_PACKET_TYPE_INITIAL &&
3910 (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) &&
3911 dglen < QUIC_INITIAL_PACKET_MINLEN);
3912
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003913 pkt->time_sent = time_sent;
3914 if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) {
3915 pkt->pktns->tx.time_of_last_eliciting = time_sent;
3916 qc->path->ifae_pkts++;
3917 if (qc->flags & QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ)
Frédéric Lécailled7215712023-03-24 18:13:37 +01003918 qc_idle_timer_rearm(qc, 0, 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003919 }
3920 if (!(qc->flags & QUIC_FL_CONN_CLOSING) &&
3921 (pkt->flags & QUIC_FL_TX_PACKET_CC)) {
3922 qc->flags |= QUIC_FL_CONN_CLOSING;
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01003923 qc_detach_th_ctx_list(qc, 1);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003924
3925 /* RFC 9000 10.2. Immediate Close:
3926 * The closing and draining connection states exist to ensure
3927 * that connections close cleanly and that delayed or reordered
3928 * packets are properly discarded. These states SHOULD persist
3929 * for at least three times the current PTO interval...
3930 *
3931 * Rearm the idle timeout only one time when entering closing
3932 * state.
3933 */
Frédéric Lécailled7215712023-03-24 18:13:37 +01003934 qc_idle_timer_do_rearm(qc, 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003935 if (qc->timer_task) {
3936 task_destroy(qc->timer_task);
3937 qc->timer_task = NULL;
3938 }
3939 }
3940 qc->path->in_flight += pkt->in_flight_len;
3941 pkt->pktns->tx.in_flight += pkt->in_flight_len;
3942 if (pkt->in_flight_len)
3943 qc_set_timer(qc);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01003944 TRACE_PROTO("TX pkt", QUIC_EV_CONN_SPPKTS, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003945 next_pkt = pkt->next;
3946 quic_tx_packet_refinc(pkt);
3947 eb64_insert(&pkt->pktns->tx.pkts, &pkt->pn_node);
3948 }
3949 }
3950
Frédéric Lécaillea2c62c32023-02-10 14:13:43 +01003951 ret = 1;
3952leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003953 TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
3954
Frédéric Lécaillea2c62c32023-02-10 14:13:43 +01003955 return ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003956}
3957
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02003958/* Copy at <pos> position a stateless reset token depending on the
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003959 * <salt> salt input. This is the cluster secret which will be derived
3960 * as HKDF input secret to generate this token.
3961 * Return 1 if succeeded, 0 if not.
3962 */
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02003963static int quic_stateless_reset_token_cpy(unsigned char *pos, size_t len,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003964 const unsigned char *salt, size_t saltlen)
3965{
3966 /* Input secret */
Frédéric Lécaille0499db42023-09-07 18:43:52 +02003967 const unsigned char *key = global.cluster_secret;
3968 size_t keylen = sizeof global.cluster_secret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003969 /* Info */
3970 const unsigned char label[] = "stateless token";
3971 size_t labellen = sizeof label - 1;
3972 int ret;
3973
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02003974 ret = quic_hkdf_extract_and_expand(EVP_sha256(), pos, len,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003975 key, keylen, salt, saltlen, label, labellen);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003976 return ret;
3977}
3978
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003979/* Initialize the stateless reset token attached to <conn_id> connection ID.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003980 * Returns 1 if succeeded, 0 if not.
3981 */
Amaury Denoyelle591e7982023-04-12 10:04:49 +02003982static int quic_stateless_reset_token_init(struct quic_connection_id *conn_id)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003983{
Frédéric Lécaille0499db42023-09-07 18:43:52 +02003984 /* Output secret */
3985 unsigned char *token = conn_id->stateless_reset_token;
3986 size_t tokenlen = sizeof conn_id->stateless_reset_token;
3987 /* Salt */
3988 const unsigned char *cid = conn_id->cid.data;
3989 size_t cidlen = conn_id->cid.len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003990
Frédéric Lécaille0499db42023-09-07 18:43:52 +02003991 return quic_stateless_reset_token_cpy(token, tokenlen, cid, cidlen);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02003992}
3993
Amaury Denoyelle1e959ad2023-04-13 17:34:56 +02003994/* Generate a CID directly derived from <orig> CID and <addr> address.
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003995 *
Amaury Denoyellec2a92642023-04-13 15:26:18 +02003996 * Returns the derived CID.
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003997 */
Amaury Denoyellec2a92642023-04-13 15:26:18 +02003998struct quic_cid quic_derive_cid(const struct quic_cid *orig,
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02003999 const struct sockaddr_storage *addr)
4000{
Amaury Denoyellec2a92642023-04-13 15:26:18 +02004001 struct quic_cid cid;
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004002 const struct sockaddr_in *in;
4003 const struct sockaddr_in6 *in6;
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004004 char *pos = trash.area;
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004005 size_t idx = 0;
4006 uint64_t hash;
Amaury Denoyellec2a92642023-04-13 15:26:18 +02004007 int i;
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004008
4009 /* Prepare buffer for hash using original CID first. */
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004010 memcpy(pos, orig->data, orig->len);
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004011 idx += orig->len;
4012
4013 /* Concatenate client address. */
4014 switch (addr->ss_family) {
4015 case AF_INET:
4016 in = (struct sockaddr_in *)addr;
4017
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004018 memcpy(&pos[idx], &in->sin_addr, sizeof(in->sin_addr));
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004019 idx += sizeof(in->sin_addr);
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004020 memcpy(&pos[idx], &in->sin_port, sizeof(in->sin_port));
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004021 idx += sizeof(in->sin_port);
4022 break;
4023
4024 case AF_INET6:
4025 in6 = (struct sockaddr_in6 *)addr;
4026
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004027 memcpy(&pos[idx], &in6->sin6_addr, sizeof(in6->sin6_addr));
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004028 idx += sizeof(in6->sin6_addr);
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004029 memcpy(&pos[idx], &in6->sin6_port, sizeof(in6->sin6_port));
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004030 idx += sizeof(in6->sin6_port);
4031 break;
4032
4033 default:
4034 /* TODO to implement */
4035 ABORT_NOW();
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004036 }
4037
4038 /* Avoid similar values between multiple haproxy process. */
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004039 memcpy(&pos[idx], boot_seed, sizeof(boot_seed));
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004040 idx += sizeof(boot_seed);
4041
4042 /* Hash the final buffer content. */
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004043 hash = XXH64(pos, idx, 0);
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004044
Amaury Denoyellec2a92642023-04-13 15:26:18 +02004045 for (i = 0; i < sizeof(hash); ++i)
4046 cid.data[i] = hash >> ((sizeof(hash) * 7) - (8 * i));
4047 cid.len = sizeof(hash);
4048
Amaury Denoyellec2a92642023-04-13 15:26:18 +02004049 return cid;
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004050}
4051
Amaury Denoyellee83f9372023-04-18 11:10:54 +02004052/* Retrieve the thread ID associated to QUIC connection ID <cid> of length
4053 * <cid_len>. CID may be not found on the CID tree because it is an ODCID. In
4054 * this case, it will derived using client address <cli_addr> as hash
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004055 * parameter. However, this is done only if <pos> points to an INITIAL or 0RTT
Amaury Denoyellee83f9372023-04-18 11:10:54 +02004056 * packet of length <len>.
4057 *
4058 * Returns the thread ID or a negative error code.
4059 */
4060int quic_get_cid_tid(const unsigned char *cid, size_t cid_len,
4061 const struct sockaddr_storage *cli_addr,
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004062 unsigned char *pos, size_t len)
Amaury Denoyellee83f9372023-04-18 11:10:54 +02004063{
4064 struct quic_cid_tree *tree;
4065 struct quic_connection_id *conn_id;
4066 struct ebmb_node *node;
4067
4068 tree = &quic_cid_trees[_quic_cid_tree_idx(cid)];
4069 HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
4070 node = ebmb_lookup(&tree->root, cid, cid_len);
4071 HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
4072
4073 if (!node) {
4074 struct quic_cid orig, derive_cid;
4075 struct quic_rx_packet pkt;
4076
Frédéric Lécaille81a02b52023-04-24 15:29:56 +02004077 if (!qc_parse_hd_form(&pkt, &pos, pos + len))
Amaury Denoyellee83f9372023-04-18 11:10:54 +02004078 goto not_found;
4079
4080 if (pkt.type != QUIC_PACKET_TYPE_INITIAL &&
4081 pkt.type != QUIC_PACKET_TYPE_0RTT) {
4082 goto not_found;
4083 }
4084
4085 memcpy(orig.data, cid, cid_len);
4086 orig.len = cid_len;
4087 derive_cid = quic_derive_cid(&orig, cli_addr);
4088
4089 tree = &quic_cid_trees[quic_cid_tree_idx(&derive_cid)];
4090 HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
4091 node = ebmb_lookup(&tree->root, cid, cid_len);
4092 HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
4093 }
4094
4095 if (!node)
4096 goto not_found;
4097
4098 conn_id = ebmb_entry(node, struct quic_connection_id, node);
4099 return HA_ATOMIC_LOAD(&conn_id->tid);
4100
4101 not_found:
4102 return -1;
4103}
4104
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004105/* Allocate a new CID and attach it to <root> ebtree.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004106 *
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004107 * If <orig> and <addr> params are non null, the new CID value is directly
4108 * derived from them. Else a random value is generated. The CID is then marked
4109 * with the current thread ID.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004110 *
4111 * Returns the new CID if succeeded, NULL if not.
4112 */
4113static struct quic_connection_id *new_quic_cid(struct eb_root *root,
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004114 struct quic_conn *qc,
4115 const struct quic_cid *orig,
4116 const struct sockaddr_storage *addr)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004117{
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004118 struct quic_connection_id *conn_id;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004119
4120 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4121
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004122 /* Caller must set either none or both values. */
4123 BUG_ON(!!orig != !!addr);
4124
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004125 conn_id = pool_alloc(pool_head_quic_connection_id);
4126 if (!conn_id) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004127 TRACE_ERROR("cid allocation failed", QUIC_EV_CONN_TXPKT, qc);
4128 goto err;
4129 }
4130
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004131 conn_id->cid.len = QUIC_HAP_CID_LEN;
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004132
4133 if (!orig) {
4134 /* TODO: RAND_bytes() should be replaced */
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004135 if (RAND_bytes(conn_id->cid.data, conn_id->cid.len) != 1) {
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004136 TRACE_ERROR("RAND_bytes() failed", QUIC_EV_CONN_TXPKT, qc);
4137 goto err;
4138 }
Amaury Denoyelle162baaf2023-04-03 18:49:39 +02004139 }
4140 else {
4141 /* Derive the new CID value from original CID. */
Amaury Denoyellec2a92642023-04-13 15:26:18 +02004142 conn_id->cid = quic_derive_cid(orig, addr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004143 }
4144
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004145 if (quic_stateless_reset_token_init(conn_id) != 1) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004146 TRACE_ERROR("quic_stateless_reset_token_init() failed", QUIC_EV_CONN_TXPKT, qc);
4147 goto err;
4148 }
4149
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004150 conn_id->qc = qc;
Amaury Denoyellee83f9372023-04-18 11:10:54 +02004151 HA_ATOMIC_STORE(&conn_id->tid, tid);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004152
Amaury Denoyellef16ec342023-04-13 17:42:34 +02004153 conn_id->seq_num.key = qc ? qc->next_cid_seq_num++ : 0;
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004154 conn_id->retire_prior_to = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004155 /* insert the allocated CID in the quic_conn tree */
Amaury Denoyellef16ec342023-04-13 17:42:34 +02004156 if (root)
4157 eb64_insert(root, &conn_id->seq_num);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004158
4159 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004160 return conn_id;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004161
4162 err:
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004163 pool_free(pool_head_quic_connection_id, conn_id);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004164 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4165 return NULL;
4166}
4167
4168/* Build all the frames which must be sent just after the handshake have succeeded.
4169 * This is essentially NEW_CONNECTION_ID frames. A QUIC server must also send
4170 * a HANDSHAKE_DONE frame.
4171 * Return 1 if succeeded, 0 if not.
4172 */
4173static int quic_build_post_handshake_frames(struct quic_conn *qc)
4174{
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004175 int ret = 0, max;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004176 struct quic_enc_level *qel;
4177 struct quic_frame *frm, *frmbak;
4178 struct list frm_list = LIST_HEAD_INIT(frm_list);
4179 struct eb64_node *node;
4180
4181 TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
4182
4183 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4184 /* Only servers must send a HANDSHAKE_DONE frame. */
4185 if (qc_is_listener(qc)) {
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01004186 frm = qc_frm_alloc(QUIC_FT_HANDSHAKE_DONE);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004187 if (!frm) {
4188 TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
4189 goto leave;
4190 }
4191
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004192 LIST_APPEND(&frm_list, &frm->list);
4193 }
4194
4195 /* Initialize <max> connection IDs minus one: there is
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004196 * already one connection ID used for the current connection. Also limit
4197 * the number of connection IDs sent to the peer to 4 (3 from this function
4198 * plus 1 for the current connection.
4199 * Note that active_connection_id_limit >= 2: this has been already checked
4200 * when receiving this parameter.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004201 */
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004202 max = QUIC_MIN(qc->tx.params.active_connection_id_limit - 1, (uint64_t)3);
4203 while (max--) {
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004204 struct quic_connection_id *conn_id;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004205
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01004206 frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004207 if (!frm) {
4208 TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
4209 goto err;
4210 }
4211
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004212 conn_id = new_quic_cid(&qc->cids, qc, NULL, NULL);
4213 if (!conn_id) {
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01004214 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004215 TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc);
4216 goto err;
4217 }
4218
Amaury Denoyellee83f9372023-04-18 11:10:54 +02004219 /* TODO To prevent CID tree locking, all CIDs created here
4220 * could be allocated at the same time as the first one.
4221 */
4222 quic_cid_insert(conn_id);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004223
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004224 quic_connection_id_to_frm_cpy(frm, conn_id);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004225 LIST_APPEND(&frm_list, &frm->list);
4226 }
4227
4228 LIST_SPLICE(&qel->pktns->tx.frms, &frm_list);
Amaury Denoyelle1304d192023-04-11 16:46:03 +02004229 qc->flags &= ~QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004230
4231 ret = 1;
4232 leave:
4233 TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
4234 return ret;
4235
4236 err:
4237 /* free the frames */
4238 list_for_each_entry_safe(frm, frmbak, &frm_list, list)
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01004239 qc_frm_free(&frm);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004240
Frédéric Lécailleb4c54712023-03-06 14:07:59 +01004241 /* The first CID sequence number value used to allocated CIDs by this function is 1,
4242 * 0 being the sequence number of the CID for this connection.
4243 */
4244 node = eb64_lookup_ge(&qc->cids, 1);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004245 while (node) {
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004246 struct quic_connection_id *conn_id;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004247
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004248 conn_id = eb64_entry(node, struct quic_connection_id, seq_num);
4249 if (conn_id->seq_num.key >= max)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004250 break;
4251
4252 node = eb64_next(node);
Amaury Denoyellee83f9372023-04-18 11:10:54 +02004253 quic_cid_delete(conn_id);
4254
Amaury Denoyelle591e7982023-04-12 10:04:49 +02004255 eb64_delete(&conn_id->seq_num);
4256 pool_free(pool_head_quic_connection_id, conn_id);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004257 }
4258 goto leave;
4259}
4260
4261/* Deallocate <l> list of ACK ranges. */
4262void quic_free_arngs(struct quic_conn *qc, struct quic_arngs *arngs)
4263{
4264 struct eb64_node *n;
4265 struct quic_arng_node *ar;
4266
4267 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
4268
4269 n = eb64_first(&arngs->root);
4270 while (n) {
4271 struct eb64_node *next;
4272
4273 ar = eb64_entry(n, struct quic_arng_node, first);
4274 next = eb64_next(n);
4275 eb64_delete(n);
4276 pool_free(pool_head_quic_arng, ar);
4277 n = next;
4278 }
4279
4280 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
4281}
4282
4283/* Return the gap value between <p> and <q> ACK ranges where <q> follows <p> in
4284 * descending order.
4285 */
4286static inline size_t sack_gap(struct quic_arng_node *p,
4287 struct quic_arng_node *q)
4288{
4289 return p->first.key - q->last - 2;
4290}
4291
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004292/* Set the encoded size of <arngs> QUIC ack ranges. */
4293static void quic_arngs_set_enc_sz(struct quic_conn *qc, struct quic_arngs *arngs)
4294{
4295 struct eb64_node *node, *next;
4296 struct quic_arng_node *ar, *ar_next;
4297
4298 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4299
4300 node = eb64_last(&arngs->root);
4301 if (!node)
4302 goto leave;
4303
4304 ar = eb64_entry(node, struct quic_arng_node, first);
4305 arngs->enc_sz = quic_int_getsize(ar->last) +
4306 quic_int_getsize(ar->last - ar->first.key) + quic_int_getsize(arngs->sz - 1);
4307
4308 while ((next = eb64_prev(node))) {
4309 ar_next = eb64_entry(next, struct quic_arng_node, first);
4310 arngs->enc_sz += quic_int_getsize(sack_gap(ar, ar_next)) +
4311 quic_int_getsize(ar_next->last - ar_next->first.key);
4312 node = next;
4313 ar = eb64_entry(node, struct quic_arng_node, first);
4314 }
4315
4316 leave:
4317 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4318}
4319
4320/* Insert <ar> ack range into <argns> tree of ack ranges.
4321 * Returns the ack range node which has been inserted if succeeded, NULL if not.
4322 */
4323static inline
4324struct quic_arng_node *quic_insert_new_range(struct quic_conn *qc,
4325 struct quic_arngs *arngs,
4326 struct quic_arng *ar)
4327{
4328 struct quic_arng_node *new_ar;
4329
4330 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
4331
Frédéric Lécaille0ed94032023-04-17 14:10:14 +02004332 if (arngs->sz >= QUIC_MAX_ACK_RANGES) {
4333 struct eb64_node *last;
4334
4335 last = eb64_last(&arngs->root);
4336 BUG_ON(last == NULL);
4337 eb64_delete(last);
4338 pool_free(pool_head_quic_arng, last);
4339 arngs->sz--;
4340 }
4341
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004342 new_ar = pool_alloc(pool_head_quic_arng);
4343 if (!new_ar) {
4344 TRACE_ERROR("ack range allocation failed", QUIC_EV_CONN_RXPKT, qc);
4345 goto leave;
4346 }
4347
4348 new_ar->first.key = ar->first;
4349 new_ar->last = ar->last;
4350 eb64_insert(&arngs->root, &new_ar->first);
4351 arngs->sz++;
4352
4353 leave:
4354 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
4355 return new_ar;
4356}
4357
4358/* Update <arngs> tree of ACK ranges with <ar> as new ACK range value.
4359 * Note that this function computes the number of bytes required to encode
4360 * this tree of ACK ranges in descending order.
4361 *
4362 * Descending order
4363 * ------------->
4364 * range1 range2
4365 * ..........|--------|..............|--------|
4366 * ^ ^ ^ ^
4367 * | | | |
4368 * last1 first1 last2 first2
4369 * ..........+--------+--------------+--------+......
4370 * diff1 gap12 diff2
4371 *
4372 * To encode the previous list of ranges we must encode integers as follows in
4373 * descending order:
4374 * enc(last2),enc(diff2),enc(gap12),enc(diff1)
4375 * with diff1 = last1 - first1
4376 * diff2 = last2 - first2
4377 * gap12 = first1 - last2 - 2 (>= 0)
4378 *
4379
4380returns 0 on error
4381
4382 */
4383int quic_update_ack_ranges_list(struct quic_conn *qc,
4384 struct quic_arngs *arngs,
4385 struct quic_arng *ar)
4386{
4387 int ret = 0;
4388 struct eb64_node *le;
4389 struct quic_arng_node *new_node;
4390 struct eb64_node *new;
4391
4392 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
4393
4394 new = NULL;
4395 if (eb_is_empty(&arngs->root)) {
4396 new_node = quic_insert_new_range(qc, arngs, ar);
4397 if (new_node)
4398 ret = 1;
4399
4400 goto leave;
4401 }
4402
4403 le = eb64_lookup_le(&arngs->root, ar->first);
4404 if (!le) {
4405 new_node = quic_insert_new_range(qc, arngs, ar);
4406 if (!new_node)
4407 goto leave;
4408
4409 new = &new_node->first;
4410 }
4411 else {
4412 struct quic_arng_node *le_ar =
4413 eb64_entry(le, struct quic_arng_node, first);
4414
4415 /* Already existing range */
4416 if (le_ar->last >= ar->last) {
4417 ret = 1;
4418 }
4419 else if (le_ar->last + 1 >= ar->first) {
4420 le_ar->last = ar->last;
4421 new = le;
4422 new_node = le_ar;
4423 }
4424 else {
4425 new_node = quic_insert_new_range(qc, arngs, ar);
4426 if (!new_node)
4427 goto leave;
4428
4429 new = &new_node->first;
4430 }
4431 }
4432
4433 /* Verify that the new inserted node does not overlap the nodes
4434 * which follow it.
4435 */
4436 if (new) {
4437 struct eb64_node *next;
4438 struct quic_arng_node *next_node;
4439
4440 while ((next = eb64_next(new))) {
4441 next_node =
4442 eb64_entry(next, struct quic_arng_node, first);
4443 if (new_node->last + 1 < next_node->first.key)
4444 break;
4445
4446 if (next_node->last > new_node->last)
4447 new_node->last = next_node->last;
4448 eb64_delete(next);
4449 pool_free(pool_head_quic_arng, next_node);
4450 /* Decrement the size of these ranges. */
4451 arngs->sz--;
4452 }
4453 }
4454
4455 ret = 1;
4456 leave:
4457 quic_arngs_set_enc_sz(qc, arngs);
4458 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
4459 return ret;
4460}
Frédéric Lécailleece86e62023-03-07 11:53:43 +01004461
4462/* Detect the value of the spin bit to be used. */
4463static inline void qc_handle_spin_bit(struct quic_conn *qc, struct quic_rx_packet *pkt,
4464 struct quic_enc_level *qel)
4465{
4466 uint64_t largest_pn = qel->pktns->rx.largest_pn;
4467
4468 if (qel != &qc->els[QUIC_TLS_ENC_LEVEL_APP] || largest_pn == -1 ||
4469 pkt->pn <= largest_pn)
4470 return;
4471
4472 if (qc_is_listener(qc)) {
4473 if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
4474 qc->flags |= QUIC_FL_CONN_SPIN_BIT;
4475 else
4476 qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
4477 }
4478 else {
4479 if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
4480 qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
4481 else
4482 qc->flags |= QUIC_FL_CONN_SPIN_BIT;
4483 }
4484}
4485
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004486/* Remove the header protection of packets at <el> encryption level.
4487 * Always succeeds.
4488 */
4489static inline void qc_rm_hp_pkts(struct quic_conn *qc, struct quic_enc_level *el)
4490{
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004491 struct quic_rx_packet *pqpkt, *pkttmp;
4492 struct quic_enc_level *app_qel;
4493
4494 TRACE_ENTER(QUIC_EV_CONN_ELRMHP, qc);
4495 app_qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4496 /* A server must not process incoming 1-RTT packets before the handshake is complete. */
4497 if (el == app_qel && qc_is_listener(qc) && qc->state < QUIC_HS_ST_COMPLETE) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004498 TRACE_PROTO("RX hp not removed (handshake not completed)",
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004499 QUIC_EV_CONN_ELRMHP, qc);
4500 goto out;
4501 }
Frédéric Lécaille72027782023-02-22 16:20:09 +01004502
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004503 list_for_each_entry_safe(pqpkt, pkttmp, &el->rx.pqpkts, list) {
Frédéric Lécaille72027782023-02-22 16:20:09 +01004504 struct quic_tls_ctx *tls_ctx;
4505
4506 tls_ctx = qc_select_tls_ctx(qc, el, pqpkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004507 if (!qc_do_rm_hp(qc, pqpkt, tls_ctx, el->pktns->rx.largest_pn,
4508 pqpkt->data + pqpkt->pn_offset, pqpkt->data)) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004509 TRACE_ERROR("RX hp removing error", QUIC_EV_CONN_ELRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004510 }
4511 else {
Frédéric Lécailleece86e62023-03-07 11:53:43 +01004512 qc_handle_spin_bit(qc, pqpkt, el);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004513 /* The AAD includes the packet number field */
4514 pqpkt->aad_len = pqpkt->pn_offset + pqpkt->pnl;
4515 /* Store the packet into the tree of packets to decrypt. */
4516 pqpkt->pn_node.key = pqpkt->pn;
4517 eb64_insert(&el->rx.pkts, &pqpkt->pn_node);
4518 quic_rx_packet_refinc(pqpkt);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004519 TRACE_PROTO("RX hp removed", QUIC_EV_CONN_ELRMHP, qc, pqpkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004520 }
4521 LIST_DELETE(&pqpkt->list);
4522 quic_rx_packet_refdec(pqpkt);
4523 }
4524
4525 out:
4526 TRACE_LEAVE(QUIC_EV_CONN_ELRMHP, qc);
4527}
4528
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004529/* Process all the CRYPTO frame at <el> encryption level. This is the
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05004530 * responsibility of the called to ensure there exists a CRYPTO data
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004531 * stream for this level.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004532 * Return 1 if succeeded, 0 if not.
4533 */
4534static inline int qc_treat_rx_crypto_frms(struct quic_conn *qc,
4535 struct quic_enc_level *el,
4536 struct ssl_sock_ctx *ctx)
4537{
4538 int ret = 0;
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004539 struct ncbuf *ncbuf;
4540 struct quic_cstream *cstream = el->cstream;
4541 ncb_sz_t data;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004542
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004543 TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004544
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004545 BUG_ON(!cstream);
4546 ncbuf = &cstream->rx.ncbuf;
4547 if (ncb_is_null(ncbuf))
4548 goto done;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004549
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004550 /* TODO not working if buffer is wrapping */
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004551 while ((data = ncb_data(ncbuf, 0))) {
4552 const unsigned char *cdata = (const unsigned char *)ncb_head(ncbuf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004553
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004554 if (!qc_provide_cdata(el, ctx, cdata, data, NULL, NULL))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004555 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004556
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004557 cstream->rx.offset += data;
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004558 TRACE_DEVEL("buffered crypto data were provided to TLS stack",
4559 QUIC_EV_CONN_PHPKTS, qc, el);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004560 }
4561
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004562 done:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004563 ret = 1;
4564 leave:
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004565 if (!ncb_is_null(ncbuf) && ncb_is_empty(ncbuf)) {
4566 TRACE_DEVEL("freeing crypto buf", QUIC_EV_CONN_PHPKTS, qc, el);
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004567 quic_free_ncbuf(ncbuf);
Amaury Denoyelle2f668f02022-11-18 15:24:08 +01004568 }
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004569 TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004570 return ret;
4571}
4572
4573/* Process all the packets at <el> and <next_el> encryption level.
4574 * This is the caller responsibility to check that <cur_el> is different of <next_el>
4575 * as pointer value.
4576 * Return 1 if succeeded, 0 if not.
4577 */
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004578int qc_treat_rx_pkts(struct quic_conn *qc, struct quic_enc_level *cur_el,
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01004579 struct quic_enc_level *next_el)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004580{
4581 int ret = 0;
4582 struct eb64_node *node;
4583 int64_t largest_pn = -1;
4584 unsigned int largest_pn_time_received = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004585 struct quic_enc_level *qel = cur_el;
4586
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004587 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004588 qel = cur_el;
4589 next_tel:
4590 if (!qel)
4591 goto out;
4592
4593 node = eb64_first(&qel->rx.pkts);
4594 while (node) {
4595 struct quic_rx_packet *pkt;
4596
4597 pkt = eb64_entry(node, struct quic_rx_packet, pn_node);
4598 TRACE_DATA("new packet", QUIC_EV_CONN_RXPKT,
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004599 qc, pkt, NULL, qc->xprt_ctx->ssl);
Amaury Denoyelle518c98f2022-11-24 17:12:25 +01004600 if (!qc_pkt_decrypt(qc, qel, pkt)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004601 /* Drop the packet */
4602 TRACE_ERROR("packet decryption failed -> dropped",
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004603 QUIC_EV_CONN_RXPKT, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004604 }
4605 else {
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004606 if (!qc_parse_pkt_frms(qc, pkt, qel)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004607 /* Drop the packet */
4608 TRACE_ERROR("packet parsing failed -> dropped",
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004609 QUIC_EV_CONN_RXPKT, qc, pkt);
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02004610 qc->cntrs.dropped_parsing++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004611 }
4612 else {
4613 struct quic_arng ar = { .first = pkt->pn, .last = pkt->pn };
4614
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01004615 if (pkt->flags & QUIC_FL_RX_PACKET_ACK_ELICITING) {
Frédéric Lécailleb5efe792023-04-14 09:56:17 +02004616 int arm_ack_timer =
4617 qc->state >= QUIC_HS_ST_COMPLETE &&
4618 qel->pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT];
4619
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004620 qel->pktns->flags |= QUIC_FL_PKTNS_ACK_REQUIRED;
4621 qel->pktns->rx.nb_aepkts_since_last_ack++;
Frédéric Lécailleb5efe792023-04-14 09:56:17 +02004622 qc_idle_timer_rearm(qc, 1, arm_ack_timer);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004623 }
4624 if (pkt->pn > largest_pn) {
4625 largest_pn = pkt->pn;
4626 largest_pn_time_received = pkt->time_received;
4627 }
4628 /* Update the list of ranges to acknowledge. */
4629 if (!quic_update_ack_ranges_list(qc, &qel->pktns->rx.arngs, &ar))
4630 TRACE_ERROR("Could not update ack range list",
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004631 QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004632 }
4633 }
4634 node = eb64_next(node);
4635 eb64_delete(&pkt->pn_node);
4636 quic_rx_packet_refdec(pkt);
4637 }
4638
4639 if (largest_pn != -1 && largest_pn > qel->pktns->rx.largest_pn) {
4640 /* Update the largest packet number. */
4641 qel->pktns->rx.largest_pn = largest_pn;
4642 /* Update the largest acknowledged packet timestamps */
4643 qel->pktns->rx.largest_time_received = largest_pn_time_received;
4644 qel->pktns->flags |= QUIC_FL_PKTNS_NEW_LARGEST_PN;
4645 }
4646
Frédéric Lécaille9f9263e2022-09-13 14:36:44 +02004647 if (qel->cstream && !qc_treat_rx_crypto_frms(qc, qel, qc->xprt_ctx)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004648 // trace already emitted by function above
4649 goto leave;
4650 }
4651
4652 if (qel == cur_el) {
4653 BUG_ON(qel == next_el);
4654 qel = next_el;
4655 largest_pn = -1;
4656 goto next_tel;
4657 }
4658
4659 out:
4660 ret = 1;
4661 leave:
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02004662 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004663 return ret;
4664}
4665
4666/* Check if it's possible to remove header protection for packets related to
4667 * encryption level <qel>. If <qel> is NULL, assume it's false.
4668 *
4669 * Return true if the operation is possible else false.
4670 */
4671static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel)
4672{
4673 int ret = 0;
4674 enum quic_tls_enc_level tel;
4675
4676 TRACE_ENTER(QUIC_EV_CONN_TRMHP, qc);
4677
4678 if (!qel)
4679 goto cant_rm_hp;
4680
4681 tel = ssl_to_quic_enc_level(qel->level);
4682
4683 /* check if tls secrets are available */
4684 if (qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004685 TRACE_PROTO("Discarded keys", QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004686 goto cant_rm_hp;
4687 }
4688
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02004689 if (!quic_tls_has_rx_sec(qel)) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004690 TRACE_PROTO("non available secrets", QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004691 goto cant_rm_hp;
4692 }
4693
Frédéric Lécaille8417beb2023-02-01 10:31:35 +01004694 if (tel == QUIC_TLS_ENC_LEVEL_APP && qc->state < QUIC_HS_ST_COMPLETE) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004695 TRACE_PROTO("handshake not complete", QUIC_EV_CONN_TRMHP, qc);
Frédéric Lécaille8417beb2023-02-01 10:31:35 +01004696 goto cant_rm_hp;
4697 }
4698
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004699 /* check if the connection layer is ready before using app level */
4700 if ((tel == QUIC_TLS_ENC_LEVEL_APP || tel == QUIC_TLS_ENC_LEVEL_EARLY_DATA) &&
4701 qc->mux_state == QC_MUX_NULL) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01004702 TRACE_PROTO("connection layer not ready", QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004703 goto cant_rm_hp;
4704 }
4705
4706 ret = 1;
4707 cant_rm_hp:
4708 TRACE_LEAVE(QUIC_EV_CONN_TRMHP, qc);
4709 return ret;
4710}
4711
Amaury Denoyelle147862d2023-02-28 15:10:00 +01004712/* Flush txbuf for <qc> connection. This must be called prior to a packet
4713 * preparation when txbuf contains older data. A send will be conducted for
4714 * these data.
4715 *
4716 * Returns 1 on success : buffer is empty and can be use for packet
4717 * preparation. On error 0 is returned.
4718 */
4719static int qc_purge_txbuf(struct quic_conn *qc, struct buffer *buf)
4720{
4721 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4722
4723 /* This operation can only be conducted if txbuf is not empty. This
4724 * case only happens for connection with their owned socket due to an
4725 * older transient sendto() error.
4726 */
4727 BUG_ON(!qc_test_fd(qc));
4728
4729 if (b_data(buf) && !qc_send_ppkts(buf, qc->xprt_ctx)) {
4730 if (qc->flags & QUIC_FL_CONN_TO_KILL)
4731 qc_txb_release(qc);
4732 TRACE_DEVEL("leaving in error", QUIC_EV_CONN_TXPKT, qc);
4733 return 0;
4734 }
4735
4736 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4737 return 1;
4738}
4739
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004740/* Try to send application frames from list <frms> on connection <qc>.
4741 *
4742 * Use qc_send_app_probing wrapper when probing with old data.
4743 *
4744 * Returns 1 on success. Some data might not have been sent due to congestion,
4745 * in this case they are left in <frms> input list. The caller may subscribe on
4746 * quic-conn to retry later.
4747 *
4748 * Returns 0 on critical error.
4749 * TODO review and classify more distinctly transient from definitive errors to
4750 * allow callers to properly handle it.
4751 */
4752static int qc_send_app_pkts(struct quic_conn *qc, struct list *frms)
4753{
Amaury Denoyelle7385ff32023-04-19 15:56:30 +02004754 int status = 0, ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004755 struct buffer *buf;
4756
4757 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4758
4759 buf = qc_txb_alloc(qc);
4760 if (!buf) {
4761 TRACE_ERROR("buffer allocation failed", QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyelle37333862023-02-28 11:53:48 +01004762 goto err;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004763 }
4764
Amaury Denoyelle147862d2023-02-28 15:10:00 +01004765 if (b_data(buf) && !qc_purge_txbuf(qc, buf))
4766 goto err;
4767
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004768 /* Prepare and send packets until we could not further prepare packets. */
Amaury Denoyelle7385ff32023-04-19 15:56:30 +02004769 do {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004770 /* Currently buf cannot be non-empty at this stage. Even if a
4771 * previous sendto() has failed it is emptied to simulate
4772 * packet emission and rely on QUIC lost detection to try to
4773 * emit it.
4774 */
4775 BUG_ON_HOT(b_data(buf));
4776 b_reset(buf);
4777
4778 ret = qc_prep_app_pkts(qc, buf, frms);
Amaury Denoyelle37333862023-02-28 11:53:48 +01004779
Amaury Denoyelle7385ff32023-04-19 15:56:30 +02004780 if (b_data(buf) && !qc_send_ppkts(buf, qc->xprt_ctx)) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01004781 if (qc->flags & QUIC_FL_CONN_TO_KILL)
4782 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004783 goto err;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004784 }
Amaury Denoyelle7385ff32023-04-19 15:56:30 +02004785 } while (ret > 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004786
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004787 qc_txb_release(qc);
Amaury Denoyelle7385ff32023-04-19 15:56:30 +02004788 if (ret < 0)
4789 goto err;
4790
4791 status = 1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004792 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4793 return status;
4794
4795 err:
Amaury Denoyelle37333862023-02-28 11:53:48 +01004796 TRACE_DEVEL("leaving in error", QUIC_EV_CONN_TXPKT, qc);
4797 return 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004798}
4799
4800/* Try to send application frames from list <frms> on connection <qc>. Use this
4801 * function when probing is required.
4802 *
4803 * Returns the result from qc_send_app_pkts function.
4804 */
4805static forceinline int qc_send_app_probing(struct quic_conn *qc,
4806 struct list *frms)
4807{
4808 int ret;
4809
4810 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4811
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02004812 TRACE_PROTO("preparing old data (probing)", QUIC_EV_CONN_FRMLIST, qc, frms);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004813 qc->flags |= QUIC_FL_CONN_RETRANS_OLD_DATA;
4814 ret = qc_send_app_pkts(qc, frms);
4815 qc->flags &= ~QUIC_FL_CONN_RETRANS_OLD_DATA;
4816
4817 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4818 return ret;
4819}
4820
4821/* Try to send application frames from list <frms> on connection <qc>. This
4822 * function is provided for MUX upper layer usage only.
4823 *
4824 * Returns the result from qc_send_app_pkts function.
4825 */
4826int qc_send_mux(struct quic_conn *qc, struct list *frms)
4827{
4828 int ret;
4829
4830 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4831 BUG_ON(qc->mux_state != QC_MUX_READY); /* Only MUX can uses this function so it must be ready. */
4832
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02004833 if (qc->conn->flags & CO_FL_SOCK_WR_SH) {
4834 qc->conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH;
4835 TRACE_DEVEL("connection on error", QUIC_EV_CONN_TXPKT, qc);
4836 return 0;
4837 }
4838
Amaury Denoyelle1304d192023-04-11 16:46:03 +02004839 /* Try to send post handshake frames first unless on 0-RTT. */
4840 if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) &&
4841 qc->state >= QUIC_HS_ST_COMPLETE) {
4842 struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4843 quic_build_post_handshake_frames(qc);
4844 qc_send_app_pkts(qc, &qel->pktns->tx.frms);
4845 }
4846
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004847 TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc);
4848 qc->flags |= QUIC_FL_CONN_TX_MUX_CONTEXT;
4849 ret = qc_send_app_pkts(qc, frms);
4850 qc->flags &= ~QUIC_FL_CONN_TX_MUX_CONTEXT;
4851
4852 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4853 return ret;
4854}
4855
4856/* Sends handshake packets from up to two encryption levels <tel> and <next_te>
4857 * with <tel_frms> and <next_tel_frms> as frame list respectively for <qc>
4858 * QUIC connection. <old_data> is used as boolean to send data already sent but
4859 * not already acknowledged (in flight).
4860 * Returns 1 if succeeded, 0 if not.
4861 */
4862int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
4863 enum quic_tls_enc_level tel, struct list *tel_frms,
4864 enum quic_tls_enc_level next_tel, struct list *next_tel_frms)
4865{
4866 int ret, status = 0;
4867 struct buffer *buf = qc_txb_alloc(qc);
4868
4869 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4870
4871 if (!buf) {
4872 TRACE_ERROR("buffer allocation failed", QUIC_EV_CONN_TXPKT, qc);
4873 goto leave;
4874 }
4875
Amaury Denoyelle147862d2023-02-28 15:10:00 +01004876 if (b_data(buf) && !qc_purge_txbuf(qc, buf))
4877 goto out;
4878
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004879 /* Currently buf cannot be non-empty at this stage. Even if a previous
4880 * sendto() has failed it is emptied to simulate packet emission and
4881 * rely on QUIC lost detection to try to emit it.
4882 */
4883 BUG_ON_HOT(b_data(buf));
4884 b_reset(buf);
4885
4886 if (old_data) {
4887 TRACE_STATE("old data for probing asked", QUIC_EV_CONN_TXPKT, qc);
4888 qc->flags |= QUIC_FL_CONN_RETRANS_OLD_DATA;
4889 }
4890
4891 ret = qc_prep_pkts(qc, buf, tel, tel_frms, next_tel, next_tel_frms);
Amaury Denoyelle37333862023-02-28 11:53:48 +01004892 if (ret == -1) {
4893 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004894 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004895 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004896
Amaury Denoyelle37333862023-02-28 11:53:48 +01004897 if (ret && !qc_send_ppkts(buf, qc->xprt_ctx)) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01004898 if (qc->flags & QUIC_FL_CONN_TO_KILL)
4899 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004900 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004901 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004902
Amaury Denoyelle37333862023-02-28 11:53:48 +01004903 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004904 status = 1;
Amaury Denoyelle37333862023-02-28 11:53:48 +01004905
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004906 out:
4907 TRACE_STATE("no more need old data for probing", QUIC_EV_CONN_TXPKT, qc);
4908 qc->flags &= ~QUIC_FL_CONN_RETRANS_OLD_DATA;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004909 leave:
4910 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4911 return status;
4912}
4913
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004914/* Retransmit up to two datagrams depending on packet number space.
4915 * Return 0 when failed, 0 if not.
4916 */
4917static int qc_dgrams_retransmit(struct quic_conn *qc)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004918{
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004919 int ret = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004920 struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
4921 struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
4922 struct quic_enc_level *aqel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4923
4924 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
4925
4926 if (iqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
Frédéric Lécaille37ed4a32023-01-31 17:32:06 +01004927 int i;
4928
4929 for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
4930 struct list ifrms = LIST_HEAD_INIT(ifrms);
4931 struct list hfrms = LIST_HEAD_INIT(hfrms);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004932
Frédéric Lécaille37ed4a32023-01-31 17:32:06 +01004933 qc_prep_hdshk_fast_retrans(qc, &ifrms, &hfrms);
4934 TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &ifrms);
4935 TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &hfrms);
4936 if (!LIST_ISEMPTY(&ifrms)) {
4937 iqel->pktns->tx.pto_probe = 1;
4938 if (!LIST_ISEMPTY(&hfrms))
4939 hqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004940 if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms,
4941 QUIC_TLS_ENC_LEVEL_HANDSHAKE, &hfrms))
4942 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004943 /* Put back unsent frames in their packet number spaces */
4944 LIST_SPLICE(&iqel->pktns->tx.frms, &ifrms);
4945 LIST_SPLICE(&hqel->pktns->tx.frms, &hfrms);
4946 }
Frédéric Lécailleec937212023-03-03 17:34:41 +01004947 else {
4948 if (!(qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED)) {
4949 iqel->pktns->tx.pto_probe = 1;
4950 if (!qc_send_hdshk_pkts(qc, 0, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms,
4951 QUIC_TLS_ENC_LEVEL_NONE, NULL))
4952 goto leave;
4953 }
4954 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004955 }
4956 TRACE_STATE("no more need to probe Initial packet number space",
4957 QUIC_EV_CONN_TXPKT, qc);
4958 iqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
Frédéric Lécaille37ed4a32023-01-31 17:32:06 +01004959 hqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004960 }
4961 else {
4962 int i;
4963
4964 if (hqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004965 hqel->pktns->tx.pto_probe = 0;
4966 for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
Frédéric Lécaille7b5d9b12022-11-28 17:21:45 +01004967 struct list frms1 = LIST_HEAD_INIT(frms1);
4968
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004969 qc_prep_fast_retrans(qc, hqel, &frms1, NULL);
4970 TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
4971 if (!LIST_ISEMPTY(&frms1)) {
4972 hqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004973 if (!qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_HANDSHAKE, &frms1,
4974 QUIC_TLS_ENC_LEVEL_NONE, NULL))
4975 goto leave;
4976
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02004977 /* Put back unsent frames into their packet number spaces */
4978 LIST_SPLICE(&hqel->pktns->tx.frms, &frms1);
4979 }
4980 }
4981 TRACE_STATE("no more need to probe Handshake packet number space",
4982 QUIC_EV_CONN_TXPKT, qc);
4983 hqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
4984 }
4985 else if (aqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
4986 struct list frms2 = LIST_HEAD_INIT(frms2);
4987 struct list frms1 = LIST_HEAD_INIT(frms1);
4988
4989 aqel->pktns->tx.pto_probe = 0;
4990 qc_prep_fast_retrans(qc, aqel, &frms1, &frms2);
4991 TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
4992 TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms2);
4993 if (!LIST_ISEMPTY(&frms1)) {
4994 aqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillec6bec2a2023-04-24 11:20:32 +02004995 if (!qc_send_app_probing(qc, &frms1)) {
Frédéric Lécaillee66d67a2023-04-24 12:05:46 +02004996 qc_free_frm_list(&frms2);
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004997 goto leave;
Frédéric Lécaillec6bec2a2023-04-24 11:20:32 +02004998 }
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01004999
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005000 /* Put back unsent frames into their packet number spaces */
5001 LIST_SPLICE(&aqel->pktns->tx.frms, &frms1);
5002 }
5003 if (!LIST_ISEMPTY(&frms2)) {
5004 aqel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01005005 if (!qc_send_app_probing(qc, &frms2))
5006 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005007 /* Put back unsent frames into their packet number spaces */
5008 LIST_SPLICE(&aqel->pktns->tx.frms, &frms2);
5009 }
5010 TRACE_STATE("no more need to probe 01RTT packet number space",
5011 QUIC_EV_CONN_TXPKT, qc);
5012 aqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
5013 }
5014 }
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01005015
5016 ret = 1;
5017 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005018 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01005019 return ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005020}
5021
5022/* QUIC connection packet handler task (post handshake) */
5023struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state)
5024{
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005025 struct quic_conn *qc = context;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005026 struct quic_enc_level *qel;
5027
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005028 TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
Amaury Denoyelle25174d52023-04-05 17:52:05 +02005029
5030 qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005031 TRACE_STATE("connection handshake state", QUIC_EV_CONN_IO_CB, qc, &qc->state);
5032
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01005033 if (qc_test_fd(qc))
5034 qc_rcv_buf(qc);
5035
Amaury Denoyelle1304d192023-04-11 16:46:03 +02005036 /* Prepare post-handshake frames
5037 * - after connection is instantiated (accept is done)
5038 * - handshake state is completed (may not be the case here in 0-RTT)
5039 */
5040 if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) && qc->conn &&
5041 qc->state >= QUIC_HS_ST_COMPLETE) {
5042 quic_build_post_handshake_frames(qc);
5043 }
5044
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005045 /* Retranmissions */
5046 if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
5047 TRACE_STATE("retransmission needed", QUIC_EV_CONN_IO_CB, qc);
5048 qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01005049 if (!qc_dgrams_retransmit(qc))
5050 goto out;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005051 }
5052
5053 if (!LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel))
5054 qc_rm_hp_pkts(qc, qel);
5055
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01005056 if (!qc_treat_rx_pkts(qc, qel, NULL)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005057 TRACE_DEVEL("qc_treat_rx_pkts() failed", QUIC_EV_CONN_IO_CB, qc);
5058 goto out;
5059 }
5060
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01005061 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
5062 TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_IO_CB, qc);
5063 goto out;
5064 }
5065
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005066 if ((qc->flags & QUIC_FL_CONN_DRAINING) &&
5067 !(qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)) {
5068 TRACE_STATE("draining connection (must not send packets)", QUIC_EV_CONN_IO_CB, qc);
5069 goto out;
5070 }
5071
5072 /* XXX TODO: how to limit the list frames to send */
5073 if (!qc_send_app_pkts(qc, &qel->pktns->tx.frms)) {
5074 TRACE_DEVEL("qc_send_app_pkts() failed", QUIC_EV_CONN_IO_CB, qc);
5075 goto out;
5076 }
5077
5078 out:
5079 TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
5080 return t;
5081}
5082
5083/* Returns a boolean if <qc> needs to emit frames for <qel> encryption level. */
5084static int qc_need_sending(struct quic_conn *qc, struct quic_enc_level *qel)
5085{
5086 return (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) ||
5087 (qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) ||
5088 qel->pktns->tx.pto_probe ||
5089 !LIST_ISEMPTY(&qel->pktns->tx.frms);
5090}
5091
5092/* QUIC connection packet handler task. */
5093struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
5094{
5095 int ret, ssl_err;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005096 struct quic_conn *qc = context;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005097 enum quic_tls_enc_level tel, next_tel;
5098 struct quic_enc_level *qel, *next_qel;
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005099 /* Early-data encryption level */
5100 struct quic_enc_level *eqel;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005101 struct buffer *buf = NULL;
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01005102 int st, zero_rtt;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005103
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005104 TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
Amaury Denoyelle25174d52023-04-05 17:52:05 +02005105
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005106 eqel = &qc->els[QUIC_TLS_ENC_LEVEL_EARLY_DATA];
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005107 st = qc->state;
5108 TRACE_PROTO("connection state", QUIC_EV_CONN_IO_CB, qc, &st);
5109
5110 /* Retranmissions */
5111 if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
5112 TRACE_DEVEL("retransmission needed", QUIC_EV_CONN_PHPKTS, qc);
5113 qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED;
Frédéric Lécaillee1738df2023-02-10 14:46:39 +01005114 if (!qc_dgrams_retransmit(qc))
5115 goto out;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005116 }
5117
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005118 ssl_err = SSL_ERROR_NONE;
5119 zero_rtt = st < QUIC_HS_ST_COMPLETE &&
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005120 quic_tls_has_rx_sec(eqel) &&
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005121 (!LIST_ISEMPTY(&eqel->rx.pqpkts) || qc_el_rx_pkts(eqel));
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01005122
5123 if (qc_test_fd(qc))
5124 qc_rcv_buf(qc);
5125
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005126 if (st >= QUIC_HS_ST_COMPLETE &&
5127 qc_el_rx_pkts(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE])) {
5128 TRACE_DEVEL("remaining Handshake packets", QUIC_EV_CONN_PHPKTS, qc);
5129 /* There may be remaining Handshake packets to treat and acknowledge. */
5130 tel = QUIC_TLS_ENC_LEVEL_HANDSHAKE;
5131 next_tel = QUIC_TLS_ENC_LEVEL_APP;
5132 }
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005133 else if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, zero_rtt))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005134 goto out;
5135
5136 qel = &qc->els[tel];
5137 next_qel = next_tel == QUIC_TLS_ENC_LEVEL_NONE ? NULL : &qc->els[next_tel];
5138
5139 next_level:
5140 /* Treat packets waiting for header packet protection decryption */
5141 if (!LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel))
5142 qc_rm_hp_pkts(qc, qel);
5143
Frédéric Lécailleb3562a32023-02-25 11:27:34 +01005144 if (!qc_treat_rx_pkts(qc, qel, next_qel))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005145 goto out;
5146
Frédéric Lécaille0aa79952023-02-03 16:15:08 +01005147 if (qc->flags & QUIC_FL_CONN_TO_KILL) {
5148 TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_PHPKTS, qc);
5149 goto out;
5150 }
5151
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005152 if ((qc->flags & QUIC_FL_CONN_DRAINING) &&
5153 !(qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE))
5154 goto out;
5155
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005156 zero_rtt = st < QUIC_HS_ST_COMPLETE &&
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005157 quic_tls_has_rx_sec(eqel) &&
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005158 (!LIST_ISEMPTY(&eqel->rx.pqpkts) || qc_el_rx_pkts(eqel));
5159 if (next_qel && next_qel == eqel && zero_rtt) {
5160 TRACE_DEVEL("select 0RTT as next encryption level",
5161 QUIC_EV_CONN_PHPKTS, qc);
5162 qel = next_qel;
5163 next_qel = NULL;
5164 goto next_level;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005165 }
5166
5167 st = qc->state;
5168 if (st >= QUIC_HS_ST_COMPLETE) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005169 if (!(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].tls_ctx.flags &
5170 QUIC_FL_TLS_SECRETS_DCD)) {
5171 /* Discard the Handshake keys. */
5172 quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]);
5173 TRACE_PROTO("discarding Handshake pktns", QUIC_EV_CONN_PHPKTS, qc);
5174 quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns, qc);
5175 qc_set_timer(qc);
5176 qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]);
5177 qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns);
5178 }
5179
5180 if (qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) {
5181 /* There may be remaining handshake to build (acks) */
5182 st = QUIC_HS_ST_SERVER_HANDSHAKE;
5183 }
5184 }
5185
5186 /* A listener does not send any O-RTT packet. O-RTT packet number space must not
5187 * be considered.
5188 */
Frédéric Lécaille4aa7d812022-09-16 10:15:58 +02005189 if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, 0))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005190 goto out;
5191
5192 if (!qc_need_sending(qc, qel) &&
5193 (!next_qel || !qc_need_sending(qc, next_qel))) {
5194 goto skip_send;
5195 }
5196
5197 buf = qc_txb_alloc(qc);
5198 if (!buf)
5199 goto out;
5200
Amaury Denoyelle147862d2023-02-28 15:10:00 +01005201 if (b_data(buf) && !qc_purge_txbuf(qc, buf))
5202 goto skip_send;
5203
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005204 /* Currently buf cannot be non-empty at this stage. Even if a previous
5205 * sendto() has failed it is emptied to simulate packet emission and
5206 * rely on QUIC lost detection to try to emit it.
5207 */
5208 BUG_ON_HOT(b_data(buf));
5209 b_reset(buf);
5210
5211 ret = qc_prep_pkts(qc, buf, tel, &qc->els[tel].pktns->tx.frms,
5212 next_tel, &qc->els[next_tel].pktns->tx.frms);
Amaury Denoyelle37333862023-02-28 11:53:48 +01005213 if (ret == -1) {
5214 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005215 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01005216 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005217
Amaury Denoyelle37333862023-02-28 11:53:48 +01005218 if (ret && !qc_send_ppkts(buf, qc->xprt_ctx)) {
Amaury Denoyellee1a0ee32023-02-28 15:11:09 +01005219 if (qc->flags & QUIC_FL_CONN_TO_KILL)
5220 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005221 goto out;
Amaury Denoyelle37333862023-02-28 11:53:48 +01005222 }
5223
5224 qc_txb_release(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005225
5226 skip_send:
5227 /* Check if there is something to do for the next level.
5228 */
5229 if (next_qel && next_qel != qel &&
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005230 quic_tls_has_rx_sec(next_qel) &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005231 (!LIST_ISEMPTY(&next_qel->rx.pqpkts) || qc_el_rx_pkts(next_qel))) {
5232 qel = next_qel;
5233 next_qel = NULL;
5234 goto next_level;
5235 }
5236
5237 out:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01005238 TRACE_PROTO("ssl error", QUIC_EV_CONN_IO_CB, qc, &st, &ssl_err);
5239 TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005240 return t;
5241}
5242
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005243/* Release the memory allocated for <cs> CRYPTO stream */
5244void quic_cstream_free(struct quic_cstream *cs)
5245{
5246 if (!cs) {
5247 /* This is the case for ORTT encryption level */
5248 return;
5249 }
5250
Amaury Denoyellebc174b22022-11-17 10:12:52 +01005251 quic_free_ncbuf(&cs->rx.ncbuf);
5252
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005253 qc_stream_desc_release(cs->desc);
5254 pool_free(pool_head_quic_cstream, cs);
5255}
5256
5257/* Allocate a new QUIC stream for <qc>.
5258 * Return it if succeeded, NULL if not.
5259 */
5260struct quic_cstream *quic_cstream_new(struct quic_conn *qc)
5261{
5262 struct quic_cstream *cs, *ret_cs = NULL;
5263
5264 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
5265 cs = pool_alloc(pool_head_quic_cstream);
5266 if (!cs) {
5267 TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
5268 goto leave;
5269 }
5270
5271 cs->rx.offset = 0;
5272 cs->rx.ncbuf = NCBUF_NULL;
5273 cs->rx.offset = 0;
5274
5275 cs->tx.offset = 0;
5276 cs->tx.sent_offset = 0;
5277 cs->tx.buf = BUF_NULL;
5278 cs->desc = qc_stream_desc_new((uint64_t)-1, -1, cs, qc);
5279 if (!cs->desc) {
5280 TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
5281 goto err;
5282 }
5283
5284 ret_cs = cs;
5285 leave:
5286 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
5287 return ret_cs;
5288
5289 err:
5290 pool_free(pool_head_quic_cstream, cs);
5291 goto leave;
5292}
5293
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005294/* Uninitialize <qel> QUIC encryption level. Never fails. */
5295static void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel)
5296{
5297 int i;
5298
5299 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
5300
5301 for (i = 0; i < qel->tx.crypto.nb_buf; i++) {
5302 if (qel->tx.crypto.bufs[i]) {
5303 pool_free(pool_head_quic_crypto_buf, qel->tx.crypto.bufs[i]);
5304 qel->tx.crypto.bufs[i] = NULL;
5305 }
5306 }
5307 ha_free(&qel->tx.crypto.bufs);
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005308 quic_cstream_free(qel->cstream);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005309
5310 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
5311}
5312
5313/* Initialize QUIC TLS encryption level with <level<> as level for <qc> QUIC
5314 * connection allocating everything needed.
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005315 *
5316 * Returns 1 if succeeded, 0 if not. On error the caller is responsible to use
5317 * quic_conn_enc_level_uninit() to cleanup partially allocated content.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005318 */
5319static int quic_conn_enc_level_init(struct quic_conn *qc,
5320 enum quic_tls_enc_level level)
5321{
5322 int ret = 0;
5323 struct quic_enc_level *qel;
5324
5325 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
5326
5327 qel = &qc->els[level];
5328 qel->level = quic_to_ssl_enc_level(level);
5329 qel->tls_ctx.rx.aead = qel->tls_ctx.tx.aead = NULL;
5330 qel->tls_ctx.rx.md = qel->tls_ctx.tx.md = NULL;
5331 qel->tls_ctx.rx.hp = qel->tls_ctx.tx.hp = NULL;
5332 qel->tls_ctx.flags = 0;
5333
5334 qel->rx.pkts = EB_ROOT;
5335 LIST_INIT(&qel->rx.pqpkts);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005336
5337 /* Allocate only one buffer. */
5338 /* TODO: use a pool */
5339 qel->tx.crypto.bufs = malloc(sizeof *qel->tx.crypto.bufs);
5340 if (!qel->tx.crypto.bufs)
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005341 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005342
5343 qel->tx.crypto.bufs[0] = pool_alloc(pool_head_quic_crypto_buf);
5344 if (!qel->tx.crypto.bufs[0])
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005345 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005346
5347 qel->tx.crypto.bufs[0]->sz = 0;
5348 qel->tx.crypto.nb_buf = 1;
5349
5350 qel->tx.crypto.sz = 0;
5351 qel->tx.crypto.offset = 0;
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005352 /* No CRYPTO data for early data TLS encryption level */
5353 if (level == QUIC_TLS_ENC_LEVEL_EARLY_DATA)
5354 qel->cstream = NULL;
5355 else {
5356 qel->cstream = quic_cstream_new(qc);
5357 if (!qel->cstream)
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005358 goto leave;
Frédéric Lécaille7e3f7c42022-09-09 18:05:45 +02005359 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005360
5361 ret = 1;
5362 leave:
5363 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
5364 return ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005365}
5366
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005367/* Return 1 if <qc> connection may probe the Initial packet number space, 0 if not.
5368 * This is not the case if the remote peer address is not validated and if
5369 * it cannot send at least QUIC_INITIAL_PACKET_MINLEN bytes.
5370 */
5371static int qc_may_probe_ipktns(struct quic_conn *qc)
5372{
5373 return quic_peer_validated_addr(qc) ||
5374 (int)(3 * qc->rx.bytes - qc->tx.prep_bytes) >= QUIC_INITIAL_PACKET_MINLEN;
5375}
5376
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005377/* Callback called upon loss detection and PTO timer expirations. */
5378struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state)
5379{
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005380 struct quic_conn *qc = ctx;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005381 struct quic_pktns *pktns;
5382
Frédéric Lécaille8f991942023-03-24 15:14:45 +01005383 TRACE_ENTER(QUIC_EV_CONN_PTIMER, qc);
5384 TRACE_PROTO("process timer", QUIC_EV_CONN_PTIMER, qc,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005385 NULL, NULL, &qc->path->ifae_pkts);
Frédéric Lécailled21c6282023-04-24 11:26:06 +02005386
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005387 task->expire = TICK_ETERNITY;
5388 pktns = quic_loss_pktns(qc);
Frédéric Lécailled21c6282023-04-24 11:26:06 +02005389
5390 if (qc->flags & (QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_TO_KILL)) {
5391 TRACE_PROTO("cancelled action (draining state)", QUIC_EV_CONN_PTIMER, qc);
5392 task = NULL;
5393 goto out;
5394 }
5395
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005396 if (tick_isset(pktns->tx.loss_time)) {
5397 struct list lost_pkts = LIST_HEAD_INIT(lost_pkts);
5398
5399 qc_packet_loss_lookup(pktns, qc, &lost_pkts);
5400 if (!LIST_ISEMPTY(&lost_pkts))
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005401 tasklet_wakeup(qc->wait_event.tasklet);
Amaury Denoyellee4abb1f2023-01-27 17:54:15 +01005402 if (qc_release_lost_pkts(qc, pktns, &lost_pkts, now_ms))
5403 qc_set_timer(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005404 goto out;
5405 }
5406
5407 if (qc->path->in_flight) {
Frédéric Lécailleb75eecc2023-01-26 15:18:17 +01005408 pktns = quic_pto_pktns(qc, qc->state >= QUIC_HS_ST_CONFIRMED, NULL);
Frédéric Lécaille68737312023-04-07 16:28:46 +02005409 if (!pktns->tx.in_flight) {
5410 TRACE_PROTO("No in flight packets to probe with", QUIC_EV_CONN_TXPKT, qc);
5411 goto out;
5412 }
5413
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005414 if (pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL]) {
5415 if (qc_may_probe_ipktns(qc)) {
5416 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5417 pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
5418 TRACE_STATE("needs to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5419 }
5420 else {
5421 TRACE_STATE("Cannot probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5422 }
5423 if (qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].tx.in_flight) {
5424 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5425 qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
5426 TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
5427 }
Frédéric Lécaillee25fce02023-03-20 17:23:19 +01005428 }
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005429 else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE]) {
5430 TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
5431 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5432 pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
5433 if (qc->pktns[QUIC_TLS_PKTNS_INITIAL].tx.in_flight) {
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005434 if (qc_may_probe_ipktns(qc)) {
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005435 qc->pktns[QUIC_TLS_PKTNS_INITIAL].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005436 TRACE_STATE("needs to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5437 }
5438 else {
5439 TRACE_STATE("Cannot probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
5440 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005441 }
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005442 }
5443 else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT]) {
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01005444 pktns->tx.pto_probe = QUIC_MAX_NB_PTO_DGRAMS;
Amaury Denoyelle2a19b6e2023-03-20 18:29:36 +01005445 /* Wake up upper layer if waiting to send new data. */
5446 if (!qc_notify_send(qc)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005447 TRACE_STATE("needs to probe 01RTT packet number space", QUIC_EV_CONN_TXPKT, qc);
Frédéric Lécaille7c6d8f82023-02-14 16:00:18 +01005448 qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
5449 pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005450 }
5451 }
5452 }
5453 else if (!qc_is_listener(qc) && qc->state <= QUIC_HS_ST_COMPLETE) {
5454 struct quic_enc_level *iel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
5455 struct quic_enc_level *hel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
5456
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005457 if (quic_tls_has_tx_sec(hel))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005458 hel->pktns->tx.pto_probe = 1;
Frédéric Lécaillee1a49cf2022-09-16 16:24:47 +02005459 if (quic_tls_has_tx_sec(iel))
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005460 iel->pktns->tx.pto_probe = 1;
5461 }
5462
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005463 tasklet_wakeup(qc->wait_event.tasklet);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005464 qc->path->loss.pto_count++;
5465
5466 out:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01005467 TRACE_PROTO("process timer", QUIC_EV_CONN_PTIMER, qc, pktns);
5468 TRACE_LEAVE(QUIC_EV_CONN_PTIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005469
5470 return task;
5471}
5472
5473/* Parse the Retry token from buffer <token> with <end> a pointer to
5474 * one byte past the end of this buffer. This will extract the ODCID
5475 * which will be stored into <odcid>
5476 *
5477 * Returns 0 on success else non-zero.
5478 */
5479static int parse_retry_token(struct quic_conn *qc,
5480 const unsigned char *token, const unsigned char *end,
5481 struct quic_cid *odcid)
5482{
5483 int ret = 0;
5484 uint64_t odcid_len;
5485 uint32_t timestamp;
Emeric Brun7875f122023-07-11 16:13:19 +02005486 uint32_t now_sec = (uint32_t)date.tv_sec;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005487
5488 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
5489
5490 if (!quic_dec_int(&odcid_len, &token, end)) {
5491 TRACE_ERROR("quic_dec_int() error", QUIC_EV_CONN_LPKT, qc);
5492 goto leave;
5493 }
5494
5495 /* RFC 9000 7.2. Negotiating Connection IDs:
5496 * When an Initial packet is sent by a client that has not previously
5497 * received an Initial or Retry packet from the server, the client
5498 * populates the Destination Connection ID field with an unpredictable
5499 * value. This Destination Connection ID MUST be at least 8 bytes in length.
5500 */
5501 if (odcid_len < QUIC_ODCID_MINLEN || odcid_len > QUIC_CID_MAXLEN) {
5502 TRACE_ERROR("wrong ODCID length", QUIC_EV_CONN_LPKT, qc);
5503 goto leave;
5504 }
5505
5506 if (end - token < odcid_len + sizeof timestamp) {
5507 TRACE_ERROR("too long ODCID length", QUIC_EV_CONN_LPKT, qc);
5508 goto leave;
5509 }
5510
5511 timestamp = ntohl(read_u32(token + odcid_len));
Emeric Brun7875f122023-07-11 16:13:19 +02005512 /* check if elapsed time is +/- QUIC_RETRY_DURATION_SEC
5513 * to tolerate token generator is not perfectly time synced
5514 */
5515 if ((uint32_t)(now_sec - timestamp) > QUIC_RETRY_DURATION_SEC &&
5516 (uint32_t)(timestamp - now_sec) > QUIC_RETRY_DURATION_SEC) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005517 TRACE_ERROR("token has expired", QUIC_EV_CONN_LPKT, qc);
5518 goto leave;
5519 }
5520
5521 ret = 1;
5522 memcpy(odcid->data, token, odcid_len);
5523 odcid->len = odcid_len;
5524 leave:
5525 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
5526 return !ret;
5527}
5528
5529/* Allocate a new QUIC connection with <version> as QUIC version. <ipv4>
5530 * boolean is set to 1 for IPv4 connection, 0 for IPv6. <server> is set to 1
5531 * for QUIC servers (or haproxy listeners).
Frédéric Lécaille8a586582023-06-26 10:39:56 +02005532 * <dcid> is the destination connection ID, <scid> is the source connection ID.
5533 * This latter <scid> CID as the same value on the wire as the one for <conn_id>
5534 * which is the first CID of this connection but a different internal representation used to build
5535 * NEW_CONNECTION_ID frames. This is the responsability of the caller to insert
5536 * <conn_id> in the CIDs tree for this connection (qc->cids).
5537 * <token> is the token found to be used for this connection with <token_len> as
Amaury Denoyelle97ecc7a2022-09-23 17:15:58 +02005538 * length. Endpoints addresses are specified via <local_addr> and <peer_addr>.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005539 * Returns the connection if succeeded, NULL if not.
5540 */
5541static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
5542 struct quic_cid *dcid, struct quic_cid *scid,
5543 const struct quic_cid *token_odcid,
Amaury Denoyellef16ec342023-04-13 17:42:34 +02005544 struct quic_connection_id *conn_id,
Amaury Denoyelle97ecc7a2022-09-23 17:15:58 +02005545 struct sockaddr_storage *local_addr,
5546 struct sockaddr_storage *peer_addr,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005547 int server, int token, void *owner)
5548{
5549 int i;
5550 struct quic_conn *qc;
5551 /* Initial CID. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005552 char *buf_area = NULL;
5553 struct listener *l = NULL;
5554 struct quic_cc_algo *cc_algo = NULL;
5555 struct quic_tls_ctx *ictx;
5556 TRACE_ENTER(QUIC_EV_CONN_INIT);
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005557 /* TODO replace pool_zalloc by pool_alloc(). This requires special care
5558 * to properly initialized internal quic_conn members to safely use
5559 * quic_conn_release() on alloc failure.
5560 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005561 qc = pool_zalloc(pool_head_quic_conn);
5562 if (!qc) {
5563 TRACE_ERROR("Could not allocate a new connection", QUIC_EV_CONN_INIT);
5564 goto err;
5565 }
5566
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005567 /* Initialize in priority qc members required for a safe dealloc. */
5568
5569 /* required to use MTLIST_IN_LIST */
5570 MT_LIST_INIT(&qc->accept_list);
5571
5572 LIST_INIT(&qc->rx.pkt_list);
5573
Amaury Denoyelle42448332022-12-12 11:24:05 +01005574 qc_init_fd(qc);
5575
Amaury Denoyelle15c74702023-02-01 10:18:26 +01005576 LIST_INIT(&qc->back_refs);
Amaury Denoyelled537ca72023-04-19 10:45:40 +02005577 LIST_INIT(&qc->el_th_ctx);
Amaury Denoyelle15c74702023-02-01 10:18:26 +01005578
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005579 /* Now proceeds to allocation of qc members. */
5580
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005581 buf_area = pool_alloc(pool_head_quic_conn_rxbuf);
5582 if (!buf_area) {
5583 TRACE_ERROR("Could not allocate a new RX buffer", QUIC_EV_CONN_INIT, qc);
5584 goto err;
5585 }
5586
5587 qc->cids = EB_ROOT;
5588 /* QUIC Server (or listener). */
5589 if (server) {
5590 struct proxy *prx;
5591
5592 l = owner;
5593 prx = l->bind_conf->frontend;
5594 cc_algo = l->bind_conf->quic_cc_algo;
5595
5596 qc->prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe,
5597 &quic_stats_module);
5598 qc->flags |= QUIC_FL_CONN_LISTENER;
5599 qc->state = QUIC_HS_ST_SERVER_INITIAL;
Amaury Denoyelle15adc4c2023-04-05 09:50:17 +02005600 /* Copy the client original DCID. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005601 qc->odcid.len = dcid->len;
Amaury Denoyelle15adc4c2023-04-05 09:50:17 +02005602 memcpy(qc->odcid.data, dcid->data, dcid->len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005603
5604 /* copy the packet SCID to reuse it as DCID for sending */
5605 if (scid->len)
5606 memcpy(qc->dcid.data, scid->data, scid->len);
5607 qc->dcid.len = scid->len;
5608 qc->tx.buf = BUF_NULL;
5609 qc->li = l;
5610 }
5611 /* QUIC Client (outgoing connection to servers) */
5612 else {
5613 qc->state = QUIC_HS_ST_CLIENT_INITIAL;
5614 if (dcid->len)
5615 memcpy(qc->dcid.data, dcid->data, dcid->len);
5616 qc->dcid.len = dcid->len;
5617 }
5618 qc->mux_state = QC_MUX_NULL;
5619 qc->err = quic_err_transport(QC_ERR_NO_ERROR);
5620
Amaury Denoyellef16ec342023-04-13 17:42:34 +02005621 conn_id->qc = qc;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005622
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005623 if ((global.tune.options & GTUNE_QUIC_SOCK_PER_CONN) &&
5624 is_addr(local_addr)) {
5625 TRACE_USER("Allocate a socket for QUIC connection", QUIC_EV_CONN_INIT, qc);
5626 qc_alloc_fd(qc, local_addr, peer_addr);
Amaury Denoyellefb375572023-02-01 09:28:32 +01005627
5628 /* haproxy soft-stop is supported only for QUIC connections
5629 * with their owned socket.
5630 */
5631 if (qc_test_fd(qc))
5632 _HA_ATOMIC_INC(&jobs);
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005633 }
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005634
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005635 /* Select our SCID which is the first CID with 0 as sequence number. */
Amaury Denoyelle591e7982023-04-12 10:04:49 +02005636 qc->scid = conn_id->cid;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005637
5638 /* Packet number spaces initialization. */
5639 for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++)
5640 quic_pktns_init(&qc->pktns[i]);
5641 /* QUIC encryption level context initialization. */
5642 for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
5643 if (!quic_conn_enc_level_init(qc, i)) {
5644 TRACE_ERROR("Could not initialize an encryption level", QUIC_EV_CONN_INIT, qc);
5645 goto err;
5646 }
5647 /* Initialize the packet number space. */
5648 qc->els[i].pktns = &qc->pktns[quic_tls_pktns(i)];
5649 }
5650
5651 qc->original_version = qv;
5652 qc->tps_tls_ext = (qc->original_version->num & 0xff000000) == 0xff000000 ?
5653 TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS_DRAFT:
5654 TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS;
5655 /* TX part. */
5656 LIST_INIT(&qc->tx.frms_to_send);
5657 qc->tx.nb_buf = QUIC_CONN_TX_BUFS_NB;
5658 qc->tx.wbuf = qc->tx.rbuf = 0;
5659 qc->tx.bytes = 0;
5660 qc->tx.buf = BUF_NULL;
5661 /* RX part. */
5662 qc->rx.bytes = 0;
5663 qc->rx.buf = b_make(buf_area, QUIC_CONN_RX_BUFSZ, 0, 0);
5664 for (i = 0; i < QCS_MAX_TYPES; i++)
5665 qc->rx.strms[i].nb_streams = 0;
5666
5667 qc->nb_pkt_for_cc = 1;
5668 qc->nb_pkt_since_cc = 0;
5669
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005670 if (!quic_tls_ku_init(qc)) {
5671 TRACE_ERROR("Key update initialization failed", QUIC_EV_CONN_INIT, qc);
5672 goto err;
5673 }
5674
5675 /* XXX TO DO: Only one path at this time. */
5676 qc->path = &qc->paths[0];
5677 quic_path_init(qc->path, ipv4, cc_algo ? cc_algo : default_quic_cc_algo, qc);
5678
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005679 qc->streams_by_id = EB_ROOT_UNIQUE;
5680 qc->stream_buf_count = 0;
Amaury Denoyelle97ecc7a2022-09-23 17:15:58 +02005681 memcpy(&qc->local_addr, local_addr, sizeof(qc->local_addr));
5682 memcpy(&qc->peer_addr, peer_addr, sizeof qc->peer_addr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005683
5684 if (server && !qc_lstnr_params_init(qc, &l->bind_conf->quic_params,
Amaury Denoyelle591e7982023-04-12 10:04:49 +02005685 conn_id->stateless_reset_token,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005686 dcid->data, dcid->len,
5687 qc->scid.data, qc->scid.len, token_odcid))
5688 goto err;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005689
Frédéric Lécailledeb97812023-03-22 11:29:45 +01005690 /* Initialize the idle timeout of the connection at the "max_idle_timeout"
5691 * value from local transport parameters.
5692 */
5693 qc->max_idle_timeout = qc->rx.params.max_idle_timeout;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005694 qc->wait_event.tasklet = tasklet_new();
5695 if (!qc->wait_event.tasklet) {
5696 TRACE_ERROR("tasklet_new() failed", QUIC_EV_CONN_TXPKT);
5697 goto err;
5698 }
5699 qc->wait_event.tasklet->process = quic_conn_io_cb;
5700 qc->wait_event.tasklet->context = qc;
5701 qc->wait_event.events = 0;
Amaury Denoyellebbb1c682022-09-28 15:15:51 +02005702 qc->subs = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005703
5704 if (qc_conn_alloc_ssl_ctx(qc) ||
5705 !quic_conn_init_timer(qc) ||
5706 !quic_conn_init_idle_timer_task(qc))
5707 goto err;
5708
5709 ictx = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx;
5710 if (!qc_new_isecs(qc, ictx,qc->original_version, dcid->data, dcid->len, 1))
5711 goto err;
5712
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02005713 /* Counters initialization */
5714 memset(&qc->cntrs, 0, sizeof qc->cntrs);
5715
Amaury Denoyelle15c74702023-02-01 10:18:26 +01005716 LIST_APPEND(&th_ctx->quic_conns, &qc->el_th_ctx);
5717 qc->qc_epoch = HA_ATOMIC_LOAD(&qc_epoch);
5718
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005719 TRACE_LEAVE(QUIC_EV_CONN_INIT, qc);
5720
5721 return qc;
5722
5723 err:
5724 pool_free(pool_head_quic_conn_rxbuf, buf_area);
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005725 if (qc) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005726 qc->rx.buf.area = NULL;
Amaury Denoyelledbf6ad42022-12-12 11:22:42 +01005727 quic_conn_release(qc);
5728 }
5729 TRACE_LEAVE(QUIC_EV_CONN_INIT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005730 return NULL;
5731}
5732
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02005733/* Update the proxy counters of <qc> QUIC connection from its counters */
5734static inline void quic_conn_prx_cntrs_update(struct quic_conn *qc)
5735{
Frédéric Lécaille557d30a2023-06-14 18:09:54 +02005736 if (!qc->prx_counters)
5737 return;
5738
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02005739 HA_ATOMIC_ADD(&qc->prx_counters->dropped_pkt, qc->cntrs.dropped_pkt);
5740 HA_ATOMIC_ADD(&qc->prx_counters->dropped_pkt_bufoverrun, qc->cntrs.dropped_pkt_bufoverrun);
5741 HA_ATOMIC_ADD(&qc->prx_counters->dropped_parsing, qc->cntrs.dropped_parsing);
5742 HA_ATOMIC_ADD(&qc->prx_counters->socket_full, qc->cntrs.socket_full);
5743 HA_ATOMIC_ADD(&qc->prx_counters->sendto_err, qc->cntrs.sendto_err);
5744 HA_ATOMIC_ADD(&qc->prx_counters->sendto_err_unknown, qc->cntrs.sendto_err_unknown);
Frédéric Lécaille12a815a2023-05-24 15:55:14 +02005745 HA_ATOMIC_ADD(&qc->prx_counters->sent_pkt, qc->cntrs.sent_pkt);
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02005746 HA_ATOMIC_ADD(&qc->prx_counters->lost_pkt, qc->path->loss.nb_lost_pkt);
5747 HA_ATOMIC_ADD(&qc->prx_counters->conn_migration_done, qc->cntrs.conn_migration_done);
5748 /* Stream related counters */
5749 HA_ATOMIC_ADD(&qc->prx_counters->data_blocked, qc->cntrs.data_blocked);
5750 HA_ATOMIC_ADD(&qc->prx_counters->stream_data_blocked, qc->cntrs.stream_data_blocked);
Amaury Denoyelle6d6ee0d2023-05-25 10:36:04 +02005751 HA_ATOMIC_ADD(&qc->prx_counters->streams_blocked_bidi, qc->cntrs.streams_blocked_bidi);
5752 HA_ATOMIC_ADD(&qc->prx_counters->streams_blocked_uni, qc->cntrs.streams_blocked_uni);
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02005753}
5754
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005755/* Release the quic_conn <qc>. The connection is removed from the CIDs tree.
5756 * The connection tasklet is killed.
5757 *
5758 * This function must only be called by the thread responsible of the quic_conn
5759 * tasklet.
5760 */
5761void quic_conn_release(struct quic_conn *qc)
5762{
5763 int i;
5764 struct ssl_sock_ctx *conn_ctx;
5765 struct eb64_node *node;
5766 struct quic_tls_ctx *app_tls_ctx;
5767 struct quic_rx_packet *pkt, *pktback;
5768
5769 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
5770
5771 /* We must not free the quic-conn if the MUX is still allocated. */
5772 BUG_ON(qc->mux_state == QC_MUX_READY);
5773
Amaury Denoyellefb375572023-02-01 09:28:32 +01005774 if (qc_test_fd(qc))
5775 _HA_ATOMIC_DEC(&jobs);
5776
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005777 /* Close quic-conn socket fd. */
Amaury Denoyelled3083c92022-12-01 16:20:06 +01005778 qc_release_fd(qc, 0);
Amaury Denoyelle40909df2022-10-24 17:08:43 +02005779
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005780 /* in the unlikely (but possible) case the connection was just added to
5781 * the accept_list we must delete it from there.
5782 */
5783 MT_LIST_DELETE(&qc->accept_list);
5784
5785 /* free remaining stream descriptors */
5786 node = eb64_first(&qc->streams_by_id);
5787 while (node) {
5788 struct qc_stream_desc *stream;
5789
5790 stream = eb64_entry(node, struct qc_stream_desc, by_id);
5791 node = eb64_next(node);
5792
5793 /* all streams attached to the quic-conn are released, so
5794 * qc_stream_desc_free will liberate the stream instance.
5795 */
5796 BUG_ON(!stream->release);
5797 qc_stream_desc_free(stream, 1);
5798 }
5799
5800 /* Purge Rx packet list. */
5801 list_for_each_entry_safe(pkt, pktback, &qc->rx.pkt_list, qc_rx_pkt_list) {
5802 LIST_DELETE(&pkt->qc_rx_pkt_list);
5803 pool_free(pool_head_quic_rx_packet, pkt);
5804 }
5805
5806 if (qc->idle_timer_task) {
5807 task_destroy(qc->idle_timer_task);
5808 qc->idle_timer_task = NULL;
5809 }
5810
5811 if (qc->timer_task) {
5812 task_destroy(qc->timer_task);
5813 qc->timer_task = NULL;
5814 }
5815
Tim Duesterhusb1ec21d2023-04-22 17:47:32 +02005816 tasklet_free(qc->wait_event.tasklet);
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005817
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005818 /* remove the connection from receiver cids trees */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005819 free_quic_conn_cids(qc);
5820
5821 conn_ctx = qc->xprt_ctx;
5822 if (conn_ctx) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005823 SSL_free(conn_ctx->ssl);
5824 pool_free(pool_head_quic_conn_ctx, conn_ctx);
5825 }
5826
5827 quic_tls_ku_free(qc);
5828 for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
5829 quic_tls_ctx_secs_free(&qc->els[i].tls_ctx);
5830 quic_conn_enc_level_uninit(qc, &qc->els[i]);
5831 }
5832 quic_tls_ctx_secs_free(&qc->negotiated_ictx);
5833
5834 app_tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
5835 pool_free(pool_head_quic_tls_secret, app_tls_ctx->rx.secret);
5836 pool_free(pool_head_quic_tls_secret, app_tls_ctx->tx.secret);
5837
5838 for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++) {
5839 quic_pktns_tx_pkts_release(&qc->pktns[i], qc);
5840 quic_free_arngs(qc, &qc->pktns[i].rx.arngs);
Frédéric Lécaille73e29442023-09-13 09:28:10 +02005841 qc_release_pktns_frms(qc, &qc->pktns[i]);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005842 }
5843
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01005844 qc_detach_th_ctx_list(qc, 0);
Amaury Denoyelle15c74702023-02-01 10:18:26 +01005845
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02005846 quic_conn_prx_cntrs_update(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005847 pool_free(pool_head_quic_conn_rxbuf, qc->rx.buf.area);
5848 pool_free(pool_head_quic_conn, qc);
Frédéric Lécailleeb3e5172023-04-12 13:41:54 +02005849 qc = NULL;
Amaury Denoyellefb375572023-02-01 09:28:32 +01005850
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005851 TRACE_PROTO("QUIC conn. freed", QUIC_EV_CONN_FREED, qc);
5852
5853 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
5854}
5855
5856/* Initialize the timer task of <qc> QUIC connection.
5857 * Returns 1 if succeeded, 0 if not.
5858 */
5859static int quic_conn_init_timer(struct quic_conn *qc)
5860{
5861 int ret = 0;
5862 /* Attach this task to the same thread ID used for the connection */
5863 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
5864
Amaury Denoyelle66947282023-04-13 11:48:38 +02005865 qc->timer_task = task_new_here();
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005866 if (!qc->timer_task) {
5867 TRACE_ERROR("timer task allocation failed", QUIC_EV_CONN_NEW, qc);
5868 goto leave;
5869 }
5870
5871 qc->timer = TICK_ETERNITY;
5872 qc->timer_task->process = qc_process_timer;
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02005873 qc->timer_task->context = qc;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005874
5875 ret = 1;
5876 leave:
5877 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
5878 return ret;
5879}
5880
Frédéric Lécailled7215712023-03-24 18:13:37 +01005881/* Rearm the idle timer or the ack timer (if not already armde) for <qc> QUIC
5882 * connection. */
5883static void qc_idle_timer_do_rearm(struct quic_conn *qc, int arm_ack)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005884{
5885 unsigned int expire;
5886
Amaury Denoyelle77ed6312023-02-01 09:28:55 +01005887 if (stopping && qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) {
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005888 TRACE_PROTO("executing idle timer immediately on stopping", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005889 qc->ack_expire = TICK_ETERNITY;
Amaury Denoyelle77ed6312023-02-01 09:28:55 +01005890 task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG);
5891 }
5892 else {
5893 expire = QUIC_MAX(3 * quic_pto(qc), qc->max_idle_timeout);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005894 qc->idle_expire = tick_add(now_ms, MS_TO_TICKS(expire));
5895 if (arm_ack) {
5896 /* Arm the ack timer only if not already armed. */
5897 if (!tick_isset(qc->ack_expire)) {
5898 qc->ack_expire = tick_add(now_ms, MS_TO_TICKS(QUIC_ACK_DELAY));
5899 qc->idle_timer_task->expire = qc->ack_expire;
5900 task_queue(qc->idle_timer_task);
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005901 TRACE_PROTO("ack timer armed", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005902 }
5903 }
5904 else {
5905 qc->idle_timer_task->expire = tick_first(qc->ack_expire, qc->idle_expire);
5906 task_queue(qc->idle_timer_task);
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005907 TRACE_PROTO("idle timer armed", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005908 }
Amaury Denoyelle77ed6312023-02-01 09:28:55 +01005909 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005910}
5911
Frédéric Lécailled7215712023-03-24 18:13:37 +01005912/* Rearm the idle timer or ack timer for <qc> QUIC connection depending on <read>
5913 * and <arm_ack> booleans. The former is set to 1 when receiving a packet ,
5914 * and 0 when sending packet. <arm_ack> is set to 1 if this is the ack timer
5915 * which must be rearmed.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005916 */
Frédéric Lécailled7215712023-03-24 18:13:37 +01005917static void qc_idle_timer_rearm(struct quic_conn *qc, int read, int arm_ack)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005918{
5919 TRACE_ENTER(QUIC_EV_CONN_IDLE_TIMER, qc);
5920
5921 if (read) {
5922 qc->flags |= QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ;
5923 }
5924 else {
5925 qc->flags &= ~QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ;
5926 }
Frédéric Lécailled7215712023-03-24 18:13:37 +01005927 qc_idle_timer_do_rearm(qc, arm_ack);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005928
5929 TRACE_LEAVE(QUIC_EV_CONN_IDLE_TIMER, qc);
5930}
5931
5932/* The task handling the idle timeout */
5933struct task *qc_idle_timer_task(struct task *t, void *ctx, unsigned int state)
5934{
5935 struct quic_conn *qc = ctx;
5936 struct quic_counters *prx_counters = qc->prx_counters;
5937 unsigned int qc_flags = qc->flags;
5938
5939 TRACE_ENTER(QUIC_EV_CONN_IDLE_TIMER, qc);
5940
Frédéric Lécaille12eca3a2023-04-04 10:46:54 +02005941 if ((state & TASK_WOKEN_ANY) == TASK_WOKEN_TIMER && !tick_is_expired(t->expire, now_ms))
5942 goto requeue;
5943
Frédéric Lécailled7215712023-03-24 18:13:37 +01005944 if (tick_is_expired(qc->ack_expire, now_ms)) {
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005945 TRACE_PROTO("ack timer expired", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01005946 qc->ack_expire = TICK_ETERNITY;
5947 /* Note that ->idle_expire is always set. */
5948 t->expire = qc->idle_expire;
Frédéric Lécailleb73762a2023-04-24 11:32:22 +02005949 /* Do not wakeup the I/O handler in DRAINING state or if the
5950 * connection must be killed as soon as possible.
5951 */
5952 if (!(qc->flags & (QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_TO_KILL))) {
5953 qc->flags |= QUIC_FL_CONN_ACK_TIMER_FIRED;
5954 tasklet_wakeup(qc->wait_event.tasklet);
5955 }
5956
Frédéric Lécailled7215712023-03-24 18:13:37 +01005957 goto requeue;
5958 }
5959
Frédéric Lécaille495968e2023-04-03 17:42:05 +02005960 TRACE_PROTO("idle timer task running", QUIC_EV_CONN_IDLE_TIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005961 /* Notify the MUX before settings QUIC_FL_CONN_EXP_TIMER or the MUX
5962 * might free the quic-conn too early via quic_close().
5963 */
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02005964 qc_notify_err(qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005965
5966 /* If the MUX is still alive, keep the quic-conn. The MUX is
5967 * responsible to call quic_close to release it.
5968 */
5969 qc->flags |= QUIC_FL_CONN_EXP_TIMER;
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005970 if (qc->mux_state != QC_MUX_READY) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005971 quic_conn_release(qc);
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005972 qc = NULL;
5973 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005974
5975 /* TODO if the quic-conn cannot be freed because of the MUX, we may at
5976 * least clean some parts of it such as the tasklet.
5977 */
5978
5979 if (!(qc_flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
5980 qc_flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
Frédéric Lécaillece5c1452023-04-05 09:44:21 +02005981 TRACE_DEVEL("dec half open counter", QUIC_EV_CONN_IDLE_TIMER, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005982 HA_ATOMIC_DEC(&prx_counters->half_open_conn);
5983 }
5984
Frédéric Lécailled7215712023-03-24 18:13:37 +01005985 leave:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005986 TRACE_LEAVE(QUIC_EV_CONN_IDLE_TIMER, qc);
5987 return NULL;
Frédéric Lécailled7215712023-03-24 18:13:37 +01005988
5989 requeue:
5990 TRACE_LEAVE(QUIC_EV_CONN_IDLE_TIMER, qc);
5991 return t;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02005992}
5993
5994/* Initialize the idle timeout task for <qc>.
5995 * Returns 1 if succeeded, 0 if not.
5996 */
5997static int quic_conn_init_idle_timer_task(struct quic_conn *qc)
5998{
5999 int ret = 0;
6000
6001 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
6002
6003 qc->idle_timer_task = task_new_here();
6004 if (!qc->idle_timer_task) {
6005 TRACE_ERROR("Idle timer task allocation failed", QUIC_EV_CONN_NEW, qc);
6006 goto leave;
6007 }
6008
6009 qc->idle_timer_task->process = qc_idle_timer_task;
6010 qc->idle_timer_task->context = qc;
Frédéric Lécailled7215712023-03-24 18:13:37 +01006011 qc->ack_expire = TICK_ETERNITY;
6012 qc_idle_timer_rearm(qc, 1, 0);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006013 task_queue(qc->idle_timer_task);
6014
6015 ret = 1;
6016 leave:
6017 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
6018 return ret;
6019}
6020
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006021/* Parse into <pkt> a long header located at <*pos> position, <end> begin a pointer to the end
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006022 * past one byte of this buffer.
6023 */
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006024static inline int quic_packet_read_long_header(unsigned char **pos, const unsigned char *end,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006025 struct quic_rx_packet *pkt)
6026{
6027 int ret = 0;
6028 unsigned char dcid_len, scid_len;
6029
6030 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
6031
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006032 if (end == *pos) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006033 TRACE_ERROR("buffer data consumed", QUIC_EV_CONN_RXPKT);
6034 goto leave;
6035 }
6036
6037 /* Destination Connection ID Length */
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006038 dcid_len = *(*pos)++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006039 /* We want to be sure we can read <dcid_len> bytes and one more for <scid_len> value */
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006040 if (dcid_len > QUIC_CID_MAXLEN || end - *pos < dcid_len + 1) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006041 TRACE_ERROR("too long DCID", QUIC_EV_CONN_RXPKT);
6042 goto leave;
6043 }
6044
6045 if (dcid_len) {
6046 /* Check that the length of this received DCID matches the CID lengths
6047 * of our implementation for non Initials packets only.
6048 */
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02006049 if (pkt->version && pkt->version->num &&
6050 pkt->type != QUIC_PACKET_TYPE_INITIAL &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006051 pkt->type != QUIC_PACKET_TYPE_0RTT &&
6052 dcid_len != QUIC_HAP_CID_LEN) {
6053 TRACE_ERROR("wrong DCID length", QUIC_EV_CONN_RXPKT);
6054 goto leave;
6055 }
6056
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006057 memcpy(pkt->dcid.data, *pos, dcid_len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006058 }
6059
6060 pkt->dcid.len = dcid_len;
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006061 *pos += dcid_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006062
6063 /* Source Connection ID Length */
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006064 scid_len = *(*pos)++;
6065 if (scid_len > QUIC_CID_MAXLEN || end - *pos < scid_len) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006066 TRACE_ERROR("too long SCID", QUIC_EV_CONN_RXPKT);
6067 goto leave;
6068 }
6069
6070 if (scid_len)
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006071 memcpy(pkt->scid.data, *pos, scid_len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006072 pkt->scid.len = scid_len;
Frédéric Lécaille6ff52f92023-04-24 15:41:07 +02006073 *pos += scid_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006074
6075 ret = 1;
6076 leave:
6077 TRACE_LEAVE(QUIC_EV_CONN_RXPKT);
6078 return ret;
6079}
6080
6081/* Insert <pkt> RX packet in its <qel> RX packets tree */
6082static void qc_pkt_insert(struct quic_conn *qc,
6083 struct quic_rx_packet *pkt, struct quic_enc_level *qel)
6084{
6085 TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
6086
6087 pkt->pn_node.key = pkt->pn;
6088 quic_rx_packet_refinc(pkt);
6089 eb64_insert(&qel->rx.pkts, &pkt->pn_node);
6090
6091 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
6092}
6093
Amaury Denoyelle845169d2022-10-17 18:05:26 +02006094/* Try to remove the header protection of <pkt> QUIC packet with <beg> the
6095 * address of the packet first byte, using the keys from encryption level <el>.
6096 *
6097 * If header protection has been successfully removed, packet data are copied
6098 * into <qc> Rx buffer. If <el> secrets are not yet available, the copy is also
6099 * proceeded, and the packet is inserted into <qc> protected packets tree. In
6100 * both cases, packet can now be considered handled by the <qc> connection.
6101 *
6102 * If header protection cannot be removed due to <el> secrets already
6103 * discarded, no operation is conducted.
6104 *
6105 * Returns 1 on success : packet data is now handled by the connection. On
6106 * error 0 is returned : packet should be dropped by the caller.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006107 */
6108static inline int qc_try_rm_hp(struct quic_conn *qc,
6109 struct quic_rx_packet *pkt,
Amaury Denoyelle845169d2022-10-17 18:05:26 +02006110 unsigned char *beg,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006111 struct quic_enc_level **el)
6112{
6113 int ret = 0;
6114 unsigned char *pn = NULL; /* Packet number field */
6115 enum quic_tls_enc_level tel;
6116 struct quic_enc_level *qel;
6117 /* Only for traces. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006118
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006119 TRACE_ENTER(QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle845169d2022-10-17 18:05:26 +02006120 BUG_ON(!pkt->pn_offset);
6121
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006122 /* The packet number is here. This is also the start minus
6123 * QUIC_PACKET_PN_MAXLEN of the sample used to add/remove the header
6124 * protection.
6125 */
Amaury Denoyelle845169d2022-10-17 18:05:26 +02006126 pn = beg + pkt->pn_offset;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006127
6128 tel = quic_packet_type_enc_level(pkt->type);
6129 qel = &qc->els[tel];
6130
6131 if (qc_qel_may_rm_hp(qc, qel)) {
Frédéric Lécaille72027782023-02-22 16:20:09 +01006132 struct quic_tls_ctx *tls_ctx = qc_select_tls_ctx(qc, qel, pkt);
6133
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006134 /* Note that the following function enables us to unprotect the packet
6135 * number and its length subsequently used to decrypt the entire
6136 * packets.
6137 */
Frédéric Lécaille72027782023-02-22 16:20:09 +01006138 if (!qc_do_rm_hp(qc, pkt, tls_ctx,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006139 qel->pktns->rx.largest_pn, pn, beg)) {
6140 TRACE_PROTO("hp error", QUIC_EV_CONN_TRMHP, qc);
6141 goto out;
6142 }
6143
Frédéric Lécailleece86e62023-03-07 11:53:43 +01006144 qc_handle_spin_bit(qc, pkt, qel);
Amaury Denoyelle845169d2022-10-17 18:05:26 +02006145 /* The AAD includes the packet number field. */
6146 pkt->aad_len = pkt->pn_offset + pkt->pnl;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006147 if (pkt->len - pkt->aad_len < QUIC_TLS_TAG_LEN) {
6148 TRACE_PROTO("Too short packet", QUIC_EV_CONN_TRMHP, qc);
6149 goto out;
6150 }
6151
Frédéric Lécaillec0aaa072023-04-07 17:58:49 +02006152 TRACE_PROTO("RX hp removed", QUIC_EV_CONN_TRMHP, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006153 }
6154 else {
6155 if (qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD) {
6156 /* If the packet number space has been discarded, this packet
6157 * will be not parsed.
6158 */
6159 TRACE_PROTO("Discarded pktns", QUIC_EV_CONN_TRMHP, qc, pkt);
6160 goto out;
6161 }
6162
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006163 TRACE_PROTO("RX hp not removed", QUIC_EV_CONN_TRMHP, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006164 LIST_APPEND(&qel->rx.pqpkts, &pkt->list);
6165 quic_rx_packet_refinc(pkt);
6166 }
6167
6168 *el = qel;
6169 /* No reference counter incrementation here!!! */
6170 LIST_APPEND(&qc->rx.pkt_list, &pkt->qc_rx_pkt_list);
6171 memcpy(b_tail(&qc->rx.buf), beg, pkt->len);
6172 pkt->data = (unsigned char *)b_tail(&qc->rx.buf);
6173 b_add(&qc->rx.buf, pkt->len);
6174
6175 ret = 1;
6176 out:
Frédéric Lécaillec0aaa072023-04-07 17:58:49 +02006177 TRACE_LEAVE(QUIC_EV_CONN_TRMHP, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006178 return ret;
6179}
6180
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02006181/* Return the QUIC version (quic_version struct) with <version> as version number
6182 * if supported or NULL if not.
6183 */
6184static inline const struct quic_version *qc_supported_version(uint32_t version)
6185{
6186 int i;
6187
6188 if (unlikely(!version))
6189 return &quic_version_VN_reserved;
6190
6191 for (i = 0; i < quic_versions_nb; i++)
6192 if (quic_versions[i].num == version)
6193 return &quic_versions[i];
6194
6195 return NULL;
6196}
6197
Willy Tarreaudd9f9212023-05-07 07:07:44 +02006198/* Parse a QUIC packet header starting at <pos> position without exceeding <end>.
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02006199 * Version and type are stored in <pkt> packet instance. Type is set to unknown
6200 * on two occasions : for unsupported version, in this case version field is
6201 * set to NULL; for Version Negotiation packet with version number set to 0.
6202 *
6203 * Returns 1 on success else 0.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006204 */
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02006205int qc_parse_hd_form(struct quic_rx_packet *pkt,
Frédéric Lécaillebb426aa2023-04-24 15:44:18 +02006206 unsigned char **pos, const unsigned char *end)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006207{
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02006208 uint32_t version;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006209 int ret = 0;
Frédéric Lécaillebb426aa2023-04-24 15:44:18 +02006210 const unsigned char byte0 = **pos;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006211
6212 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02006213 pkt->version = NULL;
6214 pkt->type = QUIC_PACKET_TYPE_UNKNOWN;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006215
Frédéric Lécaillebb426aa2023-04-24 15:44:18 +02006216 (*pos)++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006217 if (byte0 & QUIC_PACKET_LONG_HEADER_BIT) {
6218 unsigned char type =
6219 (byte0 >> QUIC_PACKET_TYPE_SHIFT) & QUIC_PACKET_TYPE_BITMASK;
6220
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006221 /* Version */
Frédéric Lécaillebb426aa2023-04-24 15:44:18 +02006222 if (!quic_read_uint32(&version, (const unsigned char **)pos, end)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006223 TRACE_ERROR("could not read the packet version", QUIC_EV_CONN_RXPKT);
6224 goto out;
6225 }
6226
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02006227 pkt->version = qc_supported_version(version);
6228 if (version && pkt->version) {
6229 if (version != QUIC_PROTOCOL_VERSION_2) {
6230 pkt->type = type;
6231 }
6232 else {
6233 switch (type) {
6234 case 0:
6235 pkt->type = QUIC_PACKET_TYPE_RETRY;
6236 break;
6237 case 1:
6238 pkt->type = QUIC_PACKET_TYPE_INITIAL;
6239 break;
6240 case 2:
6241 pkt->type = QUIC_PACKET_TYPE_0RTT;
6242 break;
6243 case 3:
6244 pkt->type = QUIC_PACKET_TYPE_HANDSHAKE;
6245 break;
6246 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006247 }
6248 }
6249 }
6250 else {
Frédéric Lécailleece86e62023-03-07 11:53:43 +01006251 if (byte0 & QUIC_PACKET_SPIN_BIT)
6252 pkt->flags |= QUIC_FL_RX_PACKET_SPIN_BIT;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006253 pkt->type = QUIC_PACKET_TYPE_SHORT;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006254 }
6255
6256 ret = 1;
6257 out:
6258 TRACE_LEAVE(QUIC_EV_CONN_RXPKT);
6259 return ret;
6260}
6261
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006262/*
6263 * Send a Version Negotiation packet on response to <pkt> on socket <fd> to
6264 * address <addr>.
6265 * Implementation of RFC9000 6. Version Negotiation
6266 *
6267 * TODO implement a rate-limiting sending of Version Negotiation packets
6268 *
6269 * Returns 0 on success else non-zero
6270 */
6271static int send_version_negotiation(int fd, struct sockaddr_storage *addr,
6272 struct quic_rx_packet *pkt)
6273{
6274 char buf[256];
6275 int ret = 0, i = 0, j;
6276 uint32_t version;
6277 const socklen_t addrlen = get_addr_len(addr);
6278
6279 TRACE_ENTER(QUIC_EV_CONN_TXPKT);
6280 /*
6281 * header form
6282 * long header, fixed bit to 0 for Version Negotiation
6283 */
6284 /* TODO: RAND_bytes() should be replaced? */
6285 if (RAND_bytes((unsigned char *)buf, 1) != 1) {
6286 TRACE_ERROR("RAND_bytes() error", QUIC_EV_CONN_TXPKT);
6287 goto out;
6288 }
6289
6290 buf[i++] |= '\x80';
6291 /* null version for Version Negotiation */
6292 buf[i++] = '\x00';
6293 buf[i++] = '\x00';
6294 buf[i++] = '\x00';
6295 buf[i++] = '\x00';
6296
6297 /* source connection id */
6298 buf[i++] = pkt->scid.len;
6299 memcpy(&buf[i], pkt->scid.data, pkt->scid.len);
6300 i += pkt->scid.len;
6301
6302 /* destination connection id */
6303 buf[i++] = pkt->dcid.len;
6304 memcpy(&buf[i], pkt->dcid.data, pkt->dcid.len);
6305 i += pkt->dcid.len;
6306
6307 /* supported version */
6308 for (j = 0; j < quic_versions_nb; j++) {
6309 version = htonl(quic_versions[j].num);
6310 memcpy(&buf[i], &version, sizeof(version));
6311 i += sizeof(version);
6312 }
6313
6314 if (sendto(fd, buf, i, 0, (struct sockaddr *)addr, addrlen) < 0)
6315 goto out;
6316
6317 ret = 1;
6318 out:
6319 TRACE_LEAVE(QUIC_EV_CONN_TXPKT);
6320 return !ret;
6321}
6322
6323/* Send a stateless reset packet depending on <pkt> RX packet information
6324 * from <fd> UDP socket to <dst>
6325 * Return 1 if succeeded, 0 if not.
6326 */
6327static int send_stateless_reset(struct listener *l, struct sockaddr_storage *dstaddr,
6328 struct quic_rx_packet *rxpkt)
6329{
6330 int ret = 0, pktlen, rndlen;
6331 unsigned char pkt[64];
6332 const socklen_t addrlen = get_addr_len(dstaddr);
6333 struct proxy *prx;
6334 struct quic_counters *prx_counters;
6335
6336 TRACE_ENTER(QUIC_EV_STATELESS_RST);
6337
6338 prx = l->bind_conf->frontend;
6339 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
6340 /* 10.3 Stateless Reset (https://www.rfc-editor.org/rfc/rfc9000.html#section-10.3)
6341 * The resulting minimum size of 21 bytes does not guarantee that a Stateless
6342 * Reset is difficult to distinguish from other packets if the recipient requires
6343 * the use of a connection ID. To achieve that end, the endpoint SHOULD ensure
6344 * that all packets it sends are at least 22 bytes longer than the minimum
6345 * connection ID length that it requests the peer to include in its packets,
6346 * adding PADDING frames as necessary. This ensures that any Stateless Reset
6347 * sent by the peer is indistinguishable from a valid packet sent to the endpoint.
6348 * An endpoint that sends a Stateless Reset in response to a packet that is
6349 * 43 bytes or shorter SHOULD send a Stateless Reset that is one byte shorter
6350 * than the packet it responds to.
6351 */
6352
6353 /* Note that we build at most a 42 bytes QUIC packet to mimic a short packet */
6354 pktlen = rxpkt->len <= 43 ? rxpkt->len - 1 : 0;
6355 pktlen = QUIC_MAX(QUIC_STATELESS_RESET_PACKET_MINLEN, pktlen);
6356 rndlen = pktlen - QUIC_STATELESS_RESET_TOKEN_LEN;
6357
6358 /* Put a header of random bytes */
6359 /* TODO: RAND_bytes() should be replaced */
6360 if (RAND_bytes(pkt, rndlen) != 1) {
6361 TRACE_ERROR("RAND_bytes() failed", QUIC_EV_STATELESS_RST);
6362 goto leave;
6363 }
6364
6365 /* Clear the most significant bit, and set the second one */
6366 *pkt = (*pkt & ~0x80) | 0x40;
Amaury Denoyelle9b68b642023-04-12 15:48:51 +02006367 if (!quic_stateless_reset_token_cpy(pkt + rndlen, QUIC_STATELESS_RESET_TOKEN_LEN,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006368 rxpkt->dcid.data, rxpkt->dcid.len))
6369 goto leave;
6370
6371 if (sendto(l->rx.fd, pkt, pktlen, 0, (struct sockaddr *)dstaddr, addrlen) < 0)
6372 goto leave;
6373
6374 ret = 1;
6375 HA_ATOMIC_INC(&prx_counters->stateless_reset_sent);
6376 TRACE_PROTO("stateless reset sent", QUIC_EV_STATELESS_RST, NULL, &rxpkt->dcid);
6377 leave:
6378 TRACE_LEAVE(QUIC_EV_STATELESS_RST);
6379 return ret;
6380}
6381
6382/* QUIC server only function.
6383 * Add AAD to <add> buffer from <cid> connection ID and <addr> socket address.
6384 * This is the responsibility of the caller to check <aad> size is big enough
6385 * to contain these data.
6386 * Return the number of bytes copied to <aad>.
6387 */
6388static int quic_generate_retry_token_aad(unsigned char *aad,
6389 uint32_t version,
Emeric Bruna0dda4b2023-09-28 15:29:53 +02006390 const struct quic_cid *cid,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006391 const struct sockaddr_storage *addr)
6392{
6393 unsigned char *p;
6394
6395 p = aad;
Frédéric Lécaille7619aa62023-06-30 14:57:30 +02006396 *(uint32_t *)p = htonl(version);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006397 p += sizeof version;
6398 p += quic_saddr_cpy(p, addr);
Emeric Bruna0dda4b2023-09-28 15:29:53 +02006399 memcpy(p, cid->data, cid->len);
6400 p += cid->len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006401
6402 return p - aad;
6403}
6404
6405/* QUIC server only function.
6406 * Generate the token to be used in Retry packets. The token is written to
Frédéric Lécailledad0ede2023-04-24 14:35:18 +02006407 * <token> with <len> as length. <odcid> is the original destination connection
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006408 * ID and <dcid> is our side destination connection ID (or client source
6409 * connection ID).
6410 * Returns the length of the encoded token or 0 on error.
6411 */
Frédéric Lécailledad0ede2023-04-24 14:35:18 +02006412static int quic_generate_retry_token(unsigned char *token, size_t len,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006413 const uint32_t version,
6414 const struct quic_cid *odcid,
6415 const struct quic_cid *dcid,
6416 struct sockaddr_storage *addr)
6417{
6418 int ret = 0;
6419 unsigned char *p;
Emeric Bruna0dda4b2023-09-28 15:29:53 +02006420 unsigned char aad[sizeof(uint32_t) + sizeof(in_port_t) +
6421 sizeof(struct in6_addr) + QUIC_CID_MAXLEN];
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006422 size_t aadlen;
6423 unsigned char salt[QUIC_RETRY_TOKEN_SALTLEN];
6424 unsigned char key[QUIC_TLS_KEY_LEN];
6425 unsigned char iv[QUIC_TLS_IV_LEN];
Frédéric Lécaille0499db42023-09-07 18:43:52 +02006426 const unsigned char *sec = global.cluster_secret;
6427 size_t seclen = sizeof global.cluster_secret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006428 EVP_CIPHER_CTX *ctx = NULL;
6429 const EVP_CIPHER *aead = EVP_aes_128_gcm();
Emeric Brun7875f122023-07-11 16:13:19 +02006430 uint32_t timestamp = (uint32_t)date.tv_sec;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006431
6432 TRACE_ENTER(QUIC_EV_CONN_TXPKT);
6433
Frédéric Lécaille6d6ddb22023-05-15 17:40:00 +02006434 /* The token is made of the token format byte, the ODCID prefixed by its one byte
6435 * length, the creation timestamp, an AEAD TAG, and finally
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006436 * the random bytes used to derive the secret to encrypt the token.
6437 */
Frédéric Lécaille6d6ddb22023-05-15 17:40:00 +02006438 if (1 + odcid->len + 1 + sizeof(timestamp) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN > len)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006439 goto err;
6440
Emeric Bruna0dda4b2023-09-28 15:29:53 +02006441 aadlen = quic_generate_retry_token_aad(aad, version, dcid, addr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006442 /* TODO: RAND_bytes() should be replaced */
6443 if (RAND_bytes(salt, sizeof salt) != 1) {
6444 TRACE_ERROR("RAND_bytes()", QUIC_EV_CONN_TXPKT);
6445 goto err;
6446 }
6447
6448 if (!quic_tls_derive_retry_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv,
6449 salt, sizeof salt, sec, seclen)) {
6450 TRACE_ERROR("quic_tls_derive_retry_token_secret() failed", QUIC_EV_CONN_TXPKT);
6451 goto err;
6452 }
6453
6454 if (!quic_tls_tx_ctx_init(&ctx, aead, key)) {
6455 TRACE_ERROR("quic_tls_tx_ctx_init() failed", QUIC_EV_CONN_TXPKT);
6456 goto err;
6457 }
6458
6459 /* Token build */
Frédéric Lécailledad0ede2023-04-24 14:35:18 +02006460 p = token;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006461 *p++ = QUIC_TOKEN_FMT_RETRY,
6462 *p++ = odcid->len;
6463 memcpy(p, odcid->data, odcid->len);
6464 p += odcid->len;
6465 write_u32(p, htonl(timestamp));
6466 p += sizeof timestamp;
6467
6468 /* Do not encrypt the QUIC_TOKEN_FMT_RETRY byte */
Emeric Brune0190c62023-07-11 14:53:41 +02006469 if (!quic_tls_encrypt(token + 1, p - token - 1, aad, aadlen, ctx, aead, iv)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006470 TRACE_ERROR("quic_tls_encrypt() failed", QUIC_EV_CONN_TXPKT);
6471 goto err;
6472 }
6473
6474 p += QUIC_TLS_TAG_LEN;
6475 memcpy(p, salt, sizeof salt);
6476 p += sizeof salt;
6477 EVP_CIPHER_CTX_free(ctx);
6478
Frédéric Lécailledad0ede2023-04-24 14:35:18 +02006479 ret = p - token;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006480 leave:
6481 TRACE_LEAVE(QUIC_EV_CONN_TXPKT);
6482 return ret;
6483
6484 err:
6485 if (ctx)
6486 EVP_CIPHER_CTX_free(ctx);
6487 goto leave;
6488}
6489
6490/* QUIC server only function.
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006491 *
6492 * Check the validity of the Retry token from Initial packet <pkt>. <dgram> is
6493 * the UDP datagram containing <pkt> and <l> is the listener instance on which
6494 * it was received. If the token is valid, the ODCID of <qc> QUIC connection
6495 * will be put into <odcid>. <qc> is used to retrieve the QUIC version needed
6496 * to validate the token but it can be NULL : in this case the version will be
6497 * retrieved from the packet.
6498 *
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006499 * Return 1 if succeeded, 0 if not.
6500 */
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006501
6502static int quic_retry_token_check(struct quic_rx_packet *pkt,
6503 struct quic_dgram *dgram,
6504 struct listener *l,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006505 struct quic_conn *qc,
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006506 struct quic_cid *odcid)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006507{
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006508 struct proxy *prx;
6509 struct quic_counters *prx_counters;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006510 int ret = 0;
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006511 unsigned char *token = pkt->token;
6512 const uint64_t tokenlen = pkt->token_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006513 unsigned char buf[128];
Emeric Bruna0dda4b2023-09-28 15:29:53 +02006514 unsigned char aad[sizeof(uint32_t) + sizeof(in_port_t) +
6515 sizeof(struct in6_addr) + QUIC_CID_MAXLEN];
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006516 size_t aadlen;
6517 const unsigned char *salt;
6518 unsigned char key[QUIC_TLS_KEY_LEN];
6519 unsigned char iv[QUIC_TLS_IV_LEN];
Frédéric Lécaille0499db42023-09-07 18:43:52 +02006520 const unsigned char *sec = global.cluster_secret;
6521 size_t seclen = sizeof global.cluster_secret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006522 EVP_CIPHER_CTX *ctx = NULL;
6523 const EVP_CIPHER *aead = EVP_aes_128_gcm();
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006524 const struct quic_version *qv = qc ? qc->original_version :
6525 pkt->version;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006526
6527 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
6528
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006529 /* The caller must ensure this. */
Frédéric Lécaille0499db42023-09-07 18:43:52 +02006530 BUG_ON(!pkt->token_len);
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006531
6532 prx = l->bind_conf->frontend;
6533 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
6534
6535 if (*pkt->token != QUIC_TOKEN_FMT_RETRY) {
6536 /* TODO: New token check */
6537 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc, NULL, NULL, pkt->version);
6538 goto leave;
6539 }
6540
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006541 if (sizeof buf < tokenlen) {
6542 TRACE_ERROR("too short buffer", QUIC_EV_CONN_LPKT, qc);
6543 goto err;
6544 }
6545
Frédéric Lécaille35b63962023-05-15 18:11:21 +02006546 /* The token is made of the token format byte, the ODCID prefixed by its one byte
6547 * length, the creation timestamp, an AEAD TAG, and finally
6548 * the random bytes used to derive the secret to encrypt the token.
6549 */
6550 if (tokenlen < 2 + QUIC_ODCID_MINLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN ||
6551 tokenlen > 2 + QUIC_CID_MAXLEN + sizeof(uint32_t) + QUIC_TLS_TAG_LEN + QUIC_RETRY_TOKEN_SALTLEN) {
6552 TRACE_ERROR("invalid token length", QUIC_EV_CONN_LPKT, qc);
6553 goto err;
6554 }
6555
Emeric Bruna0dda4b2023-09-28 15:29:53 +02006556 aadlen = quic_generate_retry_token_aad(aad, qv->num, &pkt->scid, &dgram->saddr);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006557 salt = token + tokenlen - QUIC_RETRY_TOKEN_SALTLEN;
6558 if (!quic_tls_derive_retry_token_secret(EVP_sha256(), key, sizeof key, iv, sizeof iv,
6559 salt, QUIC_RETRY_TOKEN_SALTLEN, sec, seclen)) {
6560 TRACE_ERROR("Could not derive retry secret", QUIC_EV_CONN_LPKT, qc);
6561 goto err;
6562 }
6563
6564 if (!quic_tls_rx_ctx_init(&ctx, aead, key)) {
6565 TRACE_ERROR("quic_tls_rx_ctx_init() failed", QUIC_EV_CONN_LPKT, qc);
6566 goto err;
6567 }
6568
Frédéric Lécaille35b63962023-05-15 18:11:21 +02006569 /* The token is prefixed by a one-byte length format which is not ciphered. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006570 if (!quic_tls_decrypt2(buf, token + 1, tokenlen - QUIC_RETRY_TOKEN_SALTLEN - 1, aad, aadlen,
6571 ctx, aead, key, iv)) {
6572 TRACE_ERROR("Could not decrypt retry token", QUIC_EV_CONN_LPKT, qc);
6573 goto err;
6574 }
6575
6576 if (parse_retry_token(qc, buf, buf + tokenlen - QUIC_RETRY_TOKEN_SALTLEN - 1, odcid)) {
6577 TRACE_ERROR("Error during Initial token parsing", QUIC_EV_CONN_LPKT, qc);
6578 goto err;
6579 }
6580
6581 EVP_CIPHER_CTX_free(ctx);
6582
6583 ret = 1;
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006584 HA_ATOMIC_INC(&prx_counters->retry_validated);
6585
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006586 leave:
6587 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
6588 return ret;
6589
6590 err:
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006591 HA_ATOMIC_INC(&prx_counters->retry_error);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006592 if (ctx)
6593 EVP_CIPHER_CTX_free(ctx);
6594 goto leave;
6595}
6596
6597/* Generate a Retry packet and send it on <fd> socket to <addr> in response to
6598 * the Initial <pkt> packet.
6599 *
6600 * Returns 0 on success else non-zero.
6601 */
6602static int send_retry(int fd, struct sockaddr_storage *addr,
6603 struct quic_rx_packet *pkt, const struct quic_version *qv)
6604{
6605 int ret = 0;
6606 unsigned char buf[128];
6607 int i = 0, token_len;
6608 const socklen_t addrlen = get_addr_len(addr);
6609 struct quic_cid scid;
6610
6611 TRACE_ENTER(QUIC_EV_CONN_TXPKT);
6612
Frédéric Lécaille2b220542023-06-30 12:17:36 +02006613 /* long header(1) | fixed bit(1) | packet type QUIC_PACKET_TYPE_RETRY(2) | unused random bits(4)*/
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006614 buf[i++] = (QUIC_PACKET_LONG_HEADER_BIT | QUIC_PACKET_FIXED_BIT) |
Frédéric Lécaille2b220542023-06-30 12:17:36 +02006615 (quic_pkt_type(QUIC_PACKET_TYPE_RETRY, qv->num) << QUIC_PACKET_TYPE_SHIFT) |
6616 statistical_prng_range(16);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006617 /* version */
Emeric Brun2b6d45e2023-07-17 18:33:44 +02006618 write_n32(&buf[i], qv->num);
Frédéric Lécaille966e4682023-06-30 14:41:31 +02006619 i += sizeof(uint32_t);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006620
6621 /* Use the SCID from <pkt> for Retry DCID. */
6622 buf[i++] = pkt->scid.len;
6623 memcpy(&buf[i], pkt->scid.data, pkt->scid.len);
6624 i += pkt->scid.len;
6625
6626 /* Generate a new CID to be used as SCID for the Retry packet. */
6627 scid.len = QUIC_HAP_CID_LEN;
6628 /* TODO: RAND_bytes() should be replaced */
6629 if (RAND_bytes(scid.data, scid.len) != 1) {
6630 TRACE_ERROR("RAND_bytes() failed", QUIC_EV_CONN_TXPKT);
6631 goto out;
6632 }
6633
6634 buf[i++] = scid.len;
6635 memcpy(&buf[i], scid.data, scid.len);
6636 i += scid.len;
6637
6638 /* token */
6639 if (!(token_len = quic_generate_retry_token(&buf[i], sizeof(buf) - i, qv->num,
Emeric Bruna0dda4b2023-09-28 15:29:53 +02006640 &pkt->dcid, &pkt->scid, addr))) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006641 TRACE_ERROR("quic_generate_retry_token() failed", QUIC_EV_CONN_TXPKT);
6642 goto out;
6643 }
6644
6645 i += token_len;
6646
6647 /* token integrity tag */
Emeric Bruna47f5cd2023-06-27 15:24:05 +02006648 if ((sizeof(buf) - i < QUIC_TLS_TAG_LEN) ||
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006649 !quic_tls_generate_retry_integrity_tag(pkt->dcid.data,
6650 pkt->dcid.len, buf, i, qv)) {
6651 TRACE_ERROR("quic_tls_generate_retry_integrity_tag() failed", QUIC_EV_CONN_TXPKT);
6652 goto out;
6653 }
6654
6655 i += QUIC_TLS_TAG_LEN;
6656
6657 if (sendto(fd, buf, i, 0, (struct sockaddr *)addr, addrlen) < 0) {
6658 TRACE_ERROR("quic_tls_generate_retry_integrity_tag() failed", QUIC_EV_CONN_TXPKT);
6659 goto out;
6660 }
6661
6662 ret = 1;
6663 out:
6664 TRACE_LEAVE(QUIC_EV_CONN_TXPKT);
6665 return !ret;
6666}
6667
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006668/* Retrieve a quic_conn instance from the <pkt> DCID field. If the packet is an
6669 * INITIAL or 0RTT type, we may have to use client address <saddr> if an ODCID
6670 * is used.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006671 *
6672 * Returns the instance or NULL if not found.
6673 */
6674static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt,
6675 struct listener *l,
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006676 struct sockaddr_storage *saddr,
6677 int *new_tid)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006678{
6679 struct quic_conn *qc = NULL;
6680 struct ebmb_node *node;
Amaury Denoyelle591e7982023-04-12 10:04:49 +02006681 struct quic_connection_id *conn_id;
Amaury Denoyellee83f9372023-04-18 11:10:54 +02006682 struct quic_cid_tree *tree;
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006683 uint conn_id_tid;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006684
6685 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006686 *new_tid = -1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006687
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006688 /* First look into DCID tree. */
Amaury Denoyellee83f9372023-04-18 11:10:54 +02006689 tree = &quic_cid_trees[_quic_cid_tree_idx(pkt->dcid.data)];
6690 HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
6691 node = ebmb_lookup(&tree->root, pkt->dcid.data, pkt->dcid.len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006692
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006693 /* If not found on an Initial/0-RTT packet, it could be because an
6694 * ODCID is reused by the client. Calculate the derived CID value to
6695 * retrieve it from the DCID tree.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006696 */
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006697 if (!node && (pkt->type == QUIC_PACKET_TYPE_INITIAL ||
6698 pkt->type == QUIC_PACKET_TYPE_0RTT)) {
Amaury Denoyellec2a92642023-04-13 15:26:18 +02006699 const struct quic_cid derive_cid = quic_derive_cid(&pkt->dcid, saddr);
Amaury Denoyellee83f9372023-04-18 11:10:54 +02006700
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006701 HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
6702
Amaury Denoyellee83f9372023-04-18 11:10:54 +02006703 tree = &quic_cid_trees[quic_cid_tree_idx(&derive_cid)];
6704 HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
6705 node = ebmb_lookup(&tree->root, derive_cid.data, derive_cid.len);
Amaury Denoyelle2c982092023-04-03 18:50:58 +02006706 }
6707
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006708 if (!node)
6709 goto end;
6710
Amaury Denoyelle591e7982023-04-12 10:04:49 +02006711 conn_id = ebmb_entry(node, struct quic_connection_id, node);
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006712 conn_id_tid = HA_ATOMIC_LOAD(&conn_id->tid);
6713 if (conn_id_tid != tid) {
6714 *new_tid = conn_id_tid;
6715 goto end;
6716 }
Amaury Denoyelle591e7982023-04-12 10:04:49 +02006717 qc = conn_id->qc;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006718
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006719 end:
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006720 HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006721 TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
6722 return qc;
6723}
6724
6725/* Try to allocate the <*ssl> SSL session object for <qc> QUIC connection
6726 * with <ssl_ctx> as SSL context inherited settings. Also set the transport
6727 * parameters of this session.
6728 * This is the responsibility of the caller to check the validity of all the
6729 * pointers passed as parameter to this function.
6730 * Return 0 if succeeded, -1 if not. If failed, sets the ->err_code member of <qc->conn> to
6731 * CO_ER_SSL_NO_MEM.
6732 */
6733static int qc_ssl_sess_init(struct quic_conn *qc, SSL_CTX *ssl_ctx, SSL **ssl,
6734 unsigned char *params, size_t params_len)
6735{
6736 int retry, ret = -1;
6737
6738 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
6739
6740 retry = 1;
6741 retry:
6742 *ssl = SSL_new(ssl_ctx);
6743 if (!*ssl) {
6744 if (!retry--)
Frédéric Lécaillee4185272023-06-02 16:56:16 +02006745 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006746
6747 pool_gc(NULL);
6748 goto retry;
6749 }
6750
Frédéric Lécailleca87a622023-06-02 17:00:04 +02006751 if (!SSL_set_ex_data(*ssl, ssl_qc_app_data_index, qc) ||
6752 !SSL_set_quic_method(*ssl, &ha_quic_method)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006753 SSL_free(*ssl);
6754 *ssl = NULL;
6755 if (!retry--)
Frédéric Lécaillee4185272023-06-02 16:56:16 +02006756 goto leave;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006757
6758 pool_gc(NULL);
6759 goto retry;
6760 }
6761
6762 ret = 0;
6763 leave:
6764 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
6765 return ret;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006766}
6767
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006768/* Allocate the ssl_sock_ctx from connection <qc>. This creates the tasklet
6769 * used to process <qc> received packets. The allocated context is stored in
6770 * <qc.xprt_ctx>.
6771 *
6772 * Returns 0 on success else non-zero.
6773 */
6774static int qc_conn_alloc_ssl_ctx(struct quic_conn *qc)
6775{
6776 int ret = 0;
6777 struct bind_conf *bc = qc->li->bind_conf;
6778 struct ssl_sock_ctx *ctx = NULL;
6779
6780 TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
6781
6782 ctx = pool_zalloc(pool_head_quic_conn_ctx);
6783 if (!ctx) {
6784 TRACE_ERROR("SSL context allocation failed", QUIC_EV_CONN_TXPKT);
6785 goto err;
6786 }
6787
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006788 ctx->subs = NULL;
6789 ctx->xprt_ctx = NULL;
6790 ctx->qc = qc;
6791
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006792 if (qc_is_listener(qc)) {
6793 if (qc_ssl_sess_init(qc, bc->initial_ctx, &ctx->ssl,
6794 qc->enc_params, qc->enc_params_len) == -1) {
6795 goto err;
6796 }
6797#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
Frédéric Lécaille65a8b9a2023-06-02 17:05:38 +02006798#ifndef USE_QUIC_OPENSSL_COMPAT
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006799 /* Enabling 0-RTT */
6800 if (bc->ssl_conf.early_data)
6801 SSL_set_quic_early_data_enabled(ctx->ssl, 1);
6802#endif
Frédéric Lécaille65a8b9a2023-06-02 17:05:38 +02006803#endif
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006804
6805 SSL_set_accept_state(ctx->ssl);
6806 }
6807
6808 ctx->xprt = xprt_get(XPRT_QUIC);
6809
6810 /* Store the allocated context in <qc>. */
6811 qc->xprt_ctx = ctx;
6812
6813 ret = 1;
6814 leave:
6815 TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
6816 return !ret;
6817
6818 err:
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006819 pool_free(pool_head_quic_conn_ctx, ctx);
6820 goto leave;
6821}
6822
Frédéric Lécaille7f0b1c72023-04-24 14:38:33 +02006823/* Check that all the bytes between <pos> included and <end> address
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006824 * excluded are null. This is the responsibility of the caller to
Frédéric Lécaille7f0b1c72023-04-24 14:38:33 +02006825 * check that there is at least one byte between <pos> end <end>.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006826 * Return 1 if this all the bytes are null, 0 if not.
6827 */
Frédéric Lécaille7f0b1c72023-04-24 14:38:33 +02006828static inline int quic_padding_check(const unsigned char *pos,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006829 const unsigned char *end)
6830{
Frédéric Lécaille7f0b1c72023-04-24 14:38:33 +02006831 while (pos < end && !*pos)
6832 pos++;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006833
Frédéric Lécaille7f0b1c72023-04-24 14:38:33 +02006834 return pos == end;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006835}
6836
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006837/* Find the associated connection to the packet <pkt> or create a new one if
6838 * this is an Initial packet. <dgram> is the datagram containing the packet and
6839 * <l> is the listener instance on which it was received.
6840 *
Amaury Denoyelle25174d52023-04-05 17:52:05 +02006841 * By default, <new_tid> is set to -1. However, if thread affinity has been
6842 * chanbed, it will be set to its new thread ID.
6843 *
6844 * Returns the quic-conn instance or NULL if not found or thread affinity
6845 * changed.
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006846 */
6847static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
6848 struct quic_dgram *dgram,
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006849 struct listener *l,
6850 int *new_tid)
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006851{
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006852 struct quic_cid token_odcid = { .len = 0 };
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006853 struct quic_conn *qc = NULL;
6854 struct proxy *prx;
6855 struct quic_counters *prx_counters;
6856
6857 TRACE_ENTER(QUIC_EV_CONN_LPKT);
6858
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006859 *new_tid = -1;
6860
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006861 prx = l->bind_conf->frontend;
6862 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
6863
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006864 qc = retrieve_qc_conn_from_cid(pkt, l, &dgram->saddr, new_tid);
6865
Amaury Denoyelle25174d52023-04-05 17:52:05 +02006866 /* If connection already created or rebinded on another thread. */
Frédéric Lécailleab3aa0f2023-05-24 09:06:06 +02006867 if (!qc && *new_tid != -1 && tid != *new_tid)
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006868 goto out;
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006869
6870 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
6871 BUG_ON(!pkt->version); /* This must not happen. */
6872
Frédéric Lécaille0499db42023-09-07 18:43:52 +02006873 if (pkt->token_len) {
Amaury Denoyelle9e3026c2022-10-17 11:13:07 +02006874 if (!quic_retry_token_check(pkt, dgram, l, qc, &token_odcid))
6875 goto err;
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006876 }
6877
6878 if (!qc) {
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006879 struct quic_cid_tree *tree;
6880 struct ebmb_node *node;
6881 struct quic_connection_id *conn_id;
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006882 int ipv4;
6883
Frédéric Lécaille0499db42023-09-07 18:43:52 +02006884 if (!pkt->token_len && !(l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) &&
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006885 HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold) {
6886 TRACE_PROTO("Initial without token, sending retry",
6887 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
6888 if (send_retry(l->rx.fd, &dgram->saddr, pkt, pkt->version)) {
6889 TRACE_ERROR("Error during Retry generation",
6890 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
6891 goto out;
6892 }
6893
6894 HA_ATOMIC_INC(&prx_counters->retry_sent);
6895 goto out;
6896 }
6897
6898 /* RFC 9000 7.2. Negotiating Connection IDs:
6899 * When an Initial packet is sent by a client that has not previously
6900 * received an Initial or Retry packet from the server, the client
6901 * populates the Destination Connection ID field with an unpredictable
6902 * value. This Destination Connection ID MUST be at least 8 bytes in length.
6903 */
6904 if (pkt->dcid.len < QUIC_ODCID_MINLEN) {
6905 TRACE_PROTO("dropped packet",
6906 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
6907 goto err;
6908 }
6909
6910 pkt->saddr = dgram->saddr;
6911 ipv4 = dgram->saddr.ss_family == AF_INET;
6912
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006913 /* Generate the first connection CID. This is derived from the client
6914 * ODCID and address. This allows to retrieve the connection from the
6915 * ODCID without storing it in the CID tree. This is an interesting
6916 * optimization as the client is expected to stop using its ODCID in
6917 * favor of our generated value.
6918 */
6919 conn_id = new_quic_cid(NULL, NULL, &pkt->dcid, &pkt->saddr);
6920 if (!conn_id)
6921 goto err;
6922
Frédéric Lécaillefd212a72023-06-16 16:10:58 +02006923 qc = qc_new_conn(pkt->version, ipv4, &pkt->dcid, &pkt->scid, &token_odcid,
6924 conn_id, &dgram->daddr, &pkt->saddr, 1,
6925 !!pkt->token_len, l);
6926 if (qc == NULL) {
Frédéric Lécaillefd212a72023-06-16 16:10:58 +02006927 pool_free(pool_head_quic_connection_id, conn_id);
6928 goto err;
6929 }
6930
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006931 tree = &quic_cid_trees[quic_cid_tree_idx(&conn_id->cid)];
6932 HA_RWLOCK_WRLOCK(QC_CID_LOCK, &tree->lock);
6933 node = ebmb_insert(&tree->root, &conn_id->node, conn_id->cid.len);
6934 if (node != &conn_id->node) {
6935 pool_free(pool_head_quic_connection_id, conn_id);
6936
6937 conn_id = ebmb_entry(node, struct quic_connection_id, node);
6938 *new_tid = HA_ATOMIC_LOAD(&conn_id->tid);
Frédéric Lécaillefd212a72023-06-16 16:10:58 +02006939 quic_conn_release(qc);
6940 qc = NULL;
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006941 }
Frédéric Lécaille8a586582023-06-26 10:39:56 +02006942 else {
6943 /* From here, <qc> is the correct connection for this <pkt> Initial
6944 * packet. <conn_id> must be inserted in the CIDs tree for this
6945 * connection.
6946 */
6947 eb64_insert(&qc->cids, &conn_id->seq_num);
6948 /* Initialize the next CID sequence number to be used for this connection. */
6949 qc->next_cid_seq_num = 1;
6950 }
Amaury Denoyellef16ec342023-04-13 17:42:34 +02006951 HA_RWLOCK_WRUNLOCK(QC_CID_LOCK, &tree->lock);
6952
6953 if (*new_tid != -1)
6954 goto out;
6955
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006956 HA_ATOMIC_INC(&prx_counters->half_open_conn);
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006957 }
6958 }
6959 else if (!qc) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01006960 TRACE_PROTO("RX non Initial pkt without connection", QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
Frédéric Lécaille0499db42023-09-07 18:43:52 +02006961 if (!send_stateless_reset(l, &dgram->saddr, pkt))
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006962 TRACE_ERROR("stateless reset not sent", QUIC_EV_CONN_LPKT, qc);
6963 goto err;
6964 }
6965
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006966 out:
6967 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
6968 return qc;
6969
6970 err:
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02006971 if (qc)
6972 qc->cntrs.dropped_pkt++;
6973 else
6974 HA_ATOMIC_INC(&prx_counters->dropped_pkt);
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02006975 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
6976 return NULL;
6977}
6978
Frédéric Lécaillebef30982023-04-24 14:43:57 +02006979/* Parse a QUIC packet starting at <pos>. Data won't be read after <end> even
Amaury Denoyelle98289692022-10-19 15:37:44 +02006980 * if the packet is incomplete. This function will populate fields of <pkt>
6981 * instance, most notably its length. <dgram> is the UDP datagram which
6982 * contains the parsed packet. <l> is the listener instance on which it was
6983 * received.
6984 *
6985 * Returns 0 on success else non-zero. Packet length is guaranteed to be set to
Frédéric Lécaillebef30982023-04-24 14:43:57 +02006986 * the real packet value or to cover all data between <pos> and <end> : this is
Amaury Denoyelle98289692022-10-19 15:37:44 +02006987 * useful to reject a whole datagram.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006988 */
Amaury Denoyelle98289692022-10-19 15:37:44 +02006989static int quic_rx_pkt_parse(struct quic_rx_packet *pkt,
Frédéric Lécaillebef30982023-04-24 14:43:57 +02006990 unsigned char *pos, const unsigned char *end,
Amaury Denoyelle98289692022-10-19 15:37:44 +02006991 struct quic_dgram *dgram, struct listener *l)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006992{
Frédéric Lécaillebef30982023-04-24 14:43:57 +02006993 const unsigned char *beg = pos;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006994 struct proxy *prx;
6995 struct quic_counters *prx_counters;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006996
6997 TRACE_ENTER(QUIC_EV_CONN_LPKT);
6998
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02006999 prx = l->bind_conf->frontend;
7000 prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
7001 /* This ist only to please to traces and distinguish the
7002 * packet with parsed packet number from others.
7003 */
7004 pkt->pn_node.key = (uint64_t)-1;
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007005 if (end <= pos) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007006 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
7007 goto drop;
7008 }
7009
7010 /* Fixed bit */
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007011 if (!(*pos & QUIC_PACKET_FIXED_BIT)) {
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02007012 if (!(pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST) &&
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007013 quic_padding_check(pos, end)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007014 /* Some browsers may pad the remaining datagram space with null bytes.
7015 * That is what we called add padding out of QUIC packets. Such
7016 * datagrams must be considered as valid. But we can only consume
7017 * the remaining space.
7018 */
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007019 pkt->len = end - pos;
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007020 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007021 }
7022
7023 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
7024 goto drop;
7025 }
7026
7027 /* Header form */
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007028 if (!qc_parse_hd_form(pkt, &pos, end)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007029 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
7030 goto drop;
7031 }
7032
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02007033 if (pkt->type != QUIC_PACKET_TYPE_SHORT) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007034 uint64_t len;
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02007035 TRACE_PROTO("long header packet received", QUIC_EV_CONN_LPKT);
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02007036
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007037 if (!quic_packet_read_long_header(&pos, end, pkt)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007038 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
7039 goto drop;
7040 }
7041
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007042 /* When multiple QUIC packets are coalesced on the same UDP datagram,
7043 * they must have the same DCID.
7044 */
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02007045 if (!(pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST) &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007046 (pkt->dcid.len != dgram->dcid_len ||
7047 memcmp(dgram->dcid, pkt->dcid.data, pkt->dcid.len))) {
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02007048 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007049 goto drop;
7050 }
7051
7052 /* Retry of Version Negotiation packets are only sent by servers */
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02007053 if (pkt->type == QUIC_PACKET_TYPE_RETRY ||
7054 (pkt->version && !pkt->version->num)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007055 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
7056 goto drop;
7057 }
7058
7059 /* RFC9000 6. Version Negotiation */
Amaury Denoyelle1a5cc192023-04-17 15:03:51 +02007060 if (!pkt->version) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007061 /* unsupported version, send Negotiation packet */
7062 if (send_version_negotiation(l->rx.fd, &dgram->saddr, pkt)) {
7063 TRACE_ERROR("VN packet not sent", QUIC_EV_CONN_LPKT);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007064 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007065 }
7066
7067 TRACE_PROTO("VN packet sent", QUIC_EV_CONN_LPKT);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007068 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007069 }
7070
7071 /* For Initial packets, and for servers (QUIC clients connections),
7072 * there is no Initial connection IDs storage.
7073 */
7074 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
7075 uint64_t token_len;
7076
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007077 if (!quic_dec_int(&token_len, (const unsigned char **)&pos, end) ||
7078 end - pos < token_len) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007079 TRACE_PROTO("Packet dropped",
Amaury Denoyelle89e48ff2023-04-19 10:04:41 +02007080 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007081 goto drop;
7082 }
7083
7084 /* TODO Retry should be automatically activated if
7085 * suspect network usage is detected.
7086 */
Frédéric Lécaille0499db42023-09-07 18:43:52 +02007087 if (!token_len) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007088 if (l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) {
7089 TRACE_PROTO("Initial without token, sending retry",
Amaury Denoyelle89e48ff2023-04-19 10:04:41 +02007090 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
7091 if (send_retry(l->rx.fd, &dgram->saddr, pkt, pkt->version)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007092 TRACE_PROTO("Error during Retry generation",
Amaury Denoyelle89e48ff2023-04-19 10:04:41 +02007093 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007094 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007095 }
7096
7097 HA_ATOMIC_INC(&prx_counters->retry_sent);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007098 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007099 }
7100 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007101
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007102 pkt->token = pos;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007103 pkt->token_len = token_len;
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007104 pos += pkt->token_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007105 }
7106 else if (pkt->type != QUIC_PACKET_TYPE_0RTT) {
7107 if (pkt->dcid.len != QUIC_HAP_CID_LEN) {
7108 TRACE_PROTO("Packet dropped",
Amaury Denoyelle89e48ff2023-04-19 10:04:41 +02007109 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007110 goto drop;
7111 }
7112 }
7113
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007114 if (!quic_dec_int(&len, (const unsigned char **)&pos, end) ||
7115 end - pos < len) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007116 TRACE_PROTO("Packet dropped",
Amaury Denoyelle89e48ff2023-04-19 10:04:41 +02007117 QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007118 goto drop;
7119 }
7120
Amaury Denoyelle845169d2022-10-17 18:05:26 +02007121 /* Packet Number is stored here. Packet Length totalizes the
7122 * rest of the content.
7123 */
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007124 pkt->pn_offset = pos - beg;
Amaury Denoyelle845169d2022-10-17 18:05:26 +02007125 pkt->len = pkt->pn_offset + len;
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007126
Frédéric Lécaille35218c62023-02-16 11:40:11 +01007127 /* RFC 9000. Initial Datagram Size
7128 *
7129 * A server MUST discard an Initial packet that is carried in a UDP datagram
7130 * with a payload that is smaller than the smallest allowed maximum datagram
7131 * size of 1200 bytes.
7132 */
7133 if (pkt->type == QUIC_PACKET_TYPE_INITIAL &&
7134 dgram->len < QUIC_INITIAL_PACKET_MINLEN) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007135 TRACE_PROTO("RX too short datagram with an Initial packet", QUIC_EV_CONN_LPKT);
Frédéric Lécaille35218c62023-02-16 11:40:11 +01007136 HA_ATOMIC_INC(&prx_counters->too_short_initial_dgram);
7137 goto drop;
7138 }
7139
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007140 /* Interrupt parsing after packet length retrieval : this
7141 * ensures that only the packet is dropped but not the whole
7142 * datagram.
7143 */
7144 if (pkt->type == QUIC_PACKET_TYPE_0RTT && !l->bind_conf->ssl_conf.early_data) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007145 TRACE_PROTO("RX 0-RTT packet not supported", QUIC_EV_CONN_LPKT);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007146 goto drop;
7147 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007148 }
7149 else {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007150 TRACE_PROTO("RX short header packet", QUIC_EV_CONN_LPKT);
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007151 if (end - pos < QUIC_HAP_CID_LEN) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007152 TRACE_PROTO("RX pkt dropped", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007153 goto drop;
7154 }
7155
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007156 memcpy(pkt->dcid.data, pos, QUIC_HAP_CID_LEN);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007157 pkt->dcid.len = QUIC_HAP_CID_LEN;
7158
7159 /* When multiple QUIC packets are coalesced on the same UDP datagram,
7160 * they must have the same DCID.
7161 */
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02007162 if (!(pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST) &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007163 (pkt->dcid.len != dgram->dcid_len ||
7164 memcmp(dgram->dcid, pkt->dcid.data, pkt->dcid.len))) {
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007165 TRACE_PROTO("RX pkt dropped", QUIC_EV_CONN_LPKT);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007166 goto drop;
7167 }
7168
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007169 pos += QUIC_HAP_CID_LEN;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007170
Frédéric Lécaillebef30982023-04-24 14:43:57 +02007171 pkt->pn_offset = pos - beg;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007172 /* A short packet is the last one of a UDP datagram. */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007173 pkt->len = end - beg;
Amaury Denoyelle449b1a82022-10-19 15:28:44 +02007174 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007175
Amaury Denoyelle89e48ff2023-04-19 10:04:41 +02007176 TRACE_PROTO("RX pkt parsed", QUIC_EV_CONN_LPKT, NULL, pkt, NULL, pkt->version);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007177 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
Amaury Denoyelle98289692022-10-19 15:37:44 +02007178 return 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007179
Amaury Denoyelle98289692022-10-19 15:37:44 +02007180 drop:
7181 HA_ATOMIC_INC(&prx_counters->dropped_pkt);
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007182 drop_silent:
Amaury Denoyelle98289692022-10-19 15:37:44 +02007183 if (!pkt->len)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007184 pkt->len = end - beg;
Amaury Denoyelle89e48ff2023-04-19 10:04:41 +02007185 TRACE_PROTO("RX pkt parsing failed", QUIC_EV_CONN_LPKT, NULL, pkt, NULL, pkt->version);
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007186 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
Amaury Denoyelle98289692022-10-19 15:37:44 +02007187 return -1;
7188}
7189
7190/* Check if received packet <pkt> should be drop due to <qc> already in closing
7191 * state. This can be true if a CONNECTION_CLOSE has already been emitted for
7192 * this connection.
7193 *
7194 * Returns false if connection is not in closing state else true. The caller
7195 * should drop the whole datagram in the last case to not mess up <qc>
7196 * CONNECTION_CLOSE rate limit counter.
7197 */
7198static int qc_rx_check_closing(struct quic_conn *qc,
7199 struct quic_rx_packet *pkt)
7200{
7201 if (!(qc->flags & QUIC_FL_CONN_CLOSING))
7202 return 0;
7203
7204 TRACE_STATE("Closing state connection", QUIC_EV_CONN_LPKT, qc, NULL, NULL, pkt->version);
7205
7206 /* Check if CONNECTION_CLOSE rate reemission is reached. */
7207 if (++qc->nb_pkt_since_cc >= qc->nb_pkt_for_cc) {
7208 qc->flags |= QUIC_FL_CONN_IMMEDIATE_CLOSE;
7209 qc->nb_pkt_for_cc++;
7210 qc->nb_pkt_since_cc = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007211 }
7212
Amaury Denoyelle98289692022-10-19 15:37:44 +02007213 return 1;
7214}
7215
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007216/* React to a connection migration initiated on <qc> by a client with the new
7217 * path addresses <peer_addr>/<local_addr>.
7218 *
7219 * Returns 0 on success else non-zero.
7220 */
7221static int qc_handle_conn_migration(struct quic_conn *qc,
7222 const struct sockaddr_storage *peer_addr,
7223 const struct sockaddr_storage *local_addr)
7224{
7225 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
7226
Frédéric Lécaille6fc86972023-01-12 08:29:23 +01007227 /* RFC 9000. Connection Migration
7228 *
7229 * If the peer sent the disable_active_migration transport parameter,
7230 * an endpoint also MUST NOT send packets (including probing packets;
7231 * see Section 9.1) from a different local address to the address the peer
7232 * used during the handshake, unless the endpoint has acted on a
7233 * preferred_address transport parameter from the peer.
7234 */
7235 if (qc->li->bind_conf->quic_params.disable_active_migration) {
7236 TRACE_ERROR("Active migration was disabled, datagram dropped", QUIC_EV_CONN_LPKT, qc);
7237 goto err;
7238 }
7239
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007240 /* RFC 9000 9. Connection Migration
7241 *
Amaury Denoyelleeb6be982022-11-21 11:14:45 +01007242 * The design of QUIC relies on endpoints retaining a stable address for
7243 * the duration of the handshake. An endpoint MUST NOT initiate
7244 * connection migration before the handshake is confirmed, as defined in
7245 * Section 4.1.2 of [QUIC-TLS].
7246 */
7247 if (qc->state < QUIC_HS_ST_COMPLETE) {
7248 TRACE_STATE("Connection migration during handshake rejected", QUIC_EV_CONN_LPKT, qc);
7249 goto err;
7250 }
7251
7252 /* RFC 9000 9. Connection Migration
7253 *
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007254 * TODO
7255 * An endpoint MUST
7256 * perform path validation (Section 8.2) if it detects any change to a
7257 * peer's address, unless it has previously validated that address.
7258 */
7259
Amaury Denoyelled3083c92022-12-01 16:20:06 +01007260 /* Update quic-conn owned socket if in used.
7261 * TODO try to reuse it instead of closing and opening a new one.
7262 */
7263 if (qc_test_fd(qc)) {
7264 /* TODO try to reuse socket instead of closing it and opening a new one. */
7265 TRACE_STATE("Connection migration detected, allocate a new connection socket", QUIC_EV_CONN_LPKT, qc);
7266 qc_release_fd(qc, 1);
Amaury Denoyellefb375572023-02-01 09:28:32 +01007267 /* TODO need to adjust <jobs> on socket allocation failure. */
Amaury Denoyelled3083c92022-12-01 16:20:06 +01007268 qc_alloc_fd(qc, local_addr, peer_addr);
7269 }
7270
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007271 qc->local_addr = *local_addr;
7272 qc->peer_addr = *peer_addr;
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02007273 qc->cntrs.conn_migration_done++;
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01007274
7275 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
7276 return 0;
7277
7278 err:
7279 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
7280 return 1;
7281}
7282
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007283/* Release the memory for the RX packets which are no more referenced
7284 * and consume their payloads which have been copied to the RX buffer
7285 * for the connection.
7286 * Always succeeds.
7287 */
7288static inline void quic_rx_pkts_del(struct quic_conn *qc)
7289{
7290 struct quic_rx_packet *pkt, *pktback;
7291
7292 list_for_each_entry_safe(pkt, pktback, &qc->rx.pkt_list, qc_rx_pkt_list) {
7293 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_LPKT, qc, 0, 0, 0,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007294 "pkt #%lld(type=%d,len=%llu,rawlen=%llu,refcnt=%u) (diff: %zd)",
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007295 (long long)pkt->pn_node.key,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007296 pkt->type, (ull)pkt->len, (ull)pkt->raw_len, pkt->refcnt,
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007297 (unsigned char *)b_head(&qc->rx.buf) - pkt->data);
7298 if (pkt->data != (unsigned char *)b_head(&qc->rx.buf)) {
7299 size_t cdata;
7300
7301 cdata = b_contig_data(&qc->rx.buf, 0);
7302 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_LPKT, qc, 0, 0, 0,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007303 "cdata=%llu *b_head()=0x%x", (ull)cdata, *b_head(&qc->rx.buf));
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007304 if (cdata && !*b_head(&qc->rx.buf)) {
7305 /* Consume the remaining data */
7306 b_del(&qc->rx.buf, cdata);
7307 }
7308 break;
7309 }
7310
7311 if (pkt->refcnt)
7312 break;
7313
7314 b_del(&qc->rx.buf, pkt->raw_len);
7315 LIST_DELETE(&pkt->qc_rx_pkt_list);
7316 pool_free(pool_head_quic_rx_packet, pkt);
7317 }
7318
7319 /* In frequent cases the buffer will be emptied at this stage. */
7320 b_realign_if_empty(&qc->rx.buf);
7321}
7322
Amaury Denoyelle98289692022-10-19 15:37:44 +02007323/* Handle a parsed packet <pkt> by the connection <qc>. Data will be copied
7324 * into <qc> receive buffer after header protection removal procedure.
7325 *
7326 * <dgram> must be set to the datagram which contains the QUIC packet. <beg>
7327 * must point to packet buffer first byte.
7328 *
7329 * <tasklist_head> may be non-NULL when the caller treat several datagrams for
7330 * different quic-conn. In this case, each quic-conn tasklet will be appended
7331 * to it in order to be woken up after the current task.
7332 *
7333 * The caller can safely removed the packet data. If packet refcount was not
7334 * incremented by this function, it means that the connection did not handled
7335 * it and it should be freed by the caller.
7336 */
7337static void qc_rx_pkt_handle(struct quic_conn *qc, struct quic_rx_packet *pkt,
7338 struct quic_dgram *dgram, unsigned char *beg,
7339 struct list **tasklist_head)
7340{
7341 const struct quic_version *qv = pkt->version;
7342 struct quic_enc_level *qel = NULL;
7343 size_t b_cspace;
Amaury Denoyelle98289692022-10-19 15:37:44 +02007344
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007345 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
7346 TRACE_PROTO("RX pkt", QUIC_EV_CONN_LPKT, qc, pkt, NULL, qv);
Amaury Denoyelle3f474e62022-11-24 17:15:08 +01007347
Amaury Denoyelledeb7c872022-10-19 17:14:28 +02007348 if (pkt->flags & QUIC_FL_RX_PACKET_DGRAM_FIRST &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007349 qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED) {
7350 TRACE_PROTO("PTO timer must be armed after anti-amplication was reached",
7351 QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01007352 TRACE_DEVEL("needs to wakeup the timer task after the amplification limit was reached",
7353 QUIC_EV_CONN_LPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007354 /* Reset the anti-amplification bit. It will be set again
7355 * when sending the next packet if reached again.
7356 */
7357 qc->flags &= ~QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
Frédéric Lécaillea65b71f2023-03-03 10:16:32 +01007358 qc_set_timer(qc);
7359 if (qc->timer_task && tick_isset(qc->timer) && tick_is_lt(qc->timer, now_ms))
7360 task_wakeup(qc->timer_task, TASK_WOKEN_MSG);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007361 }
7362
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007363 if (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) {
7364 TRACE_PROTO("Connection error",
7365 QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
7366 goto out;
7367 }
7368
7369 pkt->raw_len = pkt->len;
7370 quic_rx_pkts_del(qc);
7371 b_cspace = b_contig_space(&qc->rx.buf);
7372 if (b_cspace < pkt->len) {
Frédéric Lécaille1dbeb352023-02-07 11:40:21 +01007373 TRACE_PRINTF(TRACE_LEVEL_DEVELOPER, QUIC_EV_CONN_LPKT, qc, 0, 0, 0,
Frédéric Lécailleb7a13be2023-02-22 17:24:23 +01007374 "bspace=%llu pkt->len=%llu", (ull)b_cspace, (ull)pkt->len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007375 /* Do not consume buf if space not at the end. */
7376 if (b_tail(&qc->rx.buf) + b_cspace < b_wrap(&qc->rx.buf)) {
7377 TRACE_PROTO("Packet dropped",
7378 QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02007379 qc->cntrs.dropped_pkt_bufoverrun++;
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007380 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007381 }
7382
7383 /* Let us consume the remaining contiguous space. */
7384 if (b_cspace) {
7385 b_putchr(&qc->rx.buf, 0x00);
7386 b_cspace--;
7387 }
7388 b_add(&qc->rx.buf, b_cspace);
7389 if (b_contig_space(&qc->rx.buf) < pkt->len) {
7390 TRACE_PROTO("Too big packet",
7391 QUIC_EV_CONN_LPKT, qc, pkt, &pkt->len, qv);
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02007392 qc->cntrs.dropped_pkt_bufoverrun++;
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007393 goto drop_silent;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007394 }
7395 }
7396
Amaury Denoyelle845169d2022-10-17 18:05:26 +02007397 if (!qc_try_rm_hp(qc, pkt, beg, &qel)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007398 TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
7399 goto drop;
7400 }
7401
7402 TRACE_DATA("New packet", QUIC_EV_CONN_LPKT, qc, pkt, NULL, qv);
7403 if (pkt->aad_len)
7404 qc_pkt_insert(qc, pkt, qel);
7405 out:
Amaury Denoyelle2ed84002022-09-26 14:53:59 +02007406 *tasklist_head = tasklet_wakeup_after(*tasklist_head,
7407 qc->wait_event.tasklet);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007408
Amaury Denoyelle6e56a9e2022-10-17 12:04:49 +02007409 drop_silent:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007410 TRACE_PROTO("RX pkt", QUIC_EV_CONN_LPKT, qc ? qc : NULL, pkt, NULL, qv);
7411 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc ? qc : NULL);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007412 return;
7413
7414 drop:
Frédéric Lécaillebdd64fd2023-05-24 11:10:19 +02007415 qc->cntrs.dropped_pkt++;
Frédéric Lécaille464281a2023-05-24 10:24:42 +02007416 TRACE_PROTO("packet drop", QUIC_EV_CONN_LPKT, qc, pkt, NULL, qv);
7417 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007418}
7419
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007420/* This function builds into a buffer at <pos> position a QUIC long packet header,
7421 * <end> being one byte past the end of this buffer.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007422 * Return 1 if enough room to build this header, 0 if not.
7423 */
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007424static int quic_build_packet_long_header(unsigned char **pos, const unsigned char *end,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007425 int type, size_t pn_len,
7426 struct quic_conn *qc, const struct quic_version *ver)
7427{
7428 int ret = 0;
7429
7430 TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
7431
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007432 if (end - *pos < sizeof ver->num + qc->dcid.len + qc->scid.len + 3) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007433 TRACE_DEVEL("not enough room", QUIC_EV_CONN_LPKT, qc);
7434 goto leave;
7435 }
7436
7437 type = quic_pkt_type(type, ver->num);
7438 /* #0 byte flags */
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007439 *(*pos)++ = QUIC_PACKET_FIXED_BIT | QUIC_PACKET_LONG_HEADER_BIT |
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007440 (type << QUIC_PACKET_TYPE_SHIFT) | (pn_len - 1);
7441 /* Version */
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007442 quic_write_uint32(pos, end, ver->num);
7443 *(*pos)++ = qc->dcid.len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007444 /* Destination connection ID */
7445 if (qc->dcid.len) {
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007446 memcpy(*pos, qc->dcid.data, qc->dcid.len);
7447 *pos += qc->dcid.len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007448 }
7449 /* Source connection ID */
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007450 *(*pos)++ = qc->scid.len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007451 if (qc->scid.len) {
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007452 memcpy(*pos, qc->scid.data, qc->scid.len);
7453 *pos += qc->scid.len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007454 }
7455
7456 ret = 1;
7457 leave:
7458 TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
7459 return ret;
7460}
7461
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007462/* This function builds into a buffer at <pos> position a QUIC short packet header,
7463 * <end> being one byte past the end of this buffer.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007464 * Return 1 if enough room to build this header, 0 if not.
7465 */
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007466static int quic_build_packet_short_header(unsigned char **pos, const unsigned char *end,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007467 size_t pn_len, struct quic_conn *qc,
7468 unsigned char tls_flags)
7469{
7470 int ret = 0;
Frédéric Lécailleece86e62023-03-07 11:53:43 +01007471 unsigned char spin_bit =
7472 (qc->flags & QUIC_FL_CONN_SPIN_BIT) ? QUIC_PACKET_SPIN_BIT : 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007473
7474 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7475
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007476 if (end - *pos < 1 + qc->dcid.len) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007477 TRACE_DEVEL("not enough room", QUIC_EV_CONN_LPKT, qc);
7478 goto leave;
7479 }
7480
7481 /* #0 byte flags */
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007482 *(*pos)++ = QUIC_PACKET_FIXED_BIT | spin_bit |
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007483 ((tls_flags & QUIC_FL_TLS_KP_BIT_SET) ? QUIC_PACKET_KEY_PHASE_BIT : 0) | (pn_len - 1);
7484 /* Destination connection ID */
7485 if (qc->dcid.len) {
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007486 memcpy(*pos, qc->dcid.data, qc->dcid.len);
7487 *pos += qc->dcid.len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007488 }
7489
7490 ret = 1;
7491 leave:
7492 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
7493 return ret;
7494}
7495
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007496/* Apply QUIC header protection to the packet with <pos> as first byte address,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007497 * <pn> as address of the Packet number field, <pnlen> being this field length
7498 * with <aead> as AEAD cipher and <key> as secret key.
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02007499 *
7500 * TODO no error is expected as encryption is done in place but encryption
7501 * manual is unclear. <fail> will be set to true if an error is detected.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007502 */
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02007503void quic_apply_header_protection(struct quic_conn *qc, unsigned char *pos,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007504 unsigned char *pn, size_t pnlen,
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02007505 struct quic_tls_ctx *tls_ctx, int *fail)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007506
7507{
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02007508 int i;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007509 /* We need an IV of at least 5 bytes: one byte for bytes #0
7510 * and at most 4 bytes for the packet number
7511 */
7512 unsigned char mask[5] = {0};
7513 EVP_CIPHER_CTX *aes_ctx = tls_ctx->tx.hp_ctx;
7514
7515 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7516
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02007517 *fail = 0;
7518
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007519 if (!quic_tls_aes_encrypt(mask, pn + QUIC_PACKET_PN_MAXLEN, sizeof mask, aes_ctx)) {
7520 TRACE_ERROR("could not apply header protection", QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02007521 *fail = 1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007522 goto out;
7523 }
7524
Frédéric Lécaille3adb9e82023-04-24 14:54:48 +02007525 *pos ^= mask[0] & (*pos & QUIC_PACKET_LONG_HEADER_BIT ? 0xf : 0x1f);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007526 for (i = 0; i < pnlen; i++)
7527 pn[i] ^= mask[i + 1];
7528
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007529 out:
7530 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007531}
7532
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007533/* Prepare into <outlist> as most as possible ack-eliciting frame from their
7534 * <inlist> prebuilt frames for <qel> encryption level to be encoded in a buffer
7535 * with <room> as available room, and <*len> the packet Length field initialized
7536 * with the number of bytes already present in this buffer which must be taken
7537 * into an account for the Length packet field value. <headlen> is the number of
7538 * bytes already present in this packet before building frames.
7539 *
7540 * Update consequently <*len> to reflect the size of these frames built
7541 * by this function. Also attach these frames to <l> frame list.
7542 * Return 1 if at least one ack-eleciting frame could be built, 0 if not.
7543 */
7544static inline int qc_build_frms(struct list *outlist, struct list *inlist,
7545 size_t room, size_t *len, size_t headlen,
7546 struct quic_enc_level *qel,
7547 struct quic_conn *qc)
7548{
7549 int ret;
7550 struct quic_frame *cf, *cfbak;
7551
7552 TRACE_ENTER(QUIC_EV_CONN_BCFRMS, qc);
7553
7554 ret = 0;
7555 if (*len > room)
7556 goto leave;
7557
7558 /* If we are not probing we must take into an account the congestion
7559 * control window.
7560 */
7561 if (!qel->pktns->tx.pto_probe) {
7562 size_t remain = quic_path_prep_data(qc->path);
7563
7564 if (headlen > remain)
7565 goto leave;
7566
7567 room = QUIC_MIN(room, remain - headlen);
7568 }
7569
Frédéric Lécaille8f991942023-03-24 15:14:45 +01007570 TRACE_PROTO("TX frms build (headlen)",
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007571 QUIC_EV_CONN_BCFRMS, qc, &headlen);
7572
7573 /* NOTE: switch/case block inside a loop, a successful status must be
7574 * returned by this function only if at least one frame could be built
7575 * in the switch/case block.
7576 */
7577 list_for_each_entry_safe(cf, cfbak, inlist, list) {
7578 /* header length, data length, frame length. */
7579 size_t hlen, dlen, dlen_sz, avail_room, flen;
7580
7581 if (!room)
7582 break;
7583
7584 switch (cf->type) {
7585 case QUIC_FT_CRYPTO:
7586 TRACE_DEVEL(" New CRYPTO frame build (room, len)",
7587 QUIC_EV_CONN_BCFRMS, qc, &room, len);
7588 /* Compute the length of this CRYPTO frame header */
7589 hlen = 1 + quic_int_getsize(cf->crypto.offset);
7590 /* Compute the data length of this CRyPTO frame. */
7591 dlen = max_stream_data_size(room, *len + hlen, cf->crypto.len);
7592 TRACE_DEVEL(" CRYPTO data length (hlen, crypto.len, dlen)",
7593 QUIC_EV_CONN_BCFRMS, qc, &hlen, &cf->crypto.len, &dlen);
7594 if (!dlen)
7595 continue;
7596
7597 /* CRYPTO frame length. */
7598 flen = hlen + quic_int_getsize(dlen) + dlen;
7599 TRACE_DEVEL(" CRYPTO frame length (flen)",
7600 QUIC_EV_CONN_BCFRMS, qc, &flen);
7601 /* Add the CRYPTO data length and its encoded length to the packet
7602 * length and the length of this length.
7603 */
7604 *len += flen;
7605 room -= flen;
7606 if (dlen == cf->crypto.len) {
7607 /* <cf> CRYPTO data have been consumed. */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007608 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007609 LIST_APPEND(outlist, &cf->list);
7610 }
7611 else {
7612 struct quic_frame *new_cf;
7613
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01007614 new_cf = qc_frm_alloc(QUIC_FT_CRYPTO);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007615 if (!new_cf) {
7616 TRACE_ERROR("No memory for new crypto frame", QUIC_EV_CONN_BCFRMS, qc);
7617 continue;
7618 }
7619
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007620 new_cf->crypto.len = dlen;
7621 new_cf->crypto.offset = cf->crypto.offset;
7622 new_cf->crypto.qel = qel;
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05007623 TRACE_DEVEL("split frame", QUIC_EV_CONN_PRSAFRM, qc, new_cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007624 if (cf->origin) {
7625 TRACE_DEVEL("duplicated frame", QUIC_EV_CONN_PRSAFRM, qc);
7626 /* This <cf> frame was duplicated */
7627 LIST_APPEND(&cf->origin->reflist, &new_cf->ref);
7628 new_cf->origin = cf->origin;
Frédéric Lécailledd419462023-01-26 15:07:39 +01007629 /* Detach the remaining CRYPTO frame from its original frame */
7630 LIST_DEL_INIT(&cf->ref);
7631 cf->origin = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007632 }
7633 LIST_APPEND(outlist, &new_cf->list);
7634 /* Consume <dlen> bytes of the current frame. */
7635 cf->crypto.len -= dlen;
7636 cf->crypto.offset += dlen;
7637 }
7638 break;
7639
7640 case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
Amaury Denoyellec8a0efb2023-02-22 10:44:27 +01007641 if (cf->stream.dup) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007642 struct eb64_node *node = NULL;
7643 struct qc_stream_desc *stream_desc = NULL;
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02007644 struct qf_stream *strm_frm = &cf->stream;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007645
7646 /* As this frame has been already lost, ensure the stream is always
7647 * available or the range of this frame is not consumed before
7648 * resending it.
7649 */
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02007650 node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007651 if (!node) {
7652 TRACE_DEVEL("released stream", QUIC_EV_CONN_PRSAFRM, qc, cf);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007653 qc_frm_free(&cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007654 continue;
7655 }
7656
7657 stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02007658 if (strm_frm->offset.key + strm_frm->len <= stream_desc->ack_offset) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007659 TRACE_DEVEL("ignored frame frame in already acked range",
7660 QUIC_EV_CONN_PRSAFRM, qc, cf);
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007661 qc_frm_free(&cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007662 continue;
7663 }
Amaury Denoyelled5f03cd2023-04-24 15:32:23 +02007664 else if (strm_frm->offset.key < stream_desc->ack_offset) {
7665 uint64_t diff = stream_desc->ack_offset - strm_frm->offset.key;
Frédéric Lécailleca079792023-03-17 08:56:50 +01007666
Frédéric Lécaillec425e032023-03-20 14:32:59 +01007667 qc_stream_frm_mv_fwd(cf, diff);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007668 TRACE_DEVEL("updated partially acked frame",
7669 QUIC_EV_CONN_PRSAFRM, qc, cf);
7670 }
7671 }
7672 /* Note that these frames are accepted in short packets only without
7673 * "Length" packet field. Here, <*len> is used only to compute the
7674 * sum of the lengths of the already built frames for this packet.
7675 *
7676 * Compute the length of this STREAM frame "header" made a all the field
7677 * excepting the variable ones. Note that +1 is for the type of this frame.
7678 */
7679 hlen = 1 + quic_int_getsize(cf->stream.id) +
7680 ((cf->type & QUIC_STREAM_FRAME_TYPE_OFF_BIT) ? quic_int_getsize(cf->stream.offset.key) : 0);
7681 /* Compute the data length of this STREAM frame. */
7682 avail_room = room - hlen - *len;
7683 if ((ssize_t)avail_room <= 0)
7684 continue;
7685
7686 TRACE_DEVEL(" New STREAM frame build (room, len)",
7687 QUIC_EV_CONN_BCFRMS, qc, &room, len);
Amaury Denoyellef2f08f82023-02-03 18:39:06 +01007688
7689 /* hlen contains STREAM id and offset. Ensure there is
7690 * enough room for length field.
7691 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007692 if (cf->type & QUIC_STREAM_FRAME_TYPE_LEN_BIT) {
Amaury Denoyellef2f08f82023-02-03 18:39:06 +01007693 dlen = QUIC_MIN((uint64_t)max_available_room(avail_room, &dlen_sz),
7694 cf->stream.len);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007695 dlen_sz = quic_int_getsize(dlen);
7696 flen = hlen + dlen_sz + dlen;
7697 }
7698 else {
7699 dlen = QUIC_MIN((uint64_t)avail_room, cf->stream.len);
7700 flen = hlen + dlen;
7701 }
Amaury Denoyellef2f08f82023-02-03 18:39:06 +01007702
7703 if (cf->stream.len && !dlen) {
7704 /* Only a small gap is left on buffer, not
7705 * enough to encode the STREAM data length.
7706 */
7707 continue;
7708 }
7709
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007710 TRACE_DEVEL(" STREAM data length (hlen, stream.len, dlen)",
7711 QUIC_EV_CONN_BCFRMS, qc, &hlen, &cf->stream.len, &dlen);
7712 TRACE_DEVEL(" STREAM frame length (flen)",
7713 QUIC_EV_CONN_BCFRMS, qc, &flen);
7714 /* Add the STREAM data length and its encoded length to the packet
7715 * length and the length of this length.
7716 */
7717 *len += flen;
7718 room -= flen;
7719 if (dlen == cf->stream.len) {
7720 /* <cf> STREAM data have been consumed. */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007721 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007722 LIST_APPEND(outlist, &cf->list);
7723
7724 /* Do not notify MUX on retransmission. */
7725 if (qc->flags & QUIC_FL_CONN_TX_MUX_CONTEXT) {
7726 qcc_streams_sent_done(cf->stream.stream->ctx,
7727 cf->stream.len,
7728 cf->stream.offset.key);
7729 }
7730 }
7731 else {
7732 struct quic_frame *new_cf;
7733 struct buffer cf_buf;
7734
Amaury Denoyelle40c24f12023-01-27 17:47:49 +01007735 new_cf = qc_frm_alloc(cf->type);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007736 if (!new_cf) {
7737 TRACE_ERROR("No memory for new STREAM frame", QUIC_EV_CONN_BCFRMS, qc);
7738 continue;
7739 }
7740
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007741 new_cf->stream.stream = cf->stream.stream;
7742 new_cf->stream.buf = cf->stream.buf;
7743 new_cf->stream.id = cf->stream.id;
Amaury Denoyelle1dac0182023-02-02 16:45:07 +01007744 new_cf->stream.offset = cf->stream.offset;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007745 new_cf->stream.len = dlen;
7746 new_cf->type |= QUIC_STREAM_FRAME_TYPE_LEN_BIT;
7747 /* FIN bit reset */
7748 new_cf->type &= ~QUIC_STREAM_FRAME_TYPE_FIN_BIT;
7749 new_cf->stream.data = cf->stream.data;
Amaury Denoyellec8a0efb2023-02-22 10:44:27 +01007750 new_cf->stream.dup = cf->stream.dup;
Ilya Shipitsin4a689da2022-10-29 09:34:32 +05007751 TRACE_DEVEL("split frame", QUIC_EV_CONN_PRSAFRM, qc, new_cf);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007752 if (cf->origin) {
7753 TRACE_DEVEL("duplicated frame", QUIC_EV_CONN_PRSAFRM, qc);
7754 /* This <cf> frame was duplicated */
7755 LIST_APPEND(&cf->origin->reflist, &new_cf->ref);
7756 new_cf->origin = cf->origin;
Frédéric Lécailledd419462023-01-26 15:07:39 +01007757 /* Detach this STREAM frame from its origin */
7758 LIST_DEL_INIT(&cf->ref);
7759 cf->origin = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007760 }
7761 LIST_APPEND(outlist, &new_cf->list);
7762 cf->type |= QUIC_STREAM_FRAME_TYPE_OFF_BIT;
7763 /* Consume <dlen> bytes of the current frame. */
7764 cf_buf = b_make(b_orig(cf->stream.buf),
7765 b_size(cf->stream.buf),
7766 (char *)cf->stream.data - b_orig(cf->stream.buf), 0);
7767 cf->stream.len -= dlen;
7768 cf->stream.offset.key += dlen;
7769 cf->stream.data = (unsigned char *)b_peek(&cf_buf, dlen);
7770
7771 /* Do not notify MUX on retransmission. */
7772 if (qc->flags & QUIC_FL_CONN_TX_MUX_CONTEXT) {
7773 qcc_streams_sent_done(new_cf->stream.stream->ctx,
7774 new_cf->stream.len,
7775 new_cf->stream.offset.key);
7776 }
7777 }
7778
7779 /* TODO the MUX is notified about the frame sending via
7780 * previous qcc_streams_sent_done call. However, the
7781 * sending can fail later, for example if the sendto
7782 * system call returns an error. As the MUX has been
7783 * notified, the transport layer is responsible to
7784 * bufferize and resent the announced data later.
7785 */
7786
7787 break;
7788
7789 default:
7790 flen = qc_frm_len(cf);
7791 BUG_ON(!flen);
7792 if (flen > room)
7793 continue;
7794
7795 *len += flen;
7796 room -= flen;
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01007797 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007798 LIST_APPEND(outlist, &cf->list);
7799 break;
7800 }
7801
7802 /* Successful status as soon as a frame could be built */
7803 ret = 1;
7804 }
7805
7806 leave:
7807 TRACE_LEAVE(QUIC_EV_CONN_BCFRMS, qc);
7808 return ret;
7809}
7810
7811/* Generate a CONNECTION_CLOSE frame for <qc> on <qel> encryption level. <out>
7812 * is used as return parameter and should be zero'ed by the caller.
7813 */
7814static void qc_build_cc_frm(struct quic_conn *qc, struct quic_enc_level *qel,
7815 struct quic_frame *out)
7816{
7817 /* TODO improve CONNECTION_CLOSE on Initial/Handshake encryption levels
7818 *
7819 * A CONNECTION_CLOSE frame should be sent in several packets with
7820 * different encryption levels depending on the client context. This is
7821 * to ensure that the client can decrypt it. See RFC 9000 10.2.3 for
7822 * more details on how to implement it.
7823 */
7824 TRACE_ENTER(QUIC_EV_CONN_BFRM, qc);
7825
7826
7827 if (qc->err.app) {
7828 if (unlikely(qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] ||
7829 qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE])) {
7830 /* RFC 9000 10.2.3. Immediate Close during the Handshake
7831 *
7832 * Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake
7833 * packet could expose application state or be used to alter application
7834 * state. A CONNECTION_CLOSE of type 0x1d MUST be replaced by a
7835 * CONNECTION_CLOSE of type 0x1c when sending the frame in Initial or
7836 * Handshake packets. Otherwise, information about the application
7837 * state might be revealed. Endpoints MUST clear the value of the
7838 * Reason Phrase field and SHOULD use the APPLICATION_ERROR code when
7839 * converting to a CONNECTION_CLOSE of type 0x1c.
7840 */
7841 out->type = QUIC_FT_CONNECTION_CLOSE;
7842 out->connection_close.error_code = QC_ERR_APPLICATION_ERROR;
7843 out->connection_close.reason_phrase_len = 0;
7844 }
7845 else {
7846 out->type = QUIC_FT_CONNECTION_CLOSE_APP;
7847 out->connection_close.error_code = qc->err.code;
7848 }
7849 }
7850 else {
7851 out->type = QUIC_FT_CONNECTION_CLOSE;
7852 out->connection_close.error_code = qc->err.code;
7853 }
7854 TRACE_LEAVE(QUIC_EV_CONN_BFRM, qc);
7855
7856}
7857
7858/* This function builds a clear packet from <pkt> information (its type)
7859 * into a buffer with <pos> as position pointer and <qel> as QUIC TLS encryption
7860 * level for <conn> QUIC connection and <qel> as QUIC TLS encryption level,
7861 * filling the buffer with as much frames as possible from <frms> list of
7862 * prebuilt frames.
7863 * The trailing QUIC_TLS_TAG_LEN bytes of this packet are not built. But they are
7864 * reserved so that to ensure there is enough room to build this AEAD TAG after
7865 * having returned from this function.
7866 * This function also updates the value of <buf_pn> pointer to point to the packet
7867 * number field in this packet. <pn_len> will also have the packet number
7868 * length as value.
7869 *
7870 * Return 1 if succeeded (enough room to buile this packet), O if not.
7871 */
7872static int qc_do_build_pkt(unsigned char *pos, const unsigned char *end,
7873 size_t dglen, struct quic_tx_packet *pkt,
7874 int64_t pn, size_t *pn_len, unsigned char **buf_pn,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007875 int must_ack, int padding, int cc, int probe,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007876 struct quic_enc_level *qel, struct quic_conn *qc,
7877 const struct quic_version *ver, struct list *frms)
7878{
7879 unsigned char *beg, *payload;
7880 size_t len, len_sz, len_frms, padding_len;
7881 struct quic_frame frm = { .type = QUIC_FT_CRYPTO, };
7882 struct quic_frame ack_frm = { .type = QUIC_FT_ACK, };
7883 struct quic_frame cc_frm = { };
7884 size_t ack_frm_len, head_len;
7885 int64_t rx_largest_acked_pn;
7886 int add_ping_frm;
7887 struct list frm_list = LIST_HEAD_INIT(frm_list);
7888 struct quic_frame *cf;
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007889 int ret = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007890
7891 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
7892
7893 /* Length field value with CRYPTO frames if present. */
7894 len_frms = 0;
7895 beg = pos;
7896 /* When not probing, and no immediate close is required, reduce the size of this
7897 * buffer to respect the congestion controller window.
7898 * This size will be limited if we have ack-eliciting frames to send from <frms>.
7899 */
7900 if (!probe && !LIST_ISEMPTY(frms) && !cc) {
7901 size_t path_room;
7902
7903 path_room = quic_path_prep_data(qc->path);
7904 if (end - beg > path_room)
7905 end = beg + path_room;
7906 }
7907
7908 /* Ensure there is enough room for the TLS encryption tag and a zero token
7909 * length field if any.
7910 */
7911 if (end - pos < QUIC_TLS_TAG_LEN +
7912 (pkt->type == QUIC_PACKET_TYPE_INITIAL ? 1 : 0))
7913 goto no_room;
7914
7915 end -= QUIC_TLS_TAG_LEN;
7916 rx_largest_acked_pn = qel->pktns->rx.largest_acked_pn;
7917 /* packet number length */
7918 *pn_len = quic_packet_number_length(pn, rx_largest_acked_pn);
7919 /* Build the header */
7920 if ((pkt->type == QUIC_PACKET_TYPE_SHORT &&
7921 !quic_build_packet_short_header(&pos, end, *pn_len, qc, qel->tls_ctx.flags)) ||
7922 (pkt->type != QUIC_PACKET_TYPE_SHORT &&
7923 !quic_build_packet_long_header(&pos, end, pkt->type, *pn_len, qc, ver)))
7924 goto no_room;
7925
7926 /* Encode the token length (0) for an Initial packet. */
Frédéric Lécaille45662ef2023-04-18 14:42:40 +02007927 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
7928 if (end <= pos)
7929 goto no_room;
7930
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007931 *pos++ = 0;
Frédéric Lécaille45662ef2023-04-18 14:42:40 +02007932 }
7933
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007934 head_len = pos - beg;
7935 /* Build an ACK frame if required. */
7936 ack_frm_len = 0;
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02007937 /* Do not ack and probe at the same time. */
7938 if ((must_ack || (qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED)) && !qel->pktns->tx.pto_probe) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007939 struct quic_arngs *arngs = &qel->pktns->rx.arngs;
7940 BUG_ON(eb_is_empty(&qel->pktns->rx.arngs.root));
7941 ack_frm.tx_ack.arngs = arngs;
7942 if (qel->pktns->flags & QUIC_FL_PKTNS_NEW_LARGEST_PN) {
7943 qel->pktns->tx.ack_delay =
7944 quic_compute_ack_delay_us(qel->pktns->rx.largest_time_received, qc);
7945 qel->pktns->flags &= ~QUIC_FL_PKTNS_NEW_LARGEST_PN;
7946 }
7947 ack_frm.tx_ack.ack_delay = qel->pktns->tx.ack_delay;
7948 /* XXX BE CAREFUL XXX : here we reserved at least one byte for the
7949 * smallest frame (PING) and <*pn_len> more for the packet number. Note
7950 * that from here, we do not know if we will have to send a PING frame.
7951 * This will be decided after having computed the ack-eliciting frames
7952 * to be added to this packet.
7953 */
Frédéric Lécaille9d68c6a2023-04-12 20:49:29 +02007954 if (end - pos <= 1 + *pn_len)
7955 goto no_room;
7956
Frédéric Lécaille4b2627b2023-04-17 13:42:42 +02007957 ack_frm_len = qc_frm_len(&ack_frm);
7958 if (ack_frm_len > end - 1 - *pn_len - pos)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007959 goto no_room;
7960 }
7961
7962 /* Length field value without the ack-eliciting frames. */
7963 len = ack_frm_len + *pn_len;
7964 len_frms = 0;
7965 if (!cc && !LIST_ISEMPTY(frms)) {
7966 ssize_t room = end - pos;
7967
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02007968 TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, frms);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007969 /* Initialize the length of the frames built below to <len>.
7970 * If any frame could be successfully built by qc_build_frms(),
7971 * we will have len_frms > len.
7972 */
7973 len_frms = len;
7974 if (!qc_build_frms(&frm_list, frms,
7975 end - pos, &len_frms, pos - beg, qel, qc)) {
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02007976 TRACE_PROTO("Not enough room", QUIC_EV_CONN_TXPKT,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02007977 qc, NULL, NULL, &room);
7978 if (!ack_frm_len && !qel->pktns->tx.pto_probe)
7979 goto no_room;
7980 }
7981 }
7982
7983 /* Length (of the remaining data). Must not fail because, the buffer size
7984 * has been checked above. Note that we have reserved QUIC_TLS_TAG_LEN bytes
7985 * for the encryption tag. It must be taken into an account for the length
7986 * of this packet.
7987 */
7988 if (len_frms)
7989 len = len_frms + QUIC_TLS_TAG_LEN;
7990 else
7991 len += QUIC_TLS_TAG_LEN;
7992 /* CONNECTION_CLOSE frame */
7993 if (cc) {
7994 qc_build_cc_frm(qc, qel, &cc_frm);
7995 len += qc_frm_len(&cc_frm);
7996 }
7997 add_ping_frm = 0;
7998 padding_len = 0;
7999 len_sz = quic_int_getsize(len);
8000 /* Add this packet size to <dglen> */
8001 dglen += head_len + len_sz + len;
Frédéric Lécailleec937212023-03-03 17:34:41 +01008002 /* Note that <padding> is true only when building an Handshake packet
8003 * coalesced to an Initial packet.
8004 */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008005 if (padding && dglen < QUIC_INITIAL_PACKET_MINLEN) {
8006 /* This is a maximum padding size */
8007 padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen;
8008 /* The length field value is of this packet is <len> + <padding_len>
8009 * the size of which may be greater than the initial computed size
8010 * <len_sz>. So, let's deduce the difference between these to packet
8011 * sizes from <padding_len>.
8012 */
8013 padding_len -= quic_int_getsize(len + padding_len) - len_sz;
8014 len += padding_len;
8015 }
Frédéric Lécaille5faf5772023-02-16 17:30:53 +01008016 else if (len_frms && len_frms < QUIC_PACKET_PN_MAXLEN) {
8017 len += padding_len = QUIC_PACKET_PN_MAXLEN - len_frms;
8018 }
8019 else if (LIST_ISEMPTY(&frm_list)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008020 if (qel->pktns->tx.pto_probe) {
8021 /* If we cannot send a frame, we send a PING frame. */
8022 add_ping_frm = 1;
8023 len += 1;
Frédéric Lécailleec937212023-03-03 17:34:41 +01008024 dglen += 1;
8025 /* Note that only we are in the case where this Initial packet
8026 * is not coalesced to an Handshake packet. We must directly
8027 * pad the datragram.
8028 */
Frédéric Lécaille9c317b12023-03-28 15:39:11 +02008029 if (pkt->type == QUIC_PACKET_TYPE_INITIAL) {
8030 if (dglen < QUIC_INITIAL_PACKET_MINLEN) {
8031 padding_len = QUIC_INITIAL_PACKET_MINLEN - dglen;
8032 padding_len -= quic_int_getsize(len + padding_len) - len_sz;
8033 len += padding_len;
8034 }
8035 }
8036 else {
8037 /* Note that +1 is for the PING frame */
8038 if (*pn_len + 1 < QUIC_PACKET_PN_MAXLEN)
8039 len += padding_len = QUIC_PACKET_PN_MAXLEN - *pn_len - 1;
Frédéric Lécailleec937212023-03-03 17:34:41 +01008040 }
8041 }
8042 else {
8043 /* If there is no frame at all to follow, add at least a PADDING frame. */
8044 if (!ack_frm_len && !cc)
8045 len += padding_len = QUIC_PACKET_PN_MAXLEN - *pn_len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008046 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008047 }
8048
8049 if (pkt->type != QUIC_PACKET_TYPE_SHORT && !quic_enc_int(&pos, end, len))
8050 goto no_room;
8051
8052 /* Packet number field address. */
8053 *buf_pn = pos;
8054
8055 /* Packet number encoding. */
8056 if (!quic_packet_number_encode(&pos, end, pn, *pn_len))
8057 goto no_room;
8058
8059 /* payload building (ack-eliciting or not frames) */
8060 payload = pos;
8061 if (ack_frm_len) {
8062 if (!qc_build_frm(&pos, end, &ack_frm, pkt, qc))
8063 goto no_room;
8064
8065 pkt->largest_acked_pn = quic_pktns_get_largest_acked_pn(qel->pktns);
8066 pkt->flags |= QUIC_FL_TX_PACKET_ACK;
8067 }
8068
8069 /* Ack-eliciting frames */
8070 if (!LIST_ISEMPTY(&frm_list)) {
8071 struct quic_frame *tmp_cf;
8072 list_for_each_entry_safe(cf, tmp_cf, &frm_list, list) {
8073 if (!qc_build_frm(&pos, end, cf, pkt, qc)) {
8074 ssize_t room = end - pos;
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02008075 TRACE_PROTO("Not enough room", QUIC_EV_CONN_TXPKT,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008076 qc, NULL, NULL, &room);
8077 /* Note that <cf> was added from <frms> to <frm_list> list by
8078 * qc_build_frms().
8079 */
Amaury Denoyelle57b3eaa2023-02-02 16:12:09 +01008080 LIST_DEL_INIT(&cf->list);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008081 LIST_INSERT(frms, &cf->list);
8082 continue;
8083 }
8084
8085 quic_tx_packet_refinc(pkt);
8086 cf->pkt = pkt;
8087 }
8088 }
8089
8090 /* Build a PING frame if needed. */
8091 if (add_ping_frm) {
8092 frm.type = QUIC_FT_PING;
8093 if (!qc_build_frm(&pos, end, &frm, pkt, qc))
8094 goto no_room;
8095 }
8096
8097 /* Build a CONNECTION_CLOSE frame if needed. */
8098 if (cc) {
8099 if (!qc_build_frm(&pos, end, &cc_frm, pkt, qc))
8100 goto no_room;
8101
8102 pkt->flags |= QUIC_FL_TX_PACKET_CC;
8103 }
8104
8105 /* Build a PADDING frame if needed. */
8106 if (padding_len) {
8107 frm.type = QUIC_FT_PADDING;
8108 frm.padding.len = padding_len;
8109 if (!qc_build_frm(&pos, end, &frm, pkt, qc))
8110 goto no_room;
8111 }
8112
8113 if (pos == payload) {
8114 /* No payload was built because of congestion control */
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02008115 TRACE_PROTO("limited by congestion control", QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008116 goto no_room;
8117 }
8118
8119 /* If this packet is ack-eliciting and we are probing let's
8120 * decrement the PTO probe counter.
8121 */
Frédéric Lécaille0e7f9da2023-07-20 15:45:41 +02008122 if ((pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) &&
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008123 qel->pktns->tx.pto_probe)
8124 qel->pktns->tx.pto_probe--;
8125
8126 pkt->len = pos - beg;
8127 LIST_SPLICE(&pkt->frms, &frm_list);
8128
8129 ret = 1;
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02008130 TRACE_PROTO("Packet ack-eliciting frames", QUIC_EV_CONN_TXPKT, qc, pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008131 leave:
8132 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
8133 return ret;
8134
8135 no_room:
8136 /* Replace the pre-built frames which could not be add to this packet */
8137 LIST_SPLICE(frms, &frm_list);
Frédéric Lécaillee95e00e2023-04-24 10:59:33 +02008138 TRACE_PROTO("Remaining ack-eliciting frames", QUIC_EV_CONN_FRMLIST, qc, frms);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008139 goto leave;
8140}
8141
8142static inline void quic_tx_packet_init(struct quic_tx_packet *pkt, int type)
8143{
8144 pkt->type = type;
8145 pkt->len = 0;
8146 pkt->in_flight_len = 0;
8147 pkt->pn_node.key = (uint64_t)-1;
8148 LIST_INIT(&pkt->frms);
8149 pkt->time_sent = TICK_ETERNITY;
8150 pkt->next = NULL;
Frédéric Lécaille814645f2022-11-18 18:15:28 +01008151 pkt->prev = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008152 pkt->largest_acked_pn = -1;
8153 pkt->flags = 0;
8154 pkt->refcnt = 0;
8155}
8156
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008157/* Build a packet into a buffer at <pos> position, <end> pointing to one byte past
8158 * the end of this buffer, with <pkt_type> as packet type for <qc> QUIC connection
8159 * at <qel> encryption level with <frms> list of prebuilt frames.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008160 *
8161 * Return -2 if the packet could not be allocated or encrypted for any reason,
8162 * -1 if there was not enough room to build a packet.
8163 * XXX NOTE XXX
8164 * If you provide provide qc_build_pkt() with a big enough buffer to build a packet as big as
8165 * possible (to fill an MTU), the unique reason why this function may fail is the congestion
8166 * control window limitation.
8167 */
8168static struct quic_tx_packet *qc_build_pkt(unsigned char **pos,
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008169 const unsigned char *end,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008170 struct quic_enc_level *qel,
8171 struct quic_tls_ctx *tls_ctx, struct list *frms,
8172 struct quic_conn *qc, const struct quic_version *ver,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02008173 size_t dglen, int pkt_type, int must_ack,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008174 int padding, int probe, int cc, int *err)
8175{
8176 struct quic_tx_packet *ret_pkt = NULL;
8177 /* The pointer to the packet number field. */
8178 unsigned char *buf_pn;
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008179 unsigned char *first_byte, *last_byte, *payload;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008180 int64_t pn;
8181 size_t pn_len, payload_len, aad_len;
8182 struct quic_tx_packet *pkt;
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02008183 int encrypt_failure = 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008184
Frédéric Lécaille8f991942023-03-24 15:14:45 +01008185 TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
8186 TRACE_PROTO("TX pkt build", QUIC_EV_CONN_TXPKT, qc, NULL, qel);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008187 *err = 0;
8188 pkt = pool_alloc(pool_head_quic_tx_packet);
8189 if (!pkt) {
8190 TRACE_DEVEL("Not enough memory for a new packet", QUIC_EV_CONN_TXPKT, qc);
8191 *err = -2;
8192 goto err;
8193 }
8194
8195 quic_tx_packet_init(pkt, pkt_type);
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008196 first_byte = *pos;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008197 pn_len = 0;
8198 buf_pn = NULL;
8199
8200 pn = qel->pktns->tx.next_pn + 1;
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008201 if (!qc_do_build_pkt(*pos, end, dglen, pkt, pn, &pn_len, &buf_pn,
Frédéric Lécaille45bf1a82023-04-12 18:51:49 +02008202 must_ack, padding, cc, probe, qel, qc, ver, frms)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008203 // trace already emitted by function above
8204 *err = -1;
8205 goto err;
8206 }
8207
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008208 last_byte = first_byte + pkt->len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008209 payload = buf_pn + pn_len;
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008210 payload_len = last_byte - payload;
8211 aad_len = payload - first_byte;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008212
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02008213 quic_packet_encrypt(payload, payload_len, first_byte, aad_len, pn, tls_ctx, qc, &encrypt_failure);
8214 if (encrypt_failure) {
Amaury Denoyelle7385ff32023-04-19 15:56:30 +02008215 /* TODO Unrecoverable failure, unencrypted data should be returned to the caller. */
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02008216 WARN_ON("quic_packet_encrypt failure");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008217 *err = -2;
8218 goto err;
8219 }
8220
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008221 last_byte += QUIC_TLS_TAG_LEN;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008222 pkt->len += QUIC_TLS_TAG_LEN;
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02008223 quic_apply_header_protection(qc, first_byte, buf_pn, pn_len, tls_ctx, &encrypt_failure);
8224 if (encrypt_failure) {
Amaury Denoyelle7385ff32023-04-19 15:56:30 +02008225 /* TODO Unrecoverable failure, unencrypted data should be returned to the caller. */
Amaury Denoyellef8fbb0b2023-05-16 18:23:37 +02008226 WARN_ON("quic_apply_header_protection failure");
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008227 *err = -2;
8228 goto err;
8229 }
8230
8231 /* Consume a packet number */
8232 qel->pktns->tx.next_pn++;
8233 qc->tx.prep_bytes += pkt->len;
8234 if (qc->tx.prep_bytes >= 3 * qc->rx.bytes && !quic_peer_validated_addr(qc)) {
8235 qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
8236 TRACE_PROTO("anti-amplification limit reached", QUIC_EV_CONN_TXPKT, qc);
8237 }
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008238
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008239 /* Now that a correct packet is built, let us consume <*pos> buffer. */
Frédéric Lécaille1e0f8252023-04-24 15:02:34 +02008240 *pos = last_byte;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008241 /* Attach the built packet to its tree. */
8242 pkt->pn_node.key = pn;
8243 /* Set the packet in fligth length for in flight packet only. */
8244 if (pkt->flags & QUIC_FL_TX_PACKET_IN_FLIGHT) {
8245 pkt->in_flight_len = pkt->len;
8246 qc->path->prep_in_flight += pkt->len;
8247 }
Frédéric Lécailled7215712023-03-24 18:13:37 +01008248 /* Always reset this flag */
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008249 qc->flags &= ~QUIC_FL_CONN_IMMEDIATE_CLOSE;
8250 if (pkt->flags & QUIC_FL_TX_PACKET_ACK) {
8251 qel->pktns->flags &= ~QUIC_FL_PKTNS_ACK_REQUIRED;
8252 qel->pktns->rx.nb_aepkts_since_last_ack = 0;
Frédéric Lécailled7215712023-03-24 18:13:37 +01008253 qc->flags &= ~QUIC_FL_CONN_ACK_TIMER_FIRED;
8254 if (tick_isset(qc->ack_expire)) {
8255 qc->ack_expire = TICK_ETERNITY;
8256 qc->idle_timer_task->expire = qc->idle_expire;
8257 task_queue(qc->idle_timer_task);
Frédéric Lécaille495968e2023-04-03 17:42:05 +02008258 TRACE_PROTO("ack timer cancelled", QUIC_EV_CONN_IDLE_TIMER, qc);
Frédéric Lécailled7215712023-03-24 18:13:37 +01008259 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008260 }
8261
8262 pkt->pktns = qel->pktns;
8263
8264 ret_pkt = pkt;
8265 leave:
Frédéric Lécaille8f991942023-03-24 15:14:45 +01008266 TRACE_PROTO("TX pkt built", QUIC_EV_CONN_TXPKT, qc, ret_pkt);
8267 TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008268 return ret_pkt;
8269
8270 err:
8271 /* TODO: what about the frames which have been built
8272 * for this packet.
8273 */
8274 free_quic_tx_packet(qc, pkt);
8275 goto leave;
8276}
8277
8278
8279static void __quic_conn_init(void)
8280{
8281 ha_quic_meth = BIO_meth_new(0x666, "ha QUIC methods");
8282}
8283INITCALL0(STG_REGISTER, __quic_conn_init);
8284
8285static void __quic_conn_deinit(void)
8286{
8287 BIO_meth_free(ha_quic_meth);
8288}
8289REGISTER_POST_DEINIT(__quic_conn_deinit);
8290
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008291/* Handle a new <dgram> received. Parse each QUIC packets and copied their
8292 * content to a quic-conn instance. The datagram content can be released after
8293 * this function.
8294 *
8295 * If datagram has been received on a quic-conn owned FD, <from_qc> must be set
8296 * to the connection instance. <li> is the attached listener. The caller is
8297 * responsible to ensure that the first packet is destined to this connection
8298 * by comparing CIDs.
8299 *
8300 * If datagram has been received on a receiver FD, <from_qc> will be NULL. This
8301 * function will thus retrieve the connection from the CID tree or allocate a
8302 * new one if possible. <li> is the listener attached to the receiver.
8303 *
8304 * Returns 0 on success else non-zero. If an error happens, some packets from
8305 * the datagram may not have been parsed.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008306 */
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008307int quic_dgram_parse(struct quic_dgram *dgram, struct quic_conn *from_qc,
8308 struct listener *li)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008309{
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008310 struct quic_rx_packet *pkt;
8311 struct quic_conn *qc = NULL;
8312 unsigned char *pos, *end;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008313 struct list *tasklist_head = NULL;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008314
8315 TRACE_ENTER(QUIC_EV_CONN_LPKT);
8316
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008317 pos = dgram->buf;
8318 end = pos + dgram->len;
8319 do {
8320 /* TODO replace zalloc -> alloc. */
8321 pkt = pool_zalloc(pool_head_quic_rx_packet);
8322 if (!pkt) {
8323 TRACE_ERROR("RX packet allocation failed", QUIC_EV_CONN_LPKT);
8324 goto err;
8325 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008326
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008327 pkt->version = NULL;
8328 pkt->pn_offset = 0;
Amaury Denoyelle98289692022-10-19 15:37:44 +02008329
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008330 /* Set flag if pkt is the first one in dgram. */
8331 if (pos == dgram->buf)
8332 pkt->flags |= QUIC_FL_RX_PACKET_DGRAM_FIRST;
Amaury Denoyelle98289692022-10-19 15:37:44 +02008333
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008334 LIST_INIT(&pkt->qc_rx_pkt_list);
8335 pkt->time_received = now_ms;
8336 quic_rx_packet_refinc(pkt);
8337 if (quic_rx_pkt_parse(pkt, pos, end, dgram, li))
8338 goto next;
Amaury Denoyelle98289692022-10-19 15:37:44 +02008339
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008340 /* Search quic-conn instance for first packet of the datagram.
8341 * quic_rx_packet_parse() is responsible to discard packets
8342 * with different DCID as the first one in the same datagram.
8343 */
8344 if (!qc) {
Amaury Denoyellef16ec342023-04-13 17:42:34 +02008345 int new_tid = -1;
8346
8347 qc = from_qc ? from_qc : quic_rx_pkt_retrieve_conn(pkt, dgram, li, &new_tid);
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008348 /* qc is NULL if receiving a non Initial packet for an
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008349 * unknown connection or on connection affinity rebind.
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008350 */
8351 if (!qc) {
Amaury Denoyellef16ec342023-04-13 17:42:34 +02008352 if (new_tid >= 0) {
8353 MT_LIST_APPEND(&quic_dghdlrs[new_tid].dgrams,
8354 &dgram->handler_list);
8355 tasklet_wakeup(quic_dghdlrs[new_tid].task);
8356 goto out;
8357 }
8358
Amaury Denoyelle98289692022-10-19 15:37:44 +02008359 /* Skip the entire datagram. */
8360 pkt->len = end - pos;
8361 goto next;
8362 }
8363
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008364 dgram->qc = qc;
8365 }
Amaury Denoyelle98289692022-10-19 15:37:44 +02008366
Amaury Denoyelled6646dd2023-04-26 17:15:37 +02008367 if (qc->flags & QUIC_FL_CONN_AFFINITY_CHANGED)
8368 qc_finalize_affinity_rebind(qc);
8369
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008370 if (qc_rx_check_closing(qc, pkt)) {
8371 /* Skip the entire datagram. */
8372 pkt->len = end - pos;
8373 goto next;
8374 }
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008375
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01008376 /* Detect QUIC connection migration. */
Frédéric Lécaillef6769542023-01-12 10:36:26 +01008377 if (ipcmp(&qc->peer_addr, &dgram->saddr, 1)) {
Amaury Denoyelleeec0b3c2022-12-02 09:57:32 +01008378 if (qc_handle_conn_migration(qc, &dgram->saddr, &dgram->daddr)) {
8379 /* Skip the entire datagram. */
8380 TRACE_ERROR("error during connection migration, datagram dropped", QUIC_EV_CONN_LPKT, qc);
8381 pkt->len = end - pos;
8382 goto next;
8383 }
8384 }
8385
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008386 qc_rx_pkt_handle(qc, pkt, dgram, pos, &tasklist_head);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008387
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008388 next:
8389 pos += pkt->len;
8390 quic_rx_packet_refdec(pkt);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008391
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008392 /* Free rejected packets */
8393 if (!pkt->refcnt) {
8394 BUG_ON(LIST_INLIST(&pkt->qc_rx_pkt_list));
8395 pool_free(pool_head_quic_rx_packet, pkt);
8396 }
8397 } while (pos < end);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008398
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008399 /* Increasing the received bytes counter by the UDP datagram length
8400 * if this datagram could be associated to a connection.
8401 */
8402 if (dgram->qc)
8403 dgram->qc->rx.bytes += dgram->len;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008404
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008405 /* This must never happen. */
8406 BUG_ON(pos > end);
8407 BUG_ON(pos < end || pos > dgram->buf + dgram->len);
8408 /* Mark this datagram as consumed */
8409 HA_ATOMIC_STORE(&dgram->buf, NULL);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008410
Amaury Denoyellef16ec342023-04-13 17:42:34 +02008411 out:
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008412 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
8413 return 0;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008414
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008415 err:
Amaury Denoyellea65dd3a2023-04-19 14:26:16 +02008416 /* Mark this datagram as consumed as maybe at least some packets were parsed. */
8417 HA_ATOMIC_STORE(&dgram->buf, NULL);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008418 TRACE_LEAVE(QUIC_EV_CONN_LPKT);
Amaury Denoyelle8687b632022-09-27 14:22:09 +02008419 return -1;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008420}
8421
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008422/* Check if connection ID <dcid> of length <dcid_len> belongs to <qc> local
8423 * CIDs. This can be used to determine if a datagram is addressed to the right
8424 * connection instance.
8425 *
8426 * Returns a boolean value.
8427 */
8428int qc_check_dcid(struct quic_conn *qc, unsigned char *dcid, size_t dcid_len)
8429{
Amaury Denoyellee83f9372023-04-18 11:10:54 +02008430 const uchar idx = _quic_cid_tree_idx(dcid);
Amaury Denoyelle591e7982023-04-12 10:04:49 +02008431 struct quic_connection_id *conn_id;
Amaury Denoyellee83f9372023-04-18 11:10:54 +02008432 struct ebmb_node *node = NULL;
8433 struct quic_cid_tree *tree = &quic_cid_trees[idx];
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008434
Amaury Denoyellee83f9372023-04-18 11:10:54 +02008435 /* Test against our default CID or client ODCID. */
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008436 if ((qc->scid.len == dcid_len &&
8437 memcmp(qc->scid.data, dcid, dcid_len) == 0) ||
8438 (qc->odcid.len == dcid_len &&
Frédéric Lécaille07846cb2023-02-13 16:14:24 +01008439 memcmp(qc->odcid.data, dcid, dcid_len) == 0)) {
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008440 return 1;
8441 }
8442
Amaury Denoyellee83f9372023-04-18 11:10:54 +02008443 /* Test against our other CIDs. This can happen if the client has
8444 * decided to switch to a new one.
8445 *
8446 * TODO to avoid locking, loop through qc.cids as an alternative.
8447 *
8448 * TODO set it to our default CID to avoid this operation next time.
8449 */
8450 HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
8451 node = ebmb_lookup(&tree->root, dcid, dcid_len);
8452 HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
8453
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008454 if (node) {
Amaury Denoyelle591e7982023-04-12 10:04:49 +02008455 conn_id = ebmb_entry(node, struct quic_connection_id, node);
8456 if (qc == conn_id->qc)
Amaury Denoyelle7c9fdd92022-11-16 11:01:02 +01008457 return 1;
8458 }
8459
8460 return 0;
8461}
8462
Willy Tarreaudd9f9212023-05-07 07:07:44 +02008463/* Retrieve the DCID from a QUIC datagram or packet at <pos> position,
Frédéric Lécaille182934d2023-04-24 15:24:58 +02008464 * <end> being at one byte past the end of this datagram.
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008465 * Returns 1 if succeeded, 0 if not.
8466 */
Frédéric Lécaille182934d2023-04-24 15:24:58 +02008467int quic_get_dgram_dcid(unsigned char *pos, const unsigned char *end,
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008468 unsigned char **dcid, size_t *dcid_len)
8469{
8470 int ret = 0, long_header;
8471 size_t minlen, skip;
8472
8473 TRACE_ENTER(QUIC_EV_CONN_RXPKT);
8474
Frédéric Lécaille182934d2023-04-24 15:24:58 +02008475 if (!(*pos & QUIC_PACKET_FIXED_BIT)) {
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008476 TRACE_PROTO("fixed bit not set", QUIC_EV_CONN_RXPKT);
8477 goto err;
8478 }
8479
Frédéric Lécaille182934d2023-04-24 15:24:58 +02008480 long_header = *pos & QUIC_PACKET_LONG_HEADER_BIT;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008481 minlen = long_header ? QUIC_LONG_PACKET_MINLEN :
8482 QUIC_SHORT_PACKET_MINLEN + QUIC_HAP_CID_LEN + QUIC_TLS_TAG_LEN;
8483 skip = long_header ? QUIC_LONG_PACKET_DCID_OFF : QUIC_SHORT_PACKET_DCID_OFF;
Frédéric Lécaille182934d2023-04-24 15:24:58 +02008484 if (end - pos < minlen)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008485 goto err;
8486
Frédéric Lécaille182934d2023-04-24 15:24:58 +02008487 pos += skip;
8488 *dcid_len = long_header ? *pos++ : QUIC_HAP_CID_LEN;
8489 if (*dcid_len > QUIC_CID_MAXLEN || end - pos <= *dcid_len)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008490 goto err;
8491
Frédéric Lécaille182934d2023-04-24 15:24:58 +02008492 *dcid = pos;
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008493
8494 ret = 1;
8495 leave:
8496 TRACE_LEAVE(QUIC_EV_CONN_RXPKT);
8497 return ret;
8498
8499 err:
8500 TRACE_PROTO("wrong datagram", QUIC_EV_CONN_RXPKT);
8501 goto leave;
8502}
8503
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02008504/* Notify upper layer of a fatal error which forces to close the connection. */
8505void qc_notify_err(struct quic_conn *qc)
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008506{
8507 TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
8508
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02008509 if (qc->mux_state == QC_MUX_READY) {
8510 TRACE_STATE("error notified to mux", QUIC_EV_CONN_CLOSE, qc);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008511
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02008512 /* Mark socket as closed. */
8513 qc->conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
8514
8515 /* TODO quic-conn layer must stay active until MUX is released.
8516 * Thus, we have to wake up directly to ensure upper stream
8517 * layer will be notified of the error. If a proper separation
8518 * is made between MUX and quic-conn layer, wake up could be
8519 * conducted only with qc.subs.
8520 */
8521 tasklet_wakeup(qc->qcc->wait_event.tasklet);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008522 }
Amaury Denoyelleb2e31d32023-05-10 11:57:40 +02008523
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02008524 TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
8525}
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008526
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01008527/* Wake-up upper layer for sending if all conditions are met :
8528 * - room in congestion window or probe packet to sent
8529 * - socket FD ready to sent or listener socket used
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01008530 *
8531 * Returns 1 if upper layer has been woken up else 0.
8532 */
8533int qc_notify_send(struct quic_conn *qc)
8534{
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01008535 const struct quic_pktns *pktns = &qc->pktns[QUIC_TLS_PKTNS_01RTT];
8536
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01008537 if (qc->subs && qc->subs->events & SUB_RETRY_SEND) {
Amaury Denoyelle8afe4b82023-03-21 11:39:24 +01008538 /* RFC 9002 7.5. Probe Timeout
8539 *
8540 * Probe packets MUST NOT be blocked by the congestion controller.
8541 */
8542 if ((quic_path_prep_data(qc->path) || pktns->tx.pto_probe) &&
Amaury Denoyellecaa16542023-02-28 15:11:26 +01008543 (!qc_test_fd(qc) || !fd_send_active(qc->fd))) {
Amaury Denoyellee0fe1182023-02-28 15:08:59 +01008544 tasklet_wakeup(qc->subs->tasklet);
8545 qc->subs->events &= ~SUB_RETRY_SEND;
8546 if (!qc->subs->events)
8547 qc->subs = NULL;
8548
8549 return 1;
8550 }
8551 }
8552
8553 return 0;
8554}
8555
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008556/* Move a <qc> QUIC connection and its resources from the current thread to the
Willy Tarreau77d37b02023-04-20 19:03:49 +02008557 * new one <new_tid> optionally in association with <new_li> (since it may need
8558 * to change when migrating to a thread from a different group, otherwise leave
8559 * it NULL). After this call, the connection cannot be dereferenced anymore on
8560 * the current thread.
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008561 *
8562 * Returns 0 on success else non-zero.
8563 */
Willy Tarreau77d37b02023-04-20 19:03:49 +02008564int qc_set_tid_affinity(struct quic_conn *qc, uint new_tid, struct listener *new_li)
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008565{
8566 struct task *t1 = NULL, *t2 = NULL;
8567 struct tasklet *t3 = NULL;
8568
8569 struct quic_connection_id *conn_id;
8570 struct eb64_node *node;
8571
8572 TRACE_ENTER(QUIC_EV_CONN_SET_AFFINITY, qc);
8573
8574 /* Pre-allocate all required resources. This ensures we do not left a
8575 * connection with only some of its field rebinded.
8576 */
8577 if (((t1 = task_new_on(new_tid)) == NULL) ||
8578 (qc->timer_task && (t2 = task_new_on(new_tid)) == NULL) ||
8579 (t3 = tasklet_new()) == NULL) {
8580 goto err;
8581 }
8582
8583 /* Reinit idle timer task. */
8584 task_kill(qc->idle_timer_task);
8585 t1->expire = qc->idle_timer_task->expire;
8586 qc->idle_timer_task = t1;
8587 qc->idle_timer_task->process = qc_idle_timer_task;
8588 qc->idle_timer_task->context = qc;
8589
8590 /* Reinit timer task if allocated. */
8591 if (qc->timer_task) {
8592 task_kill(qc->timer_task);
8593 qc->timer_task = t2;
8594 qc->timer_task->process = qc_process_timer;
8595 qc->timer_task->context = qc;
8596 }
8597
8598 /* Reinit IO tasklet. */
Amaury Denoyelle739de3f2023-04-11 14:42:31 +02008599 if (qc->wait_event.tasklet->state & TASK_IN_LIST)
8600 qc->flags |= QUIC_FL_CONN_IO_TO_REQUEUE;
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008601 tasklet_kill(qc->wait_event.tasklet);
8602 /* In most cases quic_conn_app_io_cb is used but for 0-RTT quic_conn_io_cb can be still activated. */
8603 t3->process = qc->wait_event.tasklet->process;
8604 qc->wait_event.tasklet = t3;
8605 qc->wait_event.tasklet->tid = new_tid;
8606 qc->wait_event.tasklet->context = qc;
8607 qc->wait_event.events = 0;
8608
8609 /* Rebind the connection FD. */
8610 if (qc_test_fd(qc)) {
Amaury Denoyelle739de3f2023-04-11 14:42:31 +02008611 /* Reading is reactivated by the new thread. */
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008612 fd_migrate_on(qc->fd, new_tid);
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008613 }
8614
Amaury Denoyelle7b516d32023-04-26 16:12:12 +02008615 /* Remove conn from per-thread list instance. It will be hidden from
8616 * "show quic" until rebinding is completed.
8617 */
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008618 qc_detach_th_ctx_list(qc, 0);
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008619
8620 node = eb64_first(&qc->cids);
8621 BUG_ON(!node || eb64_next(node)); /* One and only one CID must be present before affinity rebind. */
8622 conn_id = eb64_entry(node, struct quic_connection_id, seq_num);
Willy Tarreau77d37b02023-04-20 19:03:49 +02008623
8624 /* At this point no connection was accounted for yet on this
8625 * listener so it's OK to just swap the pointer.
8626 */
8627 if (new_li && new_li != qc->li)
8628 qc->li = new_li;
8629
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008630 /* Rebinding is considered done when CID points to the new thread. No
8631 * access should be done to quic-conn instance after it.
8632 */
Amaury Denoyelled6646dd2023-04-26 17:15:37 +02008633 qc->flags |= QUIC_FL_CONN_AFFINITY_CHANGED;
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008634 HA_ATOMIC_STORE(&conn_id->tid, new_tid);
8635 qc = NULL;
8636
8637 TRACE_LEAVE(QUIC_EV_CONN_SET_AFFINITY, NULL);
8638 return 0;
8639
8640 err:
8641 task_destroy(t1);
8642 task_destroy(t2);
Tim Duesterhusb1ec21d2023-04-22 17:47:32 +02008643 tasklet_free(t3);
Amaury Denoyelle25174d52023-04-05 17:52:05 +02008644
8645 TRACE_DEVEL("leaving on error", QUIC_EV_CONN_SET_AFFINITY, qc);
8646 return 1;
8647}
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008648
Amaury Denoyelle739de3f2023-04-11 14:42:31 +02008649/* Must be called after qc_set_tid_affinity() on the new thread. */
8650void qc_finalize_affinity_rebind(struct quic_conn *qc)
8651{
8652 TRACE_ENTER(QUIC_EV_CONN_SET_AFFINITY, qc);
8653
Amaury Denoyelled6646dd2023-04-26 17:15:37 +02008654 /* This function must not be called twice after an affinity rebind. */
8655 BUG_ON(!(qc->flags & QUIC_FL_CONN_AFFINITY_CHANGED));
8656 qc->flags &= ~QUIC_FL_CONN_AFFINITY_CHANGED;
8657
Amaury Denoyelle7b516d32023-04-26 16:12:12 +02008658 /* A connection must not pass to closing state until affinity rebind
8659 * is completed. Else quic_handle_stopping() may miss it during process
8660 * stopping cleanup.
8661 */
8662 BUG_ON(qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING));
8663
8664 /* Reinsert connection in ha_thread_ctx global list. */
8665 LIST_APPEND(&th_ctx->quic_conns, &qc->el_th_ctx);
8666 qc->qc_epoch = HA_ATOMIC_LOAD(&qc_epoch);
8667
Amaury Denoyelle739de3f2023-04-11 14:42:31 +02008668 /* Reactivate FD polling if connection socket is active. */
8669 qc_want_recv(qc);
8670
8671 /* Reactivate timer task if needed. */
8672 qc_set_timer(qc);
8673
8674 /* Idle timer task is always active. */
8675 task_queue(qc->idle_timer_task);
8676
8677 /* Reactivate IO tasklet if needed. */
8678 if (qc->flags & QUIC_FL_CONN_IO_TO_REQUEUE) {
8679 tasklet_wakeup(qc->wait_event.tasklet);
8680 qc->flags &= ~QUIC_FL_CONN_IO_TO_REQUEUE;
8681 }
8682
8683 TRACE_LEAVE(QUIC_EV_CONN_SET_AFFINITY, qc);
8684}
8685
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008686enum quic_dump_format {
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008687 QUIC_DUMP_FMT_ONELINE,
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008688 QUIC_DUMP_FMT_FULL,
8689};
8690
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008691/* appctx context used by "show quic" command */
8692struct show_quic_ctx {
8693 unsigned int epoch;
8694 struct bref bref; /* back-reference to the quic-conn being dumped */
8695 unsigned int thr;
Amaury Denoyelle3f9758e2023-02-01 17:31:02 +01008696 int flags;
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008697 enum quic_dump_format format;
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008698};
8699
Amaury Denoyelle3f9758e2023-02-01 17:31:02 +01008700#define QC_CLI_FL_SHOW_ALL 0x1 /* show closing/draining connections */
8701
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008702static int cli_parse_show_quic(char **args, char *payload, struct appctx *appctx, void *private)
8703{
8704 struct show_quic_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008705 int argc = 2;
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008706
8707 if (!cli_has_level(appctx, ACCESS_LVL_OPER))
8708 return 1;
8709
8710 ctx->epoch = _HA_ATOMIC_FETCH_ADD(&qc_epoch, 1);
8711 ctx->thr = 0;
Amaury Denoyelle3f9758e2023-02-01 17:31:02 +01008712 ctx->flags = 0;
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008713 ctx->format = QUIC_DUMP_FMT_ONELINE;
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008714
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008715 if (strcmp(args[argc], "oneline") == 0) {
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008716 /* format already used as default value */
8717 ++argc;
8718 }
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008719 else if (strcmp(args[argc], "full") == 0) {
8720 ctx->format = QUIC_DUMP_FMT_FULL;
8721 ++argc;
8722 }
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008723
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008724 while (*args[argc]) {
8725 if (strcmp(args[argc], "all") == 0)
8726 ctx->flags |= QC_CLI_FL_SHOW_ALL;
8727
8728 ++argc;
8729 }
Amaury Denoyelle10a46de2023-02-09 18:18:45 +01008730
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008731 LIST_INIT(&ctx->bref.users);
8732
8733 return 0;
8734}
8735
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008736/* Dump for "show quic" with "oneline" format. */
8737static void dump_quic_oneline(struct show_quic_ctx *ctx, struct quic_conn *qc)
8738{
8739 char bufaddr[INET6_ADDRSTRLEN], bufport[6];
Amaury Denoyelleaa39cc92023-05-22 10:57:56 +02008740 int ret;
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008741 unsigned char cid_len;
8742
Amaury Denoyelleaa39cc92023-05-22 10:57:56 +02008743 ret = chunk_appendf(&trash, "%p[%02u]/%-.12s ", qc, ctx->thr,
8744 qc->li->bind_conf->frontend->id);
8745 chunk_appendf(&trash, "%*s", 36 - ret, " "); /* align output */
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008746
8747 /* State */
8748 if (qc->flags & QUIC_FL_CONN_CLOSING)
8749 chunk_appendf(&trash, "CLOSE ");
8750 else if (qc->flags & QUIC_FL_CONN_DRAINING)
8751 chunk_appendf(&trash, "DRAIN ");
8752 else if (qc->state < QUIC_HS_ST_COMPLETE)
8753 chunk_appendf(&trash, "HDSHK ");
8754 else
8755 chunk_appendf(&trash, "ESTAB ");
8756
8757 /* Bytes in flight / Lost packets */
8758 chunk_appendf(&trash, "%9llu %6llu %6llu ",
8759 (ullong)qc->path->in_flight,
8760 (ullong)qc->path->ifae_pkts,
8761 (ullong)qc->path->loss.nb_lost_pkt);
8762
8763 /* Socket */
8764 if (qc->local_addr.ss_family == AF_INET ||
8765 qc->local_addr.ss_family == AF_INET6) {
Frédéric Lécaille8f8e3fa2023-06-14 09:17:20 +02008766 addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
8767 port_to_str(&qc->local_addr, bufport, sizeof(bufport));
8768 chunk_appendf(&trash, "%15s:%-5s ", bufaddr, bufport);
8769
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008770 addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
8771 port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
Amaury Denoyelleaa39cc92023-05-22 10:57:56 +02008772 chunk_appendf(&trash, "%15s:%-5s ", bufaddr, bufport);
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008773
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008774 }
8775
8776 /* CIDs */
8777 for (cid_len = 0; cid_len < qc->scid.len; ++cid_len)
8778 chunk_appendf(&trash, "%02x", qc->scid.data[cid_len]);
8779
8780 chunk_appendf(&trash, " ");
8781 for (cid_len = 0; cid_len < qc->dcid.len; ++cid_len)
8782 chunk_appendf(&trash, "%02x", qc->dcid.data[cid_len]);
8783
8784 chunk_appendf(&trash, "\n");
8785}
8786
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008787/* Dump for "show quic" with "full" format. */
8788static void dump_quic_full(struct show_quic_ctx *ctx, struct quic_conn *qc)
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008789{
Frédéric Lécaillea3772e12023-03-21 13:42:43 +01008790 struct quic_pktns *pktns;
Amaury Denoyelle2eda63b2023-02-01 17:05:36 +01008791 struct eb64_node *node;
8792 struct qc_stream_desc *stream;
Amaury Denoyelleb89c0e22023-02-01 17:04:26 +01008793 char bufaddr[INET6_ADDRSTRLEN], bufport[6];
Frédéric Lécaillea73563b2023-05-25 16:10:03 +02008794 int expire, i, addnl;
Amaury Denoyelle58d9d5d2023-02-01 11:54:43 +01008795 unsigned char cid_len;
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008796
Frédéric Lécaillea73563b2023-05-25 16:10:03 +02008797 addnl = 0;
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008798 /* CIDs */
8799 chunk_appendf(&trash, "* %p[%02u]: scid=", qc, ctx->thr);
8800 for (cid_len = 0; cid_len < qc->scid.len; ++cid_len)
8801 chunk_appendf(&trash, "%02x", qc->scid.data[cid_len]);
8802 while (cid_len++ < 20)
8803 chunk_appendf(&trash, "..");
8804
8805 chunk_appendf(&trash, " dcid=");
8806 for (cid_len = 0; cid_len < qc->dcid.len; ++cid_len)
8807 chunk_appendf(&trash, "%02x", qc->dcid.data[cid_len]);
8808 while (cid_len++ < 20)
8809 chunk_appendf(&trash, "..");
8810
8811 chunk_appendf(&trash, "\n");
8812
8813 chunk_appendf(&trash, " loc. TPs:");
8814 quic_transport_params_dump(&trash, qc, &qc->rx.params);
8815 chunk_appendf(&trash, "\n");
8816 chunk_appendf(&trash, " rem. TPs:");
8817 quic_transport_params_dump(&trash, qc, &qc->tx.params);
8818 chunk_appendf(&trash, "\n");
8819
8820 /* Connection state */
8821 if (qc->flags & QUIC_FL_CONN_CLOSING)
8822 chunk_appendf(&trash, " st=closing ");
8823 else if (qc->flags & QUIC_FL_CONN_DRAINING)
8824 chunk_appendf(&trash, " st=draining ");
8825 else if (qc->state < QUIC_HS_ST_CONFIRMED)
8826 chunk_appendf(&trash, " st=handshake ");
8827 else
8828 chunk_appendf(&trash, " st=opened ");
8829
8830 if (qc->mux_state == QC_MUX_NULL)
8831 chunk_appendf(&trash, "mux=null ");
8832 else if (qc->mux_state == QC_MUX_READY)
8833 chunk_appendf(&trash, "mux=ready ");
8834 else
8835 chunk_appendf(&trash, "mux=released ");
8836
8837 expire = qc->idle_expire;
8838 chunk_appendf(&trash, "expire=%02ds ",
8839 TICKS_TO_MS(tick_remain(now_ms, expire)) / 1000);
8840
8841 chunk_appendf(&trash, "\n");
8842
8843 /* Socket */
8844 chunk_appendf(&trash, " fd=%d", qc->fd);
8845 if (qc->local_addr.ss_family == AF_INET ||
8846 qc->local_addr.ss_family == AF_INET6) {
8847 addr_to_str(&qc->local_addr, bufaddr, sizeof(bufaddr));
8848 port_to_str(&qc->local_addr, bufport, sizeof(bufport));
Frédéric Lécaille8f8e3fa2023-06-14 09:17:20 +02008849 chunk_appendf(&trash, " local_addr=%s:%s", bufaddr, bufport);
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008850
8851 addr_to_str(&qc->peer_addr, bufaddr, sizeof(bufaddr));
8852 port_to_str(&qc->peer_addr, bufport, sizeof(bufport));
Frédéric Lécaille8f8e3fa2023-06-14 09:17:20 +02008853 chunk_appendf(&trash, " foreign_addr=%s:%s", bufaddr, bufport);
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008854 }
8855
8856 chunk_appendf(&trash, "\n");
8857
8858 /* Packet number spaces information */
8859 pktns = &qc->pktns[QUIC_TLS_PKTNS_INITIAL];
8860 chunk_appendf(&trash, " [initl] rx.ackrng=%-6zu tx.inflight=%-6zu",
8861 pktns->rx.arngs.sz, pktns->tx.in_flight);
8862 pktns = &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE];
8863 chunk_appendf(&trash, " [hndshk] rx.ackrng=%-6zu tx.inflight=%-6zu\n",
8864 pktns->rx.arngs.sz, pktns->tx.in_flight);
8865 pktns = &qc->pktns[QUIC_TLS_PKTNS_01RTT];
8866 chunk_appendf(&trash, " [01rtt] rx.ackrng=%-6zu tx.inflight=%-6zu\n",
8867 pktns->rx.arngs.sz, pktns->tx.in_flight);
8868
8869 chunk_appendf(&trash, " srtt=%-4u rttvar=%-4u rttmin=%-4u ptoc=%-4u cwnd=%-6llu"
Frédéric Lécaillea73563b2023-05-25 16:10:03 +02008870 " mcwnd=%-6llu sentpkts=%-6llu lostpkts=%-6llu\n",
Frédéric Lécaille35fb5932023-09-05 15:24:11 +02008871 qc->path->loss.srtt, qc->path->loss.rtt_var,
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008872 qc->path->loss.rtt_min, qc->path->loss.pto_count, (ullong)qc->path->cwnd,
Frédéric Lécaillea73563b2023-05-25 16:10:03 +02008873 (ullong)qc->path->mcwnd, (ullong)qc->cntrs.sent_pkt, (ullong)qc->path->loss.nb_lost_pkt);
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008874
Frédéric Lécaillea73563b2023-05-25 16:10:03 +02008875 if (qc->cntrs.dropped_pkt) {
8876 chunk_appendf(&trash, " droppkts=%-6llu", qc->cntrs.dropped_pkt);
8877 addnl = 1;
8878 }
8879 if (qc->cntrs.dropped_pkt_bufoverrun) {
8880 chunk_appendf(&trash, " dropbuff=%-6llu", qc->cntrs.dropped_pkt_bufoverrun);
8881 addnl = 1;
8882 }
8883 if (qc->cntrs.dropped_parsing) {
8884 chunk_appendf(&trash, " droppars=%-6llu", qc->cntrs.dropped_parsing);
8885 addnl = 1;
8886 }
8887 if (qc->cntrs.socket_full) {
8888 chunk_appendf(&trash, " sockfull=%-6llu", qc->cntrs.socket_full);
8889 addnl = 1;
8890 }
8891 if (qc->cntrs.sendto_err) {
8892 chunk_appendf(&trash, " sendtoerr=%-6llu", qc->cntrs.sendto_err);
8893 addnl = 1;
8894 }
8895 if (qc->cntrs.sendto_err_unknown) {
8896 chunk_appendf(&trash, " sendtounknerr=%-6llu", qc->cntrs.sendto_err);
8897 addnl = 1;
8898 }
8899 if (qc->cntrs.conn_migration_done) {
8900 chunk_appendf(&trash, " migrdone=%-6llu", qc->cntrs.conn_migration_done);
8901 addnl = 1;
8902 }
8903 if (qc->cntrs.data_blocked) {
8904 chunk_appendf(&trash, " datablocked=%-6llu", qc->cntrs.data_blocked);
8905 addnl = 1;
8906 }
8907 if (qc->cntrs.stream_data_blocked) {
8908 chunk_appendf(&trash, " sdatablocked=%-6llu", qc->cntrs.stream_data_blocked);
8909 addnl = 1;
8910 }
8911 if (qc->cntrs.streams_blocked_bidi) {
8912 chunk_appendf(&trash, " sblockebidi=%-6llu", qc->cntrs.streams_blocked_bidi);
8913 addnl = 1;
8914 }
8915 if (qc->cntrs.streams_blocked_uni) {
8916 chunk_appendf(&trash, " sblockeduni=%-6llu", qc->cntrs.streams_blocked_uni);
8917 addnl = 1;
8918 }
8919 if (addnl)
8920 chunk_appendf(&trash, "\n");
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02008921
8922 /* Streams */
8923 node = eb64_first(&qc->streams_by_id);
8924 i = 0;
8925 while (node) {
8926 stream = eb64_entry(node, struct qc_stream_desc, by_id);
8927 node = eb64_next(node);
8928
8929 chunk_appendf(&trash, " | stream=%-8llu", (unsigned long long)stream->by_id.key);
8930 chunk_appendf(&trash, " off=%-8llu ack=%-8llu",
8931 (unsigned long long)stream->buf_offset,
8932 (unsigned long long)stream->ack_offset);
8933
8934 if (!(++i % 3)) {
8935 chunk_appendf(&trash, "\n");
8936 i = 0;
8937 }
8938 }
8939
8940 chunk_appendf(&trash, "\n");
8941}
8942
8943static int cli_io_handler_dump_quic(struct appctx *appctx)
8944{
8945 struct show_quic_ctx *ctx = appctx->svcctx;
8946 struct stconn *sc = appctx_sc(appctx);
8947 struct quic_conn *qc;
8948
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008949 thread_isolate();
8950
8951 if (ctx->thr >= global.nbthread)
8952 goto done;
8953
Christopher Faulet87633c32023-04-03 18:32:50 +02008954 /* FIXME: Don't watch the other side !*/
Christopher Faulet208c7122023-04-13 16:16:15 +02008955 if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUT_DONE)) {
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008956 /* If we're forced to shut down, we might have to remove our
8957 * reference to the last stream being dumped.
8958 */
8959 if (!LIST_ISEMPTY(&ctx->bref.users))
8960 LIST_DEL_INIT(&ctx->bref.users);
8961 goto done;
8962 }
8963
8964 chunk_reset(&trash);
8965
8966 if (!LIST_ISEMPTY(&ctx->bref.users)) {
8967 /* Remove show_quic_ctx from previous quic_conn instance. */
8968 LIST_DEL_INIT(&ctx->bref.users);
8969 }
8970 else if (!ctx->bref.ref) {
8971 /* First invocation. */
8972 ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008973
8974 /* Print legend for oneline format. */
8975 if (ctx->format == QUIC_DUMP_FMT_ONELINE) {
Amaury Denoyelleaa39cc92023-05-22 10:57:56 +02008976 chunk_appendf(&trash, "# conn/frontend state "
Frédéric Lécaille8f8e3fa2023-06-14 09:17:20 +02008977 "in_flight infl_p lost_p "
8978 "Local Address Foreign Address "
Amaury Denoyelle2273af12023-05-05 16:08:34 +02008979 "local & remote CIDs\n");
8980 applet_putchk(appctx, &trash);
8981 }
Amaury Denoyelle15c74702023-02-01 10:18:26 +01008982 }
8983
8984 while (1) {
8985 int done = 0;
8986
8987 if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns) {
Amaury Denoyelle2d376292023-03-08 09:42:31 +01008988 /* If closing connections requested through "all", move
8989 * to quic_conns_clo list after browsing quic_conns.
8990 * Else move directly to the next quic_conns thread.
8991 */
8992 if (ctx->flags & QC_CLI_FL_SHOW_ALL) {
8993 ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns_clo.n;
8994 continue;
8995 }
8996
8997 done = 1;
8998 }
8999 else if (ctx->bref.ref == &ha_thread_ctx[ctx->thr].quic_conns_clo) {
9000 /* Closing list entirely browsed, go to next quic_conns
9001 * thread.
9002 */
Amaury Denoyelle15c74702023-02-01 10:18:26 +01009003 done = 1;
9004 }
9005 else {
Amaury Denoyelle2d376292023-03-08 09:42:31 +01009006 /* Retrieve next element of the current list. */
Amaury Denoyelle15c74702023-02-01 10:18:26 +01009007 qc = LIST_ELEM(ctx->bref.ref, struct quic_conn *, el_th_ctx);
9008 if ((int)(qc->qc_epoch - ctx->epoch) > 0)
9009 done = 1;
9010 }
9011
9012 if (done) {
9013 ++ctx->thr;
9014 if (ctx->thr >= global.nbthread)
9015 break;
Amaury Denoyelle2d376292023-03-08 09:42:31 +01009016 /* Switch to next thread quic_conns list. */
Amaury Denoyelle15c74702023-02-01 10:18:26 +01009017 ctx->bref.ref = ha_thread_ctx[ctx->thr].quic_conns.n;
9018 continue;
9019 }
9020
Amaury Denoyellebc1f5fe2023-05-05 16:07:58 +02009021 switch (ctx->format) {
9022 case QUIC_DUMP_FMT_FULL:
9023 dump_quic_full(ctx, qc);
9024 break;
Amaury Denoyelle2273af12023-05-05 16:08:34 +02009025 case QUIC_DUMP_FMT_ONELINE:
9026 dump_quic_oneline(ctx, qc);
9027 break;
Amaury Denoyelle2eda63b2023-02-01 17:05:36 +01009028 }
9029
Amaury Denoyelle15c74702023-02-01 10:18:26 +01009030 if (applet_putchk(appctx, &trash) == -1) {
9031 /* Register show_quic_ctx to quic_conn instance. */
9032 LIST_APPEND(&qc->back_refs, &ctx->bref.users);
9033 goto full;
9034 }
9035
9036 ctx->bref.ref = qc->el_th_ctx.n;
9037 }
9038
9039 done:
9040 thread_release();
9041 return 1;
9042
9043 full:
9044 thread_release();
9045 return 0;
9046}
9047
9048static void cli_release_show_quic(struct appctx *appctx)
9049{
9050 struct show_quic_ctx *ctx = appctx->svcctx;
9051
9052 if (ctx->thr < global.nbthread) {
9053 thread_isolate();
9054 if (!LIST_ISEMPTY(&ctx->bref.users))
9055 LIST_DEL_INIT(&ctx->bref.users);
9056 thread_release();
9057 }
9058}
9059
9060static struct cli_kw_list cli_kws = {{ }, {
Willy Tarreau6ccc8622023-05-31 15:54:48 +02009061 { { "show", "quic", NULL }, "show quic [oneline|full] [all] : 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 +01009062 {{},}
Amaury Denoyelle15c74702023-02-01 10:18:26 +01009063}};
9064
9065INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
9066
9067static void init_quic()
9068{
9069 int thr;
9070
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01009071 for (thr = 0; thr < MAX_THREADS; ++thr) {
Amaury Denoyelle15c74702023-02-01 10:18:26 +01009072 LIST_INIT(&ha_thread_ctx[thr].quic_conns);
Amaury Denoyelleefed86c2023-03-08 09:42:04 +01009073 LIST_INIT(&ha_thread_ctx[thr].quic_conns_clo);
9074 }
Amaury Denoyelle15c74702023-02-01 10:18:26 +01009075}
9076INITCALL0(STG_INIT, init_quic);
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +02009077
9078/*
9079 * Local variables:
9080 * c-indent-level: 8
9081 * c-basic-offset: 8
9082 * End:
9083 */