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