blob: 69c654114a277063d8cc938ffaa6b508634473e2 [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
158/* Decode into <p> struct a transport parameter found in <*buf> buffer with
159 * <type> as type and <len> as length, depending on <server> boolean value which
160 * must be set to 1 for a server (haproxy listener) or 0 for a client (connection
161 * to an haproxy server).
162 */
163static int quic_transport_param_decode(struct quic_transport_params *p,
164 int server, uint64_t type,
165 const unsigned char **buf, size_t len)
166{
167 const unsigned char *end = *buf + len;
168
169 switch (type) {
170 case QUIC_TP_ORIGINAL_DESTINATION_CONNECTION_ID:
171 if (!server || len > sizeof p->original_destination_connection_id.data)
172 return 0;
173
174 if (len)
175 memcpy(p->original_destination_connection_id.data, *buf, len);
176 p->original_destination_connection_id.len = len;
177 *buf += len;
178 p->original_destination_connection_id_present = 1;
179 break;
180 case QUIC_TP_INITIAL_SOURCE_CONNECTION_ID:
181 if (len > sizeof p->initial_source_connection_id.data)
182 return 0;
183
184 if (len)
185 memcpy(p->initial_source_connection_id.data, *buf, len);
186 p->initial_source_connection_id.len = len;
187 *buf += len;
188 p->initial_source_connection_id_present = 1;
189 break;
190 case QUIC_TP_STATELESS_RESET_TOKEN:
191 if (!server || len != sizeof p->stateless_reset_token)
192 return 0;
193 memcpy(p->stateless_reset_token, *buf, len);
194 *buf += len;
195 p->with_stateless_reset_token = 1;
196 break;
197 case QUIC_TP_PREFERRED_ADDRESS:
198 if (!server)
199 return 0;
200 if (!quic_transport_param_dec_pref_addr(&p->preferred_address, buf, *buf + len))
201 return 0;
202 p->with_preferred_address = 1;
203 break;
204 case QUIC_TP_MAX_IDLE_TIMEOUT:
205 if (!quic_dec_int(&p->max_idle_timeout, buf, end))
206 return 0;
207 break;
208 case QUIC_TP_MAX_UDP_PAYLOAD_SIZE:
209 if (!quic_dec_int(&p->max_udp_payload_size, buf, end))
210 return 0;
211 break;
212 case QUIC_TP_INITIAL_MAX_DATA:
213 if (!quic_dec_int(&p->initial_max_data, buf, end))
214 return 0;
215 break;
216 case QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
217 if (!quic_dec_int(&p->initial_max_stream_data_bidi_local, buf, end))
218 return 0;
219 break;
220 case QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
221 if (!quic_dec_int(&p->initial_max_stream_data_bidi_remote, buf, end))
222 return 0;
223 break;
224 case QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI:
225 if (!quic_dec_int(&p->initial_max_stream_data_uni, buf, end))
226 return 0;
227 break;
228 case QUIC_TP_INITIAL_MAX_STREAMS_BIDI:
229 if (!quic_dec_int(&p->initial_max_streams_bidi, buf, end))
230 return 0;
231 break;
232 case QUIC_TP_INITIAL_MAX_STREAMS_UNI:
233 if (!quic_dec_int(&p->initial_max_streams_uni, buf, end))
234 return 0;
235 break;
236 case QUIC_TP_ACK_DELAY_EXPONENT:
237 if (!quic_dec_int(&p->ack_delay_exponent, buf, end) ||
238 p->ack_delay_exponent > QUIC_TP_ACK_DELAY_EXPONENT_LIMIT)
239 return 0;
240 break;
241 case QUIC_TP_MAX_ACK_DELAY:
242 if (!quic_dec_int(&p->max_ack_delay, buf, end) ||
243 p->max_ack_delay > QUIC_TP_MAX_ACK_DELAY_LIMIT)
244 return 0;
245 break;
246 case QUIC_TP_DISABLE_ACTIVE_MIGRATION:
247 /* Zero-length parameter type. */
248 if (len != 0)
249 return 0;
250 p->disable_active_migration = 1;
251 break;
252 case QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT:
253 if (!quic_dec_int(&p->active_connection_id_limit, buf, end))
254 return 0;
255 break;
256 default:
257 *buf += len;
258 };
259
260 return *buf == end;
261}
262
263/* Encode <type> and <len> variable length values in <buf>.
264 * Returns 1 if succeeded, 0 if not.
265 */
266static int quic_transport_param_encode_type_len(unsigned char **buf,
267 const unsigned char *end,
268 uint64_t type, uint64_t len)
269{
270 return quic_enc_int(buf, end, type) && quic_enc_int(buf, end, len);
271}
272
273/* Decode variable length type and length values of a QUIC transport parameter
274 * into <type> and <len> found in <*buf> buffer.
275 * Returns 1 if succeeded, 0 if not.
276 */
277static int quic_transport_param_decode_type_len(uint64_t *type, uint64_t *len,
278 const unsigned char **buf,
279 const unsigned char *end)
280{
281 return quic_dec_int(type, buf, end) && quic_dec_int(len, buf, end);
282}
283
284/* Encode <param> bytes stream with <type> as type and <length> as length into buf.
285 * Returns 1 if succeeded, 0 if not.
286 */
287static int quic_transport_param_enc_mem(unsigned char **buf, const unsigned char *end,
288 uint64_t type, void *param, uint64_t length)
289{
290 if (!quic_transport_param_encode_type_len(buf, end, type, length))
291 return 0;
292
293 if (end - *buf < length)
294 return 0;
295
296 if (length)
297 memcpy(*buf, param, length);
298 *buf += length;
299
300 return 1;
301}
302
303/* Encode <val> 64-bits value as variable length integer into <buf>.
304 * Returns 1 if succeeded, 0 if not.
305 */
306static int quic_transport_param_enc_int(unsigned char **buf,
307 const unsigned char *end,
308 uint64_t type, uint64_t val)
309{
310 size_t len;
311
312 len = quic_int_getsize(val);
313
314 return len && quic_transport_param_encode_type_len(buf, end, type, len) &&
315 quic_enc_int(buf, end, val);
316}
317
318/* Returns the required length in bytes to encode <cid> QUIC connection ID. */
319static inline size_t sizeof_quic_cid(const struct tp_cid *cid)
320{
321 return sizeof cid->len + cid->len;
322}
323
324/* Encode <addr> preferred address into <buf>.
325 * Note that the IP addresses must be encoded in network byte order.
326 * So ->ipv4_addr and ->ipv6_addr, which are buffers, must contained
327 * values already encoded in network byte order.
328 * Returns 1 if succeeded, 0 if not.
329 */
330static int quic_transport_param_enc_pref_addr(unsigned char **buf,
331 const unsigned char *end,
332 struct tp_preferred_address *addr)
333{
334 uint64_t addr_len = 0;
335
336 addr_len += sizeof addr->ipv4_port + sizeof addr->ipv4_addr;
337 addr_len += sizeof addr->ipv6_port + sizeof addr->ipv6_addr;
338 addr_len += sizeof_quic_cid(&addr->cid);
339 addr_len += sizeof addr->stateless_reset_token;
340
341 if (!quic_transport_param_encode_type_len(buf, end, QUIC_TP_PREFERRED_ADDRESS, addr_len))
342 return 0;
343
344 if (end - *buf < addr_len)
345 return 0;
346
347 quic_transport_param_enc_pref_addr_val(buf, end, addr);
348
349 return 1;
350}
351
352/* Encode <p> transport parameter into <buf> depending on <server> value which
353 * must be set to 1 for a server (haproxy listener) or 0 for a client
354 * (connection to a haproxy server).
355 * Return the number of bytes consumed if succeeded, 0 if not.
356 */
357int quic_transport_params_encode(unsigned char *buf,
358 const unsigned char *end,
359 struct quic_transport_params *p,
360 int server)
361{
362 unsigned char *head;
363 unsigned char *pos;
364
365 head = pos = buf;
366 if (server) {
367 if (!quic_transport_param_enc_mem(&pos, end,
368 QUIC_TP_ORIGINAL_DESTINATION_CONNECTION_ID,
369 p->original_destination_connection_id.data,
370 p->original_destination_connection_id.len))
371 return 0;
372
373 if (p->retry_source_connection_id.len) {
374 if (!quic_transport_param_enc_mem(&pos, end,
375 QUIC_TP_RETRY_SOURCE_CONNECTION_ID,
376 p->retry_source_connection_id.data,
377 p->retry_source_connection_id.len))
378 return 0;
379 }
380
381 if (p->with_stateless_reset_token &&
382 !quic_transport_param_enc_mem(&pos, end, QUIC_TP_STATELESS_RESET_TOKEN,
383 p->stateless_reset_token,
384 sizeof p->stateless_reset_token))
385 return 0;
386 if (p->with_preferred_address &&
387 !quic_transport_param_enc_pref_addr(&pos, end, &p->preferred_address))
388 return 0;
389 }
390
391 if (!quic_transport_param_enc_mem(&pos, end,
392 QUIC_TP_INITIAL_SOURCE_CONNECTION_ID,
393 p->initial_source_connection_id.data,
394 p->initial_source_connection_id.len))
395 return 0;
396
397 if (p->max_idle_timeout &&
398 !quic_transport_param_enc_int(&pos, end, QUIC_TP_MAX_IDLE_TIMEOUT, p->max_idle_timeout))
399 return 0;
400
401 /*
402 * "max_packet_size" transport parameter must be transmitted only if different
403 * of the default value.
404 */
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200405 if (p->max_udp_payload_size != QUIC_TP_DFLT_MAX_UDP_PAYLOAD_SIZE &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200406 !quic_transport_param_enc_int(&pos, end, QUIC_TP_MAX_UDP_PAYLOAD_SIZE, p->max_udp_payload_size))
407 return 0;
408
409 if (p->initial_max_data &&
410 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_DATA, p->initial_max_data))
411 return 0;
412
413 if (p->initial_max_stream_data_bidi_local &&
414 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
415 p->initial_max_stream_data_bidi_local))
416 return 0;
417
418 if (p->initial_max_stream_data_bidi_remote &&
419 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
420 p->initial_max_stream_data_bidi_remote))
421 return 0;
422
423 if (p->initial_max_stream_data_uni &&
424 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI,
425 p->initial_max_stream_data_uni))
426 return 0;
427
428 if (p->initial_max_streams_bidi &&
429 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAMS_BIDI,
430 p->initial_max_streams_bidi))
431 return 0;
432
433 if (p->initial_max_streams_uni &&
434 !quic_transport_param_enc_int(&pos, end, QUIC_TP_INITIAL_MAX_STREAMS_UNI,
435 p->initial_max_streams_uni))
436 return 0;
437
438 /*
439 * "ack_delay_exponent" transport parameter must be transmitted only if different
440 * of the default value.
441 */
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200442 if (p->ack_delay_exponent != QUIC_TP_DFLT_ACK_DELAY_COMPONENT &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200443 !quic_transport_param_enc_int(&pos, end, QUIC_TP_ACK_DELAY_EXPONENT, p->ack_delay_exponent))
444 return 0;
445
446 /*
447 * "max_ack_delay" transport parameter must be transmitted only if different
448 * of the default value.
449 */
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200450 if (p->max_ack_delay != QUIC_TP_DFLT_MAX_ACK_DELAY &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200451 !quic_transport_param_enc_int(&pos, end, QUIC_TP_MAX_ACK_DELAY, p->max_ack_delay))
452 return 0;
453
454 /* 0-length value */
455 if (p->disable_active_migration &&
456 !quic_transport_param_encode_type_len(&pos, end, QUIC_TP_DISABLE_ACTIVE_MIGRATION, 0))
457 return 0;
458
459 if (p->active_connection_id_limit &&
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200460 p->active_connection_id_limit != QUIC_TP_DFLT_ACTIVE_CONNECTION_ID_LIMIT &&
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200461 !quic_transport_param_enc_int(&pos, end, QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT,
462 p->active_connection_id_limit))
463 return 0;
464
465 return pos - head;
466}
467
468/* Decode transport parameters found in <buf> buffer into <p>, depending on
469 * <server> boolean value which must be set to 1 for a server (haproxy listener)
470 * or 0 for a client (connection to a haproxy server).
471 * Returns 1 if succeeded, 0 if not.
472 */
473static int quic_transport_params_decode(struct quic_transport_params *p, int server,
474 const unsigned char *buf,
475 const unsigned char *end)
476{
477 const unsigned char *pos;
478
479 pos = buf;
480
481 while (pos != end) {
482 uint64_t type, len;
483
484 if (!quic_transport_param_decode_type_len(&type, &len, &pos, end))
485 return 0;
486
487 if (end - pos < len)
488 return 0;
489
490 if (!quic_transport_param_decode(p, server, type, &pos, len))
491 return 0;
492 }
493
494 /*
495 * A server MUST send original_destination_connection_id transport parameter.
496 * initial_source_connection_id must be present both for server and client.
497 */
498 if ((server && !p->original_destination_connection_id_present) ||
499 !p->initial_source_connection_id_present)
500 return 0;
501
502 return 1;
503}
504
505/* Store transport parameters found in <buf> buffer into <qc> QUIC connection
506 * depending on <server> value which must be 1 for a server (haproxy listener)
507 * or 0 for a client (connection to a haproxy server).
508 * Note that peer transport parameters are stored in the TX part of the connection:
509 * they are used to send packets to the peer with its transport parameters as
510 * limitations.
511 * Returns 1 if succeeded, 0 if not.
512 */
513int quic_transport_params_store(struct quic_conn *qc, int server,
514 const unsigned char *buf,
515 const unsigned char *end)
516{
517 struct quic_transport_params *tx_params = &qc->tx.params;
518 struct quic_transport_params *rx_params = &qc->rx.params;
519
520 /* initialize peer TPs to RFC default value */
521 quic_dflt_transport_params_cpy(tx_params);
522
523 if (!quic_transport_params_decode(tx_params, server, buf, end))
524 return 0;
525
526 if (tx_params->max_ack_delay)
527 qc->max_ack_delay = tx_params->max_ack_delay;
528
529 if (tx_params->max_idle_timeout && rx_params->max_idle_timeout)
530 qc->max_idle_timeout =
531 QUIC_MIN(tx_params->max_idle_timeout, rx_params->max_idle_timeout);
532 else
533 qc->max_idle_timeout =
534 QUIC_MAX(tx_params->max_idle_timeout, rx_params->max_idle_timeout);
535
Frédéric Lécaillec7785b52022-05-23 09:08:54 +0200536 TRACE_PROTO("\nTX(remote) transp. params.", QUIC_EV_TRANSP_PARAMS, qc, tx_params);
537
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200538 return 1;
539}
540
541/* QUIC server (or haproxy listener) only function.
542 * Initialize the local transport parameters <rx_params> from <listener_params>
543 * coming from configuration and Initial packet information (destintation
544 * connection ID, source connection ID, original destination connection ID,
545 * and if a token was present denoted by <token> boolean value.
546 * Returns 1 if succeeded, 0 if not.
547 */
548int qc_lstnr_params_init(struct quic_conn *qc,
549 const struct quic_transport_params *listener_params,
550 const unsigned char *stateless_reset_token,
551 const unsigned char *dcid, size_t dcidlen,
552 const unsigned char *scid, size_t scidlen,
553 const unsigned char *odcid, size_t odcidlen, int token)
554{
555 struct quic_transport_params *rx_params = &qc->rx.params;
556 struct tp_cid *odcid_param = &rx_params->original_destination_connection_id;
557
558 /* Copy the transport parameters. */
559 *rx_params = *listener_params;
560 /* Copy the stateless reset token */
561 memcpy(rx_params->stateless_reset_token, stateless_reset_token,
562 sizeof rx_params->stateless_reset_token);
563 /* Copy original_destination_connection_id transport parameter. */
564 if (token) {
565 memcpy(odcid_param->data, odcid, odcidlen);
566 odcid_param->len = odcidlen;
567 /* Copy retry_source_connection_id transport parameter. */
568 memcpy(rx_params->retry_source_connection_id.data, dcid, dcidlen);
569 rx_params->retry_source_connection_id.len = dcidlen;
570 }
571 else {
572 memcpy(odcid_param->data, dcid, dcidlen);
573 odcid_param->len = dcidlen;
574 }
575
576 /* Copy the initial source connection ID. */
577 memcpy(rx_params->initial_source_connection_id.data, scid, scidlen);
578 rx_params->initial_source_connection_id.len = scidlen;
Frédéric Lécaillec7785b52022-05-23 09:08:54 +0200579 TRACE_PROTO("\nRX(local) transp. params.", QUIC_EV_TRANSP_PARAMS, qc, rx_params);
Frédéric Lécaille748ece62022-05-21 23:58:40 +0200580
581 return 1;
582}
583