blob: f83ed86811d4bcf1c68d6215a78a0ea9117dee1f [file] [log] [blame]
Frédéric Lécaille748ece62022-05-21 23:58:40 +02001#include <haproxy/global.h>
2#include <haproxy/ncbuf-t.h>
3#include <haproxy/net_helper.h>
4#include <haproxy/quic_enc.h>
5#include <haproxy/quic_tp.h>
Frédéric Lécaillec7785b52022-05-23 09:08:54 +02006#include <haproxy/trace.h>
Frédéric Lécaille748ece62022-05-21 23:58:40 +02007#include <haproxy/xprt_quic-t.h>
8
9#define QUIC_MAX_UDP_PAYLOAD_SIZE 2048
10
Frédéric Lécaillec7785b52022-05-23 09:08:54 +020011#define TRACE_SOURCE &trace_quic
12
Frédéric Lécaille748ece62022-05-21 23:58:40 +020013/* This is the values of some QUIC transport parameters when absent.
14 * Should be used to initialize any transport parameters (local or remote)
15 * before updating them with customized values.
16 */
17struct quic_transport_params quic_dflt_transport_params = {
Frédéric Lécailleaee67572022-05-23 18:29:39 +020018 .max_udp_payload_size = QUIC_TP_DFLT_MAX_UDP_PAYLOAD_SIZE,
19 .ack_delay_exponent = QUIC_TP_DFLT_ACK_DELAY_COMPONENT,
20 .max_ack_delay = QUIC_TP_DFLT_MAX_ACK_DELAY,
21 .active_connection_id_limit = QUIC_TP_DFLT_ACTIVE_CONNECTION_ID_LIMIT,
Frédéric Lécaille748ece62022-05-21 23:58:40 +020022};
23
24/* Initialize <dst> transport parameters with default values (when absent)
25 * from <quic_dflt_transport_params>.
26 * Never fails.
27 */
28static void quic_dflt_transport_params_cpy(struct quic_transport_params *dst)
29{
30 dst->max_udp_payload_size = quic_dflt_transport_params.max_udp_payload_size;
31 dst->ack_delay_exponent = quic_dflt_transport_params.ack_delay_exponent;
32 dst->max_ack_delay = quic_dflt_transport_params.max_ack_delay;
33 dst->active_connection_id_limit = quic_dflt_transport_params.active_connection_id_limit;
34}
35
36/* Initialize <p> transport parameters. <server> is a boolean, set if TPs are
37 * used by a server (haproxy frontend) else this is for a client (haproxy
38 * backend).
39 *
40 * This must only be used for haproxy local parameters. To initialize peer
41 * parameters, see quic_dflt_transport_params_cpy().
42 *
43 * Never fails.
44 */
45void quic_transport_params_init(struct quic_transport_params *p, int server)
46{
47 const uint64_t ncb_size = global.tune.bufsize - NCB_RESERVED_SZ;
Frédéric Lécaille26740982022-05-23 17:28:01 +020048 const int max_streams_bidi = global.tune.quic_frontend_max_streams_bidi;
Frédéric Lécaille748ece62022-05-21 23:58:40 +020049 const int max_streams_uni = 3;
50
51 /* Set RFC default values for unspecified parameters. */
52 quic_dflt_transport_params_cpy(p);
53
Frédéric Lécailleaee67572022-05-23 18:29:39 +020054 /* Set the max_udp_payload_size value. If not would equal to
55 * QUIC_TP_DFLT_MAX_UDP_PAYLOAD_SIZE
56 */
57 p->max_udp_payload_size = QUIC_MAX_UDP_PAYLOAD_SIZE;
Frédéric Lécaille1d96d6e2022-05-23 16:38:14 +020058 if (server)
59 p->max_idle_timeout = global.tune.quic_frontend_max_idle_timeout;
60 else
61 p->max_idle_timeout = global.tune.quic_backend_max_idle_timeout;
Frédéric Lécaille748ece62022-05-21 23:58:40 +020062
63 p->initial_max_streams_bidi = max_streams_bidi;
64 p->initial_max_streams_uni = max_streams_uni;
65 p->initial_max_stream_data_bidi_local = ncb_size;
66 p->initial_max_stream_data_bidi_remote = ncb_size;
67 p->initial_max_stream_data_uni = ncb_size;
68 p->initial_max_data = (max_streams_bidi + max_streams_uni) * ncb_size;
69
70 if (server)
71 p->with_stateless_reset_token = 1;
72
73 p->active_connection_id_limit = 8;
74
75 p->retry_source_connection_id.len = 0;
76}
77
78/* Encode <addr> preferred address transport parameter in <buf> without its
79 * "type+len" prefix. Note that the IP addresses must be encoded in network byte
80 * order.
81 * So ->ipv4_addr and ->ipv6_addr, which are buffers, must contained values
82 * already encoded in network byte order.
83 * It is the responsibility of the caller to check there is enough room in <buf> to encode
84 * this address.
85 * Never fails.
86 */
87static void quic_transport_param_enc_pref_addr_val(unsigned char **buf,
88 const unsigned char *end,
89 struct tp_preferred_address *addr)
90{
91 write_n16(*buf, addr->ipv4_port);
92 *buf += sizeof addr->ipv4_port;
93
94 memcpy(*buf, addr->ipv4_addr, sizeof addr->ipv4_addr);
95 *buf += sizeof addr->ipv4_addr;
96
97 write_n16(*buf, addr->ipv6_port);
98 *buf += sizeof addr->ipv6_port;
99
100 memcpy(*buf, addr->ipv6_addr, sizeof addr->ipv6_addr);
101 *buf += sizeof addr->ipv6_addr;
102
103 *(*buf)++ = addr->cid.len;
104 if (addr->cid.len) {
105 memcpy(*buf, addr->cid.data, addr->cid.len);
106 *buf += addr->cid.len;
107 }
108
109 memcpy(*buf, addr->stateless_reset_token, sizeof addr->stateless_reset_token);
110 *buf += sizeof addr->stateless_reset_token;
111}
112
113/* Decode into <addr> preferred address transport parameter found in <*buf> buffer.
114 * Returns 1 if succeeded, 0 if not.
115 */
116static int quic_transport_param_dec_pref_addr(struct tp_preferred_address *addr,
117 const unsigned char **buf,
118 const unsigned char *end)
119{
120 ssize_t addr_len;
121
122 addr_len = sizeof addr->ipv4_port + sizeof addr->ipv4_addr;
123 addr_len += sizeof addr->ipv6_port + sizeof addr->ipv6_addr;
124 addr_len += sizeof addr->cid.len;
125
126 if (end - *buf < addr_len)
127 return 0;
128
129 addr->ipv4_port = read_n16(*buf);
130 *buf += sizeof addr->ipv4_port;
131
132 memcpy(addr->ipv4_addr, *buf, sizeof addr->ipv4_addr);
133 *buf += sizeof addr->ipv4_addr;
134
135 addr->ipv6_port = read_n16(*buf);
136 *buf += sizeof addr->ipv6_port;
137
138 memcpy(addr->ipv6_addr, *buf, sizeof addr->ipv6_addr);
139 *buf += sizeof addr->ipv6_addr;
140
141 addr->cid.len = *(*buf)++;
142 if (addr->cid.len) {
143 if (end - *buf > addr->cid.len || addr->cid.len > sizeof addr->cid.data)
144 return 0;
145 memcpy(addr->cid.data, *buf, addr->cid.len);
146 *buf += addr->cid.len;
147 }
148
149 if (end - *buf != sizeof addr->stateless_reset_token)
150 return 0;
151
152 memcpy(addr->stateless_reset_token, *buf, end - *buf);
153 *buf += sizeof addr->stateless_reset_token;
154
155 return *buf == end;
156}
157
Frédéric Lécaille301425b2022-06-14 17:40:39 +0200158/* Decode into <v> version information received transport parameters from <*buf>
159 * buffer. <server> must be set to 1 for QUIC clients which receive server
160 * transport parameters, and 0 for QUIC servers which receive client transport
161 * parameters.
162 * Also set the QUIC negotiated version into <tp>.
163 * Return 1 if succeeded, 0 if not.
164 */
165static int quic_transport_param_dec_version_info(struct tp_version_information *tp,
166 const unsigned char **buf,
167 const unsigned char *end, int server)
168{
169 size_t tp_len = end - *buf;
170 const uint32_t *ver;
171
172 /* <tp_len> must be a multiple of sizeof(uint32_t) */
173 if (tp_len < sizeof tp->choosen || (tp_len & 0x3))
174 return 0;
175
176 tp->choosen = ntohl(*(uint32_t *)*buf);
177 /* Must not be null */
178 if (!tp->choosen)
179 return 0;
180
181 *buf += sizeof tp->choosen;
182 tp->others = (const uint32_t *)*buf;
183
184 /* Others versions must not be null */
185 for (ver = tp->others; ver < (const uint32_t *)end; ver++) {
186 if (!*ver)
187 return 0;
188 }
189
190 if (server)
191 /* TODO: not supported */
192 return 0;
193
Frédéric Lécaille4f5777a2022-06-20 19:39:26 +0200194 tp->nb_others = (end - (const unsigned char *)tp->others) / sizeof *tp->others;
Frédéric Lécaille301425b2022-06-14 17:40:39 +0200195 for (ver = tp->others; ver < (const uint32_t *)end; ver++) {
196 if (!tp->negotiated_version) {
197 int i;
198
199 for (i = 0; i < quic_versions_nb; i++) {
200 if (ntohl(*ver) == quic_versions[i].num) {
201 tp->negotiated_version = &quic_versions[i];
202 break;
203 }
204 }
205 }
206
207 if (preferred_version && ntohl(*ver) == preferred_version->num) {
208 tp->negotiated_version = preferred_version;
209 goto out;
210 }
211 }
212
213 out:
214 *buf = end;
215
216 return 1;
217}
218
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200219/* Decode into <p> struct a transport parameter found in <*buf> buffer with
220 * <type> as type and <len> as length, depending on <server> boolean value which
221 * must be set to 1 for a server (haproxy listener) or 0 for a client (connection
222 * to an haproxy server).
223 */
224static int quic_transport_param_decode(struct quic_transport_params *p,
225 int server, uint64_t type,
226 const unsigned char **buf, size_t len)
227{
228 const unsigned char *end = *buf + len;
229
230 switch (type) {
231 case QUIC_TP_ORIGINAL_DESTINATION_CONNECTION_ID:
232 if (!server || len > sizeof p->original_destination_connection_id.data)
233 return 0;
234
235 if (len)
236 memcpy(p->original_destination_connection_id.data, *buf, len);
237 p->original_destination_connection_id.len = len;
238 *buf += len;
239 p->original_destination_connection_id_present = 1;
240 break;
241 case QUIC_TP_INITIAL_SOURCE_CONNECTION_ID:
242 if (len > sizeof p->initial_source_connection_id.data)
243 return 0;
244
245 if (len)
246 memcpy(p->initial_source_connection_id.data, *buf, len);
247 p->initial_source_connection_id.len = len;
248 *buf += len;
249 p->initial_source_connection_id_present = 1;
250 break;
251 case QUIC_TP_STATELESS_RESET_TOKEN:
252 if (!server || len != sizeof p->stateless_reset_token)
253 return 0;
254 memcpy(p->stateless_reset_token, *buf, len);
255 *buf += len;
256 p->with_stateless_reset_token = 1;
257 break;
258 case QUIC_TP_PREFERRED_ADDRESS:
259 if (!server)
260 return 0;
261 if (!quic_transport_param_dec_pref_addr(&p->preferred_address, buf, *buf + len))
262 return 0;
263 p->with_preferred_address = 1;
264 break;
265 case QUIC_TP_MAX_IDLE_TIMEOUT:
266 if (!quic_dec_int(&p->max_idle_timeout, buf, end))
267 return 0;
268 break;
269 case QUIC_TP_MAX_UDP_PAYLOAD_SIZE:
270 if (!quic_dec_int(&p->max_udp_payload_size, buf, end))
271 return 0;
272 break;
273 case QUIC_TP_INITIAL_MAX_DATA:
274 if (!quic_dec_int(&p->initial_max_data, buf, end))
275 return 0;
276 break;
277 case QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
278 if (!quic_dec_int(&p->initial_max_stream_data_bidi_local, buf, end))
279 return 0;
280 break;
281 case QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
282 if (!quic_dec_int(&p->initial_max_stream_data_bidi_remote, buf, end))
283 return 0;
284 break;
285 case QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI:
286 if (!quic_dec_int(&p->initial_max_stream_data_uni, buf, end))
287 return 0;
288 break;
289 case QUIC_TP_INITIAL_MAX_STREAMS_BIDI:
290 if (!quic_dec_int(&p->initial_max_streams_bidi, buf, end))
291 return 0;
292 break;
293 case QUIC_TP_INITIAL_MAX_STREAMS_UNI:
294 if (!quic_dec_int(&p->initial_max_streams_uni, buf, end))
295 return 0;
296 break;
297 case QUIC_TP_ACK_DELAY_EXPONENT:
298 if (!quic_dec_int(&p->ack_delay_exponent, buf, end) ||
299 p->ack_delay_exponent > QUIC_TP_ACK_DELAY_EXPONENT_LIMIT)
300 return 0;
301 break;
302 case QUIC_TP_MAX_ACK_DELAY:
303 if (!quic_dec_int(&p->max_ack_delay, buf, end) ||
304 p->max_ack_delay > QUIC_TP_MAX_ACK_DELAY_LIMIT)
305 return 0;
306 break;
307 case QUIC_TP_DISABLE_ACTIVE_MIGRATION:
308 /* Zero-length parameter type. */
309 if (len != 0)
310 return 0;
311 p->disable_active_migration = 1;
312 break;
313 case QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT:
314 if (!quic_dec_int(&p->active_connection_id_limit, buf, end))
315 return 0;
316 break;
Frédéric Lécaille301425b2022-06-14 17:40:39 +0200317 case QUIC_TP_DRAFT_VERSION_INFORMATION:
318 if (!quic_transport_param_dec_version_info(&p->version_information,
319 buf, *buf + len, server))
320 return 0;
321 break;
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200322 default:
323 *buf += len;
324 };
325
326 return *buf == end;
327}
328
329/* Encode <type> and <len> variable length values in <buf>.
330 * Returns 1 if succeeded, 0 if not.
331 */
332static int quic_transport_param_encode_type_len(unsigned char **buf,
333 const unsigned char *end,
334 uint64_t type, uint64_t len)
335{
336 return quic_enc_int(buf, end, type) && quic_enc_int(buf, end, len);
337}
338
339/* Decode variable length type and length values of a QUIC transport parameter
340 * into <type> and <len> found in <*buf> buffer.
341 * Returns 1 if succeeded, 0 if not.
342 */
343static int quic_transport_param_decode_type_len(uint64_t *type, uint64_t *len,
344 const unsigned char **buf,
345 const unsigned char *end)
346{
347 return quic_dec_int(type, buf, end) && quic_dec_int(len, buf, end);
348}
349
350/* Encode <param> bytes stream with <type> as type and <length> as length into buf.
351 * Returns 1 if succeeded, 0 if not.
352 */
353static int quic_transport_param_enc_mem(unsigned char **buf, const unsigned char *end,
354 uint64_t type, void *param, uint64_t length)
355{
356 if (!quic_transport_param_encode_type_len(buf, end, type, length))
357 return 0;
358
359 if (end - *buf < length)
360 return 0;
361
362 if (length)
363 memcpy(*buf, param, length);
364 *buf += length;
365
366 return 1;
367}
368
369/* Encode <val> 64-bits value as variable length integer into <buf>.
370 * Returns 1 if succeeded, 0 if not.
371 */
372static int quic_transport_param_enc_int(unsigned char **buf,
373 const unsigned char *end,
374 uint64_t type, uint64_t val)
375{
376 size_t len;
377
378 len = quic_int_getsize(val);
379
380 return len && quic_transport_param_encode_type_len(buf, end, type, len) &&
381 quic_enc_int(buf, end, val);
382}
383
384/* Returns the required length in bytes to encode <cid> QUIC connection ID. */
385static inline size_t sizeof_quic_cid(const struct tp_cid *cid)
386{
387 return sizeof cid->len + cid->len;
388}
389
390/* Encode <addr> preferred address into <buf>.
391 * Note that the IP addresses must be encoded in network byte order.
392 * So ->ipv4_addr and ->ipv6_addr, which are buffers, must contained
393 * values already encoded in network byte order.
394 * Returns 1 if succeeded, 0 if not.
395 */
396static int quic_transport_param_enc_pref_addr(unsigned char **buf,
397 const unsigned char *end,
398 struct tp_preferred_address *addr)
399{
400 uint64_t addr_len = 0;
401
402 addr_len += sizeof addr->ipv4_port + sizeof addr->ipv4_addr;
403 addr_len += sizeof addr->ipv6_port + sizeof addr->ipv6_addr;
404 addr_len += sizeof_quic_cid(&addr->cid);
405 addr_len += sizeof addr->stateless_reset_token;
406
407 if (!quic_transport_param_encode_type_len(buf, end, QUIC_TP_PREFERRED_ADDRESS, addr_len))
408 return 0;
409
410 if (end - *buf < addr_len)
411 return 0;
412
413 quic_transport_param_enc_pref_addr_val(buf, end, addr);
414
415 return 1;
416}
417
Frédéric Lécaille301425b2022-06-14 17:40:39 +0200418/* Encode version information transport parameters with <choosen_version> as choosen
419 * version.
420 * Return 1 if succeeded, 0 if not.
421 */
422static int quic_transport_param_enc_version_info(unsigned char **buf,
423 const unsigned char *end,
424 const struct quic_version *choosen_version,
425 int server)
426{
427 int i;
428 uint64_t tp_len;
429 uint32_t ver;
430
431 tp_len = sizeof choosen_version->num + quic_versions_nb * sizeof(uint32_t);
432 if (!quic_transport_param_encode_type_len(buf, end,
433 QUIC_TP_DRAFT_VERSION_INFORMATION,
434 tp_len))
435 return 0;
436
437 if (end - *buf < tp_len)
438 return 0;
439
440 /* First: choosen version */
441 ver = htonl(choosen_version->num);
442 memcpy(*buf, &ver, sizeof ver);
443 *buf += sizeof ver;
444 /* For servers: all supported version, choosen included */
445 for (i = 0; i < quic_versions_nb; i++) {
446 ver = htonl(quic_versions[i].num);
447 memcpy(*buf, &ver, sizeof ver);
448 *buf += sizeof ver;
449 }
450
451 return 1;
452}
453
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200454/* Encode <p> transport parameter into <buf> depending on <server> value which
455 * must be set to 1 for a server (haproxy listener) or 0 for a client
456 * (connection to a haproxy server).
457 * Return the number of bytes consumed if succeeded, 0 if not.
458 */
459int quic_transport_params_encode(unsigned char *buf,
460 const unsigned char *end,
461 struct quic_transport_params *p,
Frédéric Lécaille301425b2022-06-14 17:40:39 +0200462 const struct quic_version *choosen_version,
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200463 int server)
464{
465 unsigned char *head;
466 unsigned char *pos;
467
468 head = pos = buf;
469 if (server) {
470 if (!quic_transport_param_enc_mem(&pos, end,
471 QUIC_TP_ORIGINAL_DESTINATION_CONNECTION_ID,
472 p->original_destination_connection_id.data,
473 p->original_destination_connection_id.len))
474 return 0;
475
476 if (p->retry_source_connection_id.len) {
477 if (!quic_transport_param_enc_mem(&pos, end,
478 QUIC_TP_RETRY_SOURCE_CONNECTION_ID,
479 p->retry_source_connection_id.data,
480 p->retry_source_connection_id.len))
481 return 0;
482 }
483
484 if (p->with_stateless_reset_token &&
485 !quic_transport_param_enc_mem(&pos, end, QUIC_TP_STATELESS_RESET_TOKEN,
486 p->stateless_reset_token,
487 sizeof p->stateless_reset_token))
488 return 0;
489 if (p->with_preferred_address &&
490 !quic_transport_param_enc_pref_addr(&pos, end, &p->preferred_address))
491 return 0;
492 }
493
494 if (!quic_transport_param_enc_mem(&pos, end,
495 QUIC_TP_INITIAL_SOURCE_CONNECTION_ID,
496 p->initial_source_connection_id.data,
497 p->initial_source_connection_id.len))
498 return 0;
499
500 if (p->max_idle_timeout &&
501 !quic_transport_param_enc_int(&pos, end, QUIC_TP_MAX_IDLE_TIMEOUT, p->max_idle_timeout))
502 return 0;
503
504 /*
505 * "max_packet_size" transport parameter must be transmitted only if different
506 * of the default value.
507 */
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200508 if (p->max_udp_payload_size != QUIC_TP_DFLT_MAX_UDP_PAYLOAD_SIZE &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200509 !quic_transport_param_enc_int(&pos, end, QUIC_TP_MAX_UDP_PAYLOAD_SIZE, p->max_udp_payload_size))
510 return 0;
511
512 if (p->initial_max_data &&
513 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_DATA, p->initial_max_data))
514 return 0;
515
516 if (p->initial_max_stream_data_bidi_local &&
517 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
518 p->initial_max_stream_data_bidi_local))
519 return 0;
520
521 if (p->initial_max_stream_data_bidi_remote &&
522 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
523 p->initial_max_stream_data_bidi_remote))
524 return 0;
525
526 if (p->initial_max_stream_data_uni &&
527 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI,
528 p->initial_max_stream_data_uni))
529 return 0;
530
531 if (p->initial_max_streams_bidi &&
532 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAMS_BIDI,
533 p->initial_max_streams_bidi))
534 return 0;
535
536 if (p->initial_max_streams_uni &&
537 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAMS_UNI,
538 p->initial_max_streams_uni))
539 return 0;
540
541 /*
542 * "ack_delay_exponent" transport parameter must be transmitted only if different
543 * of the default value.
544 */
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200545 if (p->ack_delay_exponent != QUIC_TP_DFLT_ACK_DELAY_COMPONENT &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200546 !quic_transport_param_enc_int(&pos, end, QUIC_TP_ACK_DELAY_EXPONENT, p->ack_delay_exponent))
547 return 0;
548
549 /*
550 * "max_ack_delay" transport parameter must be transmitted only if different
551 * of the default value.
552 */
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200553 if (p->max_ack_delay != QUIC_TP_DFLT_MAX_ACK_DELAY &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200554 !quic_transport_param_enc_int(&pos, end, QUIC_TP_MAX_ACK_DELAY, p->max_ack_delay))
555 return 0;
556
557 /* 0-length value */
558 if (p->disable_active_migration &&
559 !quic_transport_param_encode_type_len(&pos, end, QUIC_TP_DISABLE_ACTIVE_MIGRATION, 0))
560 return 0;
561
562 if (p->active_connection_id_limit &&
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200563 p->active_connection_id_limit != QUIC_TP_DFLT_ACTIVE_CONNECTION_ID_LIMIT &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200564 !quic_transport_param_enc_int(&pos, end, QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT,
565 p->active_connection_id_limit))
566 return 0;
567
Frédéric Lécaille301425b2022-06-14 17:40:39 +0200568 if (!quic_transport_param_enc_version_info(&pos, end, choosen_version, server))
569 return 0;
570
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200571 return pos - head;
572}
573
574/* Decode transport parameters found in <buf> buffer into <p>, depending on
575 * <server> boolean value which must be set to 1 for a server (haproxy listener)
576 * or 0 for a client (connection to a haproxy server).
577 * Returns 1 if succeeded, 0 if not.
578 */
579static int quic_transport_params_decode(struct quic_transport_params *p, int server,
580 const unsigned char *buf,
581 const unsigned char *end)
582{
583 const unsigned char *pos;
584
585 pos = buf;
586
587 while (pos != end) {
588 uint64_t type, len;
589
590 if (!quic_transport_param_decode_type_len(&type, &len, &pos, end))
591 return 0;
592
593 if (end - pos < len)
594 return 0;
595
596 if (!quic_transport_param_decode(p, server, type, &pos, len))
597 return 0;
598 }
599
600 /*
601 * A server MUST send original_destination_connection_id transport parameter.
602 * initial_source_connection_id must be present both for server and client.
603 */
604 if ((server && !p->original_destination_connection_id_present) ||
605 !p->initial_source_connection_id_present)
606 return 0;
607
608 return 1;
609}
610
611/* Store transport parameters found in <buf> buffer into <qc> QUIC connection
612 * depending on <server> value which must be 1 for a server (haproxy listener)
613 * or 0 for a client (connection to a haproxy server).
614 * Note that peer transport parameters are stored in the TX part of the connection:
615 * they are used to send packets to the peer with its transport parameters as
616 * limitations.
617 * Returns 1 if succeeded, 0 if not.
618 */
619int quic_transport_params_store(struct quic_conn *qc, int server,
620 const unsigned char *buf,
621 const unsigned char *end)
622{
623 struct quic_transport_params *tx_params = &qc->tx.params;
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200624
625 /* initialize peer TPs to RFC default value */
626 quic_dflt_transport_params_cpy(tx_params);
627
628 if (!quic_transport_params_decode(tx_params, server, buf, end))
629 return 0;
630
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200631 return 1;
632}
633
634/* QUIC server (or haproxy listener) only function.
635 * Initialize the local transport parameters <rx_params> from <listener_params>
636 * coming from configuration and Initial packet information (destintation
637 * connection ID, source connection ID, original destination connection ID,
638 * and if a token was present denoted by <token> boolean value.
639 * Returns 1 if succeeded, 0 if not.
640 */
641int qc_lstnr_params_init(struct quic_conn *qc,
642 const struct quic_transport_params *listener_params,
643 const unsigned char *stateless_reset_token,
644 const unsigned char *dcid, size_t dcidlen,
645 const unsigned char *scid, size_t scidlen,
646 const unsigned char *odcid, size_t odcidlen, int token)
647{
648 struct quic_transport_params *rx_params = &qc->rx.params;
649 struct tp_cid *odcid_param = &rx_params->original_destination_connection_id;
650
651 /* Copy the transport parameters. */
652 *rx_params = *listener_params;
653 /* Copy the stateless reset token */
654 memcpy(rx_params->stateless_reset_token, stateless_reset_token,
655 sizeof rx_params->stateless_reset_token);
656 /* Copy original_destination_connection_id transport parameter. */
657 if (token) {
658 memcpy(odcid_param->data, odcid, odcidlen);
659 odcid_param->len = odcidlen;
660 /* Copy retry_source_connection_id transport parameter. */
661 memcpy(rx_params->retry_source_connection_id.data, dcid, dcidlen);
662 rx_params->retry_source_connection_id.len = dcidlen;
663 }
664 else {
665 memcpy(odcid_param->data, dcid, dcidlen);
666 odcid_param->len = dcidlen;
667 }
668
669 /* Copy the initial source connection ID. */
670 memcpy(rx_params->initial_source_connection_id.data, scid, scidlen);
671 rx_params->initial_source_connection_id.len = scidlen;
Frédéric Lécaillec7785b52022-05-23 09:08:54 +0200672 TRACE_PROTO("\nRX(local) transp. params.", QUIC_EV_TRANSP_PARAMS, qc, rx_params);
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200673
674 return 1;
675}
676