lsquic_trans_params.c revision 10e0dad8
1/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_trans_params.c
4 */
5
6#include <assert.h>
7#include <errno.h>
8#include <inttypes.h>
9#include <limits.h>
10#include <stddef.h>
11#include <stdint.h>
12#include <string.h>
13
14#ifndef WIN32
15#include <arpa/inet.h>
16#include <sys/socket.h>
17#else
18#include "vc_compat.h"
19#include "Ws2tcpip.h"
20#endif
21
22#include "lsquic_byteswap.h"
23#include "lsquic_int_types.h"
24#include "lsquic_types.h"
25#include "lsquic_version.h"
26#include "lsquic_sizes.h"
27#include "lsquic_trans_params.h"
28#include "lsquic_util.h"
29#include "lsquic_varint.h"
30
31#define LSQUIC_LOGGER_MODULE LSQLM_TRAPA
32#include "lsquic_logger.h"
33
34
35static enum transport_param_id
36tpi_val_2_enum (uint64_t tpi_val)
37{
38    switch (tpi_val)
39    {
40    case 0:         return TPI_ORIGINAL_DEST_CID;
41    case 1:         return TPI_MAX_IDLE_TIMEOUT;
42    case 2:         return TPI_STATELESS_RESET_TOKEN;
43    case 3:         return TPI_MAX_UDP_PAYLOAD_SIZE;
44    case 4:         return TPI_INIT_MAX_DATA;
45    case 5:         return TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL;
46    case 6:         return TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE;
47    case 7:         return TPI_INIT_MAX_STREAM_DATA_UNI;
48    case 8:         return TPI_INIT_MAX_STREAMS_BIDI;
49    case 9:         return TPI_INIT_MAX_STREAMS_UNI;
50    case 10:        return TPI_ACK_DELAY_EXPONENT;
51    case 11:        return TPI_MAX_ACK_DELAY;
52    case 12:        return TPI_DISABLE_ACTIVE_MIGRATION;
53    case 13:        return TPI_PREFERRED_ADDRESS;
54    case 14:        return TPI_ACTIVE_CONNECTION_ID_LIMIT;
55    case 15:        return TPI_INITIAL_SOURCE_CID;
56    case 16:        return TPI_RETRY_SOURCE_CID;
57    case 0x20:      return TPI_MAX_DATAGRAM_FRAME_SIZE;
58#if LSQUIC_TEST_QUANTUM_READINESS
59    case 0xC37:     return TPI_QUANTUM_READINESS;
60#endif
61    case 0x1057:    return TPI_LOSS_BITS;
62    case 0x2AB2:    return TPI_GREASE_QUIC_BIT;
63    case 0xDE1A:    return TPI_MIN_ACK_DELAY;
64    case 0xFF02DE1A:return TPI_MIN_ACK_DELAY_02;
65    case 0x7158:    return TPI_TIMESTAMPS;
66    default:        return INT_MAX;
67    }
68}
69
70
71static const unsigned enum_2_tpi_val[LAST_TPI + 1] =
72{
73    [TPI_ORIGINAL_DEST_CID]                 =  0x0,
74    [TPI_MAX_IDLE_TIMEOUT]                  =  0x1,
75    [TPI_STATELESS_RESET_TOKEN]             =  0x2,
76    [TPI_MAX_UDP_PAYLOAD_SIZE]              =  0x3,
77    [TPI_INIT_MAX_DATA]                     =  0x4,
78    [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL]   =  0x5,
79    [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE]  =  0x6,
80    [TPI_INIT_MAX_STREAM_DATA_UNI]          =  0x7,
81    [TPI_INIT_MAX_STREAMS_BIDI]             =  0x8,
82    [TPI_INIT_MAX_STREAMS_UNI]              =  0x9,
83    [TPI_ACK_DELAY_EXPONENT]                =  0xA,
84    [TPI_MAX_ACK_DELAY]                     =  0xB,
85    [TPI_DISABLE_ACTIVE_MIGRATION]          =  0xC,
86    [TPI_PREFERRED_ADDRESS]                 =  0xD,
87    [TPI_ACTIVE_CONNECTION_ID_LIMIT]        =  0xE,
88    [TPI_INITIAL_SOURCE_CID]                =  0xF,
89    [TPI_RETRY_SOURCE_CID]                  =  0x10,
90    [TPI_MAX_DATAGRAM_FRAME_SIZE]           =  0x20,
91#if LSQUIC_TEST_QUANTUM_READINESS
92    [TPI_QUANTUM_READINESS]                 =  0xC37,
93#endif
94    [TPI_LOSS_BITS]                         =  0x1057,
95    [TPI_MIN_ACK_DELAY]                     =  0xDE1A,
96    [TPI_MIN_ACK_DELAY_02]                  =  0xFF02DE1A,
97    [TPI_TIMESTAMPS]                        =  0x7158,
98    [TPI_GREASE_QUIC_BIT]                   =  0x2AB2,
99};
100
101
102const char * const lsquic_tpi2str[LAST_TPI + 1] =
103{
104    [TPI_ORIGINAL_DEST_CID]                 =  "original_destination_connection_id",
105    [TPI_MAX_IDLE_TIMEOUT]                  =  "max_idle_timeout",
106    [TPI_STATELESS_RESET_TOKEN]             =  "stateless_reset_token",
107    [TPI_MAX_UDP_PAYLOAD_SIZE]              =  "max_udp_payload_size",
108    [TPI_INIT_MAX_DATA]                     =  "init_max_data",
109    [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL]   =  "init_max_stream_data_bidi_local",
110    [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE]  =  "init_max_stream_data_bidi_remote",
111    [TPI_INIT_MAX_STREAM_DATA_UNI]          =  "init_max_stream_data_uni",
112    [TPI_INIT_MAX_STREAMS_BIDI]             =  "init_max_streams_bidi",
113    [TPI_INIT_MAX_STREAMS_UNI]              =  "init_max_streams_uni",
114    [TPI_ACK_DELAY_EXPONENT]                =  "ack_delay_exponent",
115    [TPI_MAX_ACK_DELAY]                     =  "max_ack_delay",
116    [TPI_DISABLE_ACTIVE_MIGRATION]          =  "disable_active_migration",
117    [TPI_PREFERRED_ADDRESS]                 =  "preferred_address",
118    [TPI_ACTIVE_CONNECTION_ID_LIMIT]        =  "active_connection_id_limit",
119    [TPI_INITIAL_SOURCE_CID]                =  "initial_source_connection_id",
120    [TPI_RETRY_SOURCE_CID]                  =  "retry_source_connection_id",
121    [TPI_MAX_DATAGRAM_FRAME_SIZE]           =  "max_datagram_frame_size",
122#if LSQUIC_TEST_QUANTUM_READINESS
123    [TPI_QUANTUM_READINESS]                 =  "quantum_readiness",
124#endif
125    [TPI_LOSS_BITS]                         =  "loss_bits",
126    [TPI_MIN_ACK_DELAY]                     =  "min_ack_delay",
127    [TPI_MIN_ACK_DELAY_02]                  =  "min_ack_delay_02",
128    [TPI_TIMESTAMPS]                        =  "timestamps",
129    [TPI_GREASE_QUIC_BIT]                   =  "grease_quic_bit",
130};
131#define tpi2str lsquic_tpi2str
132
133
134static const uint64_t def_vals[MAX_NUM_WITH_DEF_TPI + 1] =
135{
136    [TPI_MAX_UDP_PAYLOAD_SIZE]              =  TP_DEF_MAX_UDP_PAYLOAD_SIZE,
137    [TPI_ACK_DELAY_EXPONENT]                =  TP_DEF_ACK_DELAY_EXP,
138    [TPI_INIT_MAX_STREAMS_UNI]              =  TP_DEF_INIT_MAX_STREAMS_UNI,
139    [TPI_INIT_MAX_STREAMS_BIDI]             =  TP_DEF_INIT_MAX_STREAMS_BIDI,
140    [TPI_INIT_MAX_DATA]                     =  TP_DEF_INIT_MAX_DATA,
141    [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL]   =  TP_DEF_INIT_MAX_STREAM_DATA_BIDI_LOCAL,
142    [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE]  =  TP_DEF_INIT_MAX_STREAM_DATA_BIDI_REMOTE,
143    [TPI_INIT_MAX_STREAM_DATA_UNI]          =  TP_DEF_INIT_MAX_STREAM_DATA_UNI,
144    [TPI_MAX_IDLE_TIMEOUT]                  =  TP_DEF_MAX_IDLE_TIMEOUT,
145    [TPI_MAX_ACK_DELAY]                     =  TP_DEF_MAX_ACK_DELAY,
146    [TPI_ACTIVE_CONNECTION_ID_LIMIT]        =  TP_DEF_ACTIVE_CONNECTION_ID_LIMIT,
147};
148
149
150static const uint64_t max_vals[MAX_NUMERIC_TPI + 1] =
151{
152    /* We don't enforce the maximum practical UDP payload value of 65527, as
153     * it is not required by the spec and is not necessary.
154     */
155    [TPI_MAX_UDP_PAYLOAD_SIZE]              =  VINT_MAX_VALUE,
156    [TPI_ACK_DELAY_EXPONENT]                =  TP_MAX_ACK_DELAY_EXP,
157    [TPI_INIT_MAX_STREAMS_UNI]              =  1ull << 60,
158    [TPI_INIT_MAX_STREAMS_BIDI]             =  1ull << 60,
159    [TPI_INIT_MAX_DATA]                     =  VINT_MAX_VALUE,
160    [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL]   =  VINT_MAX_VALUE,
161    [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE]  =  VINT_MAX_VALUE,
162    [TPI_INIT_MAX_STREAM_DATA_UNI]          =  VINT_MAX_VALUE,
163    [TPI_MAX_IDLE_TIMEOUT]                  =  VINT_MAX_VALUE,
164    [TPI_MAX_ACK_DELAY]                     =  TP_MAX_MAX_ACK_DELAY,
165    [TPI_ACTIVE_CONNECTION_ID_LIMIT]        =  VINT_MAX_VALUE,
166    [TPI_LOSS_BITS]                         =  1,
167    [TPI_MIN_ACK_DELAY]                     =  (1u << 24) - 1u,
168    [TPI_MIN_ACK_DELAY_02]                  =  (1u << 24) - 1u,
169    [TPI_TIMESTAMPS]                        =  TS_WANT_THEM|TS_GENERATE_THEM,
170    [TPI_MAX_DATAGRAM_FRAME_SIZE]           =  VINT_MAX_VALUE,
171};
172
173
174static const uint64_t min_vals[MAX_NUMERIC_TPI + 1] =
175{
176    /* On the other hand, we do enforce the lower bound. */
177    [TPI_MAX_UDP_PAYLOAD_SIZE]              =  1200,
178    [TPI_MIN_ACK_DELAY]                     =  1,
179    [TPI_MIN_ACK_DELAY_02]                  =  1,
180    [TPI_ACTIVE_CONNECTION_ID_LIMIT]        =  2,
181    [TPI_TIMESTAMPS]                        =  TS_WANT_THEM,
182};
183
184
185static size_t
186preferred_address_size (const struct transport_params *params)
187{
188    return sizeof(params->tp_preferred_address.ipv4_addr)
189         + sizeof(params->tp_preferred_address.ipv4_port)
190         + sizeof(params->tp_preferred_address.ipv6_addr)
191         + sizeof(params->tp_preferred_address.ipv6_port)
192         + 1 + params->tp_preferred_address.cid.len
193         + sizeof(params->tp_preferred_address.srst)
194         ;
195}
196
197
198int
199lsquic_tp_has_pref_ipv4 (const struct transport_params *params)
200{
201    return (params->tp_set & (1 << TPI_PREFERRED_ADDRESS))
202        && params->tp_preferred_address.ipv4_port
203        && !lsquic_is_zero(params->tp_preferred_address.ipv4_addr,
204                    sizeof(params->tp_preferred_address.ipv4_addr));
205}
206
207
208int
209lsquic_tp_has_pref_ipv6 (const struct transport_params *params)
210{
211    return (params->tp_set & (1 << TPI_PREFERRED_ADDRESS))
212        && params->tp_preferred_address.ipv6_port
213        && !lsquic_is_zero(params->tp_preferred_address.ipv6_addr,
214                    sizeof(params->tp_preferred_address.ipv6_addr));
215}
216
217
218#if LSQUIC_TEST_QUANTUM_READINESS
219#include <stdlib.h>
220size_t
221lsquic_tp_get_quantum_sz (void)
222{
223    const char *str;
224
225    str = getenv("LSQUIC_QUANTUM_SZ");
226    if (str)
227        return atoi(str);
228    else
229        /* https://github.com/quicwg/base-drafts/wiki/Quantum-Readiness-test */
230        return 1200;
231}
232#endif
233
234
235static size_t
236update_cid_bits (unsigned bits[][3], enum transport_param_id tpi,
237                                                    const lsquic_cid_t *cid)
238{
239    bits[tpi][0] = vint_val2bits(enum_2_tpi_val[tpi]);
240#if __GNUC__
241#pragma GCC diagnostic ignored "-Wunknown-pragmas"
242#if __clang__
243#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
244#else
245#pragma GCC diagnostic ignored "-Wtype-limits"
246#endif
247#endif
248    bits[tpi][1] = vint_val2bits(cid->len);
249#if __GNUC__
250#pragma GCC diagnostic pop
251#pragma GCC diagnostic pop
252#endif
253    return (1u << bits[tpi][0]) + (1u << bits[tpi][1]) + cid->len;
254}
255
256
257int
258lsquic_tp_encode (const struct transport_params *params, int is_server,
259                  unsigned char *const buf, size_t bufsz)
260{
261    unsigned char *p;
262    size_t need;
263    uint16_t u16;
264    enum transport_param_id tpi;
265    unsigned set;
266    unsigned bits[LAST_TPI + 1][3 /* ID, length, value */];
267#if LSQUIC_TEST_QUANTUM_READINESS
268    const size_t quantum_sz = lsquic_tp_get_quantum_sz();
269#endif
270
271    need = 0;
272    set = params->tp_set;   /* Will turn bits off for default values */
273
274    if (set & (1 << TPI_INITIAL_SOURCE_CID))
275        need += update_cid_bits(bits, TPI_INITIAL_SOURCE_CID,
276                                            &params->tp_initial_source_cid);
277    if (is_server)
278    {
279        if (set & (1 << TPI_ORIGINAL_DEST_CID))
280            need += update_cid_bits(bits, TPI_ORIGINAL_DEST_CID,
281                                                &params->tp_original_dest_cid);
282        if (set & (1 << TPI_RETRY_SOURCE_CID))
283            need += update_cid_bits(bits, TPI_RETRY_SOURCE_CID,
284                                                &params->tp_retry_source_cid);
285        if (set & (1 << TPI_STATELESS_RESET_TOKEN))
286        {
287            bits[TPI_STATELESS_RESET_TOKEN][0]
288                    = vint_val2bits(enum_2_tpi_val[TPI_STATELESS_RESET_TOKEN]);
289            bits[TPI_STATELESS_RESET_TOKEN][1]
290                    = vint_val2bits(sizeof(params->tp_stateless_reset_token));
291            need += (1 << bits[TPI_STATELESS_RESET_TOKEN][0])
292                 +  (1 << bits[TPI_STATELESS_RESET_TOKEN][1])
293                 +  sizeof(params->tp_stateless_reset_token);
294        }
295        if (set & (1 << TPI_PREFERRED_ADDRESS))
296        {
297            bits[TPI_PREFERRED_ADDRESS][0]
298                    = vint_val2bits(enum_2_tpi_val[TPI_PREFERRED_ADDRESS]);
299            bits[TPI_PREFERRED_ADDRESS][1] = vint_val2bits(
300                                            preferred_address_size(params));
301            need += (1 << bits[TPI_PREFERRED_ADDRESS][0])
302                 +  (1 << bits[TPI_PREFERRED_ADDRESS][1])
303                 +  preferred_address_size(params);
304        }
305    }
306#if LSQUIC_TEST_QUANTUM_READINESS
307    if (set & (1 << TPI_QUANTUM_READINESS))
308    {
309        bits[TPI_QUANTUM_READINESS][0]
310                = vint_val2bits(enum_2_tpi_val[TPI_QUANTUM_READINESS]);
311        bits[TPI_QUANTUM_READINESS][1] = vint_val2bits(quantum_sz);
312        need += (1 << bits[TPI_QUANTUM_READINESS][0])
313             +  (1 << bits[TPI_QUANTUM_READINESS][1])
314             +  quantum_sz;
315    }
316#endif
317
318    for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
319        if (set & (1 << tpi))
320        {
321            if (tpi > MAX_NUM_WITH_DEF_TPI
322                        || params->tp_numerics[tpi] != def_vals[tpi])
323            {
324                if (params->tp_numerics[tpi] >= min_vals[tpi]
325                                && params->tp_numerics[tpi] <= max_vals[tpi])
326                {
327                    bits[tpi][0] = vint_val2bits(enum_2_tpi_val[tpi]);
328                    bits[tpi][2] = vint_val2bits(params->tp_numerics[tpi]);
329                    bits[tpi][1] = vint_val2bits(bits[tpi][2]);
330                    need += (1 << bits[tpi][0])
331                         +  (1 << bits[tpi][1])
332                         +  (1 << bits[tpi][2]);
333                }
334                else if (params->tp_numerics[tpi] > max_vals[tpi])
335                {
336                    LSQ_DEBUG("numeric value of %s is too large (%"PRIu64" vs "
337                        "maximum of %"PRIu64")", tpi2str[tpi],
338                        params->tp_numerics[tpi], max_vals[tpi]);
339                    return -1;
340                }
341                else
342                {
343                    LSQ_DEBUG("numeric value of %s is too small (%"PRIu64" vs "
344                        "minimum " "of %"PRIu64")",
345                        tpi2str[tpi], params->tp_numerics[tpi], min_vals[tpi]);
346                    return -1;
347                }
348            }
349            else
350                set &= ~(1 << tpi);     /* Don't write default value */
351        }
352
353    for (; tpi <= MAX_EMPTY_TPI; ++tpi)
354        if (set & (1 << tpi))
355        {
356            bits[tpi][0] = vint_val2bits(enum_2_tpi_val[tpi]);
357            need += (1 << bits[tpi][0]) + 1 /* Zero length byte */;
358        }
359
360    if (need > bufsz || need > UINT16_MAX)
361    {
362        errno = ENOBUFS;
363        return -1;
364    }
365
366    p = buf;
367
368#define WRITE_TO_P(src, len) do {                                       \
369    memcpy(p, src, len);                                                \
370    p += len;                                                           \
371} while (0)
372
373#if __BYTE_ORDER == __LITTLE_ENDIAN
374#define WRITE_UINT_TO_P(val, width) do {                                \
375    u##width = bswap_##width(val);                                      \
376    WRITE_TO_P(&u##width, sizeof(u##width));                            \
377} while (0)
378#else
379#define WRITE_UINT_TO_P(val, width) do {                                \
380    u##width = val;                                                     \
381    WRITE_TO_P(&u##width, sizeof(u##width));                            \
382} while (0)
383#endif
384
385    for (tpi = 0; tpi <= LAST_TPI; ++tpi)
386        if (set & (1 << tpi))
387        {
388            vint_write(p, enum_2_tpi_val[tpi], bits[tpi][0],
389                                                        1 << bits[tpi][0]);
390            p += 1 << bits[tpi][0];
391            switch (tpi)
392            {
393            case TPI_MAX_IDLE_TIMEOUT:
394            case TPI_MAX_UDP_PAYLOAD_SIZE:
395            case TPI_INIT_MAX_DATA:
396            case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL:
397            case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE:
398            case TPI_INIT_MAX_STREAM_DATA_UNI:
399            case TPI_INIT_MAX_STREAMS_BIDI:
400            case TPI_INIT_MAX_STREAMS_UNI:
401            case TPI_ACK_DELAY_EXPONENT:
402            case TPI_MAX_ACK_DELAY:
403            case TPI_ACTIVE_CONNECTION_ID_LIMIT:
404            case TPI_LOSS_BITS:
405            case TPI_MIN_ACK_DELAY:
406            case TPI_MIN_ACK_DELAY_02:
407            case TPI_TIMESTAMPS:
408            case TPI_MAX_DATAGRAM_FRAME_SIZE:
409                vint_write(p, 1 << bits[tpi][2], bits[tpi][1],
410                                                            1 << bits[tpi][1]);
411                p += 1 << bits[tpi][1];
412                vint_write(p, params->tp_numerics[tpi], bits[tpi][2],
413                                                            1 << bits[tpi][2]);
414                p += 1 << bits[tpi][2];
415                break;
416            case TPI_ORIGINAL_DEST_CID:
417            case TPI_INITIAL_SOURCE_CID:
418            case TPI_RETRY_SOURCE_CID:
419                vint_write(p, params->tp_cids[TP_CID_IDX(tpi)].len, bits[tpi][1],
420                                                            1 << bits[tpi][1]);
421                p += 1 << bits[tpi][1];
422                WRITE_TO_P(params->tp_cids[TP_CID_IDX(tpi)].idbuf,
423                                        params->tp_cids[TP_CID_IDX(tpi)].len);
424                break;
425            case TPI_STATELESS_RESET_TOKEN:
426                vint_write(p, sizeof(params->tp_stateless_reset_token),
427                                            bits[tpi][1], 1 << bits[tpi][1]);
428                p += 1 << bits[tpi][1];
429                WRITE_TO_P(params->tp_stateless_reset_token,
430                                sizeof(params->tp_stateless_reset_token));
431                break;
432            case TPI_PREFERRED_ADDRESS:
433                vint_write(p, preferred_address_size(params),
434                                            bits[tpi][1], 1 << bits[tpi][1]);
435                p += 1 << bits[tpi][1];
436                WRITE_TO_P(&params->tp_preferred_address.ipv4_addr,
437                        sizeof(params->tp_preferred_address.ipv4_addr));
438                WRITE_UINT_TO_P(params->tp_preferred_address.ipv4_port, 16);
439                WRITE_TO_P(&params->tp_preferred_address.ipv6_addr,
440                        sizeof(params->tp_preferred_address.ipv6_addr));
441                WRITE_UINT_TO_P(params->tp_preferred_address.ipv6_port, 16);
442                *p++ = params->tp_preferred_address.cid.len;
443                WRITE_TO_P(params->tp_preferred_address.cid.idbuf,
444                                    params->tp_preferred_address.cid.len);
445                WRITE_TO_P(params->tp_preferred_address.srst,
446                                sizeof(params->tp_preferred_address.srst));
447                break;
448            case TPI_DISABLE_ACTIVE_MIGRATION:
449            case TPI_GREASE_QUIC_BIT:
450                *p++ = 0;
451                break;
452#if LSQUIC_TEST_QUANTUM_READINESS
453            case TPI_QUANTUM_READINESS:
454                LSQ_DEBUG("encoded %zd bytes of quantum readiness", quantum_sz);
455                vint_write(p, quantum_sz, bits[tpi][1], 1 << bits[tpi][1]);
456                p += 1 << bits[tpi][1];
457                memset(p, 'Q', quantum_sz);
458                p += quantum_sz;
459                break;
460#endif
461            }
462        }
463
464    assert(buf + need == p);
465    return (int) (p - buf);
466
467#undef WRITE_TO_P
468#undef WRITE_UINT_TO_P
469}
470
471
472int
473lsquic_tp_decode (const unsigned char *const buf, size_t bufsz,
474                  int is_server,
475                  struct transport_params *params)
476{
477    const unsigned char *p, *end, *q;
478    uint64_t len, param_id;
479    uint16_t tlen;
480    enum transport_param_id tpi;
481    unsigned set_of_ids;
482    int s;
483
484    p = buf;
485    end = buf + bufsz;
486
487    *params = TP_INITIALIZER();
488
489#define EXPECT_LEN(expected_len) do {                               \
490    if (expected_len != len)                                        \
491        return -1;                                                  \
492} while (0)
493
494#define EXPECT_AT_LEAST(expected_len) do {                          \
495    if ((expected_len) > (uintptr_t) (p + len - q))                 \
496        return -1;                                                  \
497} while (0)
498
499    set_of_ids = 0;
500    while (p < end)
501    {
502        s = vint_read(p, end, &param_id);
503        if (s < 0)
504            return -1;
505        LSQ_DEBUG("read TP 0x%"PRIX64, param_id);
506        p += s;
507        s = vint_read(p, end, &len);
508        if (s < 0)
509            return -1;
510        p += s;
511        if ((ptrdiff_t) len > end - p)
512            return -1;
513        tpi = tpi_val_2_enum(param_id);
514        if (tpi <= LAST_TPI)
515        {
516            if (set_of_ids & (1 << tpi))
517                return -1;
518            set_of_ids |= 1 << tpi;
519        }
520        switch (tpi)
521        {
522        case TPI_MAX_IDLE_TIMEOUT:
523        case TPI_MAX_UDP_PAYLOAD_SIZE:
524        case TPI_INIT_MAX_DATA:
525        case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL:
526        case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE:
527        case TPI_INIT_MAX_STREAM_DATA_UNI:
528        case TPI_INIT_MAX_STREAMS_BIDI:
529        case TPI_INIT_MAX_STREAMS_UNI:
530        case TPI_ACK_DELAY_EXPONENT:
531        case TPI_MAX_ACK_DELAY:
532        case TPI_ACTIVE_CONNECTION_ID_LIMIT:
533        case TPI_LOSS_BITS:
534        case TPI_MIN_ACK_DELAY:
535        case TPI_MIN_ACK_DELAY_02:
536        case TPI_TIMESTAMPS:
537        case TPI_MAX_DATAGRAM_FRAME_SIZE:
538            switch (len)
539            {
540            case 1:
541            case 2:
542            case 4:
543            case 8:
544                s = vint_read(p, p + len, &params->tp_numerics[tpi]);
545                if (s == (int) len)
546                {
547                    if (params->tp_numerics[tpi] > max_vals[tpi])
548                    {
549                        LSQ_DEBUG("numeric value of %s is too large "
550                            "(%"PRIu64" vs maximum of %"PRIu64, tpi2str[tpi],
551                            params->tp_numerics[tpi], max_vals[tpi]);
552                        return -1;
553                    }
554                    else if (params->tp_numerics[tpi] < min_vals[tpi])
555                    {
556                        LSQ_DEBUG("numeric value of %s is too small "
557                            "(%"PRIu64" vs minimum of %"PRIu64, tpi2str[tpi],
558                            params->tp_numerics[tpi], min_vals[tpi]);
559                        return -1;
560                    }
561                    break;
562                }
563                else
564                {
565                    LSQ_DEBUG("cannot read the value of numeric transport "
566                            "param %s of length %"PRIu64, tpi2str[tpi], len);
567                    return -1;
568                }
569            default:
570                LSQ_DEBUG("invalid length=%"PRIu64" for numeric transport "
571                                            "parameter %s", len, tpi2str[tpi]);
572                return -1;
573            }
574            break;
575        case TPI_DISABLE_ACTIVE_MIGRATION:
576        case TPI_GREASE_QUIC_BIT:
577            EXPECT_LEN(0);
578            break;
579        case TPI_STATELESS_RESET_TOKEN:
580            /* Client MUST not include reset token,
581             * see [draft-ietf-quic-transport-11], Section 6.4.1
582             */
583            if (!is_server)
584                return -1;
585            EXPECT_LEN(sizeof(params->tp_stateless_reset_token));
586            memcpy(params->tp_stateless_reset_token, p,
587                                sizeof(params->tp_stateless_reset_token));
588            break;
589        case TPI_ORIGINAL_DEST_CID:
590        case TPI_RETRY_SOURCE_CID:
591            /* [draft-ietf-quic-transport-28] Section 18.2:
592             " A client MUST NOT include any server-only transport parameter:
593             " original_destination_connection_id, preferred_address,
594             " retry_source_connection_id, or stateless_reset_token.
595             */
596            if (!is_server)
597                return -1;
598            /* fallthru */
599        case TPI_INITIAL_SOURCE_CID:
600            if (len > MAX_CID_LEN)
601                return -1;
602            memcpy(params->tp_cids[TP_CID_IDX(tpi)].idbuf, p, len);
603            params->tp_cids[TP_CID_IDX(tpi)].len = len;
604            break;
605        case TPI_PREFERRED_ADDRESS:
606            /* Client MUST not include preferred address,
607             * see [draft-ietf-quic-transport-12], Section 6.4.1
608             */
609            if (!is_server)
610                return -1;
611            q = p;
612            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_addr));
613            memcpy(params->tp_preferred_address.ipv4_addr, q,
614                        sizeof(params->tp_preferred_address.ipv4_addr));
615            q += sizeof(params->tp_preferred_address.ipv4_addr);
616            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_port));
617            READ_UINT(params->tp_preferred_address.ipv4_port, 16, q, 2);
618            q += 2;
619            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_addr));
620            memcpy(params->tp_preferred_address.ipv6_addr, q,
621                        sizeof(params->tp_preferred_address.ipv6_addr));
622            q += sizeof(params->tp_preferred_address.ipv6_addr);
623            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_port));
624            READ_UINT(params->tp_preferred_address.ipv6_port, 16, q, 2);
625            q += 2;
626            EXPECT_AT_LEAST(1);
627            tlen = *q;
628            q += 1;
629            if (tlen > MAX_CID_LEN)
630            {
631                LSQ_DEBUG("preferred server address contains invalid "
632                    "CID length of %"PRIu16" bytes", tlen);
633                return -1;
634            }
635            EXPECT_AT_LEAST(tlen);
636            memcpy(params->tp_preferred_address.cid.idbuf, q, tlen);
637            params->tp_preferred_address.cid.len = tlen;
638            q += tlen;
639            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.srst));
640            memcpy(params->tp_preferred_address.srst, q,
641                            sizeof(params->tp_preferred_address.srst));
642            q += sizeof(params->tp_preferred_address.srst);
643            if (q != p + len)
644                return -1;
645            break;
646        default:
647            /* Do nothing: skip this transport parameter */
648            break;
649        }
650        p += len;
651        if (tpi <= LAST_TPI)
652        {
653            params->tp_set |= 1 << tpi;
654            params->tp_decoded |= 1 << tpi;
655        }
656    }
657
658    if (p != end)
659        return -1;
660
661    if ((params->tp_set & (1 << TPI_MIN_ACK_DELAY))
662            && params->tp_numerics[TPI_MIN_ACK_DELAY]
663                            > params->tp_numerics[TPI_MAX_ACK_DELAY] * 1000)
664    {
665        LSQ_DEBUG("min_ack_delay (%"PRIu64" usec) is larger than "
666            "max_ack_delay (%"PRIu64" ms)",
667            params->tp_numerics[TPI_MIN_ACK_DELAY],
668            params->tp_numerics[TPI_MAX_ACK_DELAY]);
669        return -1;
670    }
671
672    if ((params->tp_set & (1 << TPI_MIN_ACK_DELAY_02))
673            && params->tp_numerics[TPI_MIN_ACK_DELAY_02]
674                            > params->tp_numerics[TPI_MAX_ACK_DELAY] * 1000)
675    {
676        LSQ_DEBUG("min_ack_delay_02 (%"PRIu64" usec) is larger than "
677            "max_ack_delay (%"PRIu64" ms)",
678            params->tp_numerics[TPI_MIN_ACK_DELAY_02],
679            params->tp_numerics[TPI_MAX_ACK_DELAY]);
680        return -1;
681    }
682
683    return (int) (end - buf);
684#undef EXPECT_LEN
685}
686
687
688void
689lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz)
690{
691    char *const end = buf + sz;
692    int nw;
693    enum transport_param_id tpi;
694    char tok_str[sizeof(params->tp_stateless_reset_token) * 2 + 1];
695    char addr_str[INET6_ADDRSTRLEN];
696
697    for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
698        if (params->tp_set & (1 << tpi))
699        {
700            nw = snprintf(buf, end - buf, "%.*s%s: %"PRIu64,
701                (buf + sz > end) << 1, "; ", tpi2str[tpi],
702                params->tp_numerics[tpi]);
703            buf += nw;
704            if (buf >= end)
705                return;
706        }
707    for (; tpi <= MAX_EMPTY_TPI; ++tpi)
708        if (params->tp_set & (1 << tpi))
709        {
710            nw = snprintf(buf, end - buf, "%.*s%s",
711                                    (buf + sz > end) << 1, "; ", tpi2str[tpi]);
712            buf += nw;
713            if (buf >= end)
714                return;
715        }
716#if LSQUIC_TEST_QUANTUM_READINESS
717    if (params->tp_set & (1 << TPI_QUANTUM_READINESS))
718    {
719        nw = snprintf(buf, end - buf, "%.*s%s",
720                (buf + sz > end) << 1, "; ", tpi2str[TPI_QUANTUM_READINESS]);
721        buf += nw;
722        if (buf >= end)
723            return;
724    }
725#endif
726    if (params->tp_set & (1 << TPI_STATELESS_RESET_TOKEN))
727    {
728        lsquic_hexstr(params->tp_stateless_reset_token,
729            sizeof(params->tp_stateless_reset_token), tok_str, sizeof(tok_str));
730        nw = snprintf(buf, end - buf, "; stateless_reset_token: %s", tok_str);
731        buf += nw;
732        if (buf >= end)
733            return;
734    }
735    for (tpi = FIRST_TP_CID; tpi <= LAST_TP_CID; ++tpi)
736        if (params->tp_set & (1 << tpi))
737        {
738            char cidbuf_[MAX_CID_LEN * 2 + 1];
739            nw = snprintf(buf, end - buf, "; %s: %"CID_FMT, tpi2str[tpi],
740                                CID_BITS(&params->tp_cids[TP_CID_IDX(tpi)]));
741            buf += nw;
742            if (buf >= end)
743                return;
744        }
745    if (lsquic_tp_has_pref_ipv4(params))
746    {
747        if (inet_ntop(AF_INET, params->tp_preferred_address.ipv4_addr,
748                                                addr_str, sizeof(addr_str)))
749        {
750            nw = snprintf(buf, end - buf, "; IPv4 preferred address: %s:%u",
751                            addr_str, params->tp_preferred_address.ipv4_port);
752            buf += nw;
753            if (buf >= end)
754                return;
755        }
756    }
757    if (lsquic_tp_has_pref_ipv6(params))
758    {
759        if (inet_ntop(AF_INET6, params->tp_preferred_address.ipv6_addr,
760                                                addr_str, sizeof(addr_str)))
761        {
762            nw = snprintf(buf, end - buf, "; IPv6 preferred address: %s:%u",
763                            addr_str, params->tp_preferred_address.ipv6_port);
764            buf += nw;
765            if (buf >= end)
766                return;
767        }
768    }
769}
770
771
772int
773lsquic_tp_encode_27 (const struct transport_params *params, int is_server,
774                  unsigned char *const buf, size_t bufsz)
775{
776    unsigned char *p;
777    size_t need;
778    uint16_t u16;
779    enum transport_param_id tpi;
780    unsigned set;
781    unsigned bits[LAST_TPI + 1][3 /* ID, length, value */];
782#if LSQUIC_TEST_QUANTUM_READINESS
783    const size_t quantum_sz = lsquic_tp_get_quantum_sz();
784#endif
785
786    need = 0;
787    set = params->tp_set;   /* Will turn bits off for default values */
788
789    if (is_server)
790    {
791        if (set & (1 << TPI_ORIGINAL_DEST_CID))
792        {
793            bits[TPI_ORIGINAL_DEST_CID][0]
794                    = vint_val2bits(enum_2_tpi_val[TPI_ORIGINAL_DEST_CID]);
795#if __GNUC__
796#pragma GCC diagnostic ignored "-Wunknown-pragmas"
797#if __clang__
798#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
799#else
800#pragma GCC diagnostic ignored "-Wtype-limits"
801#endif
802#endif
803            bits[TPI_ORIGINAL_DEST_CID][1]
804                    = vint_val2bits(params->tp_original_dest_cid.len);
805#if __GNUC__
806#pragma GCC diagnostic pop
807#pragma GCC diagnostic pop
808#endif
809            need += (1 << bits[TPI_ORIGINAL_DEST_CID][0])
810                 +  (1 << bits[TPI_ORIGINAL_DEST_CID][1])
811                 +  params->tp_original_dest_cid.len;
812        }
813        if (set & (1 << TPI_STATELESS_RESET_TOKEN))
814        {
815            bits[TPI_STATELESS_RESET_TOKEN][0]
816                    = vint_val2bits(enum_2_tpi_val[TPI_STATELESS_RESET_TOKEN]);
817            bits[TPI_STATELESS_RESET_TOKEN][1]
818                    = vint_val2bits(sizeof(params->tp_stateless_reset_token));
819            need += (1 << bits[TPI_STATELESS_RESET_TOKEN][0])
820                 +  (1 << bits[TPI_STATELESS_RESET_TOKEN][1])
821                 +  sizeof(params->tp_stateless_reset_token);
822        }
823        if (set & (1 << TPI_PREFERRED_ADDRESS))
824        {
825            bits[TPI_PREFERRED_ADDRESS][0]
826                    = vint_val2bits(enum_2_tpi_val[TPI_PREFERRED_ADDRESS]);
827            bits[TPI_PREFERRED_ADDRESS][1] = vint_val2bits(
828                                            preferred_address_size(params));
829            need += (1 << bits[TPI_PREFERRED_ADDRESS][0])
830                 +  (1 << bits[TPI_PREFERRED_ADDRESS][1])
831                 +  preferred_address_size(params);
832        }
833    }
834#if LSQUIC_TEST_QUANTUM_READINESS
835    else if (set & (1 << TPI_QUANTUM_READINESS))
836    {
837        bits[TPI_QUANTUM_READINESS][0]
838                = vint_val2bits(enum_2_tpi_val[TPI_QUANTUM_READINESS]);
839        bits[TPI_QUANTUM_READINESS][1] = vint_val2bits(quantum_sz);
840        need += (1 << bits[TPI_QUANTUM_READINESS][0])
841             +  (1 << bits[TPI_QUANTUM_READINESS][1])
842             +  quantum_sz;
843    }
844#endif
845
846    for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
847        if (set & (1 << tpi))
848        {
849            if (tpi > MAX_NUM_WITH_DEF_TPI
850                        || params->tp_numerics[tpi] != def_vals[tpi])
851            {
852                if (params->tp_numerics[tpi] >= min_vals[tpi]
853                                && params->tp_numerics[tpi] <= max_vals[tpi])
854                {
855                    bits[tpi][0] = vint_val2bits(enum_2_tpi_val[tpi]);
856                    bits[tpi][2] = vint_val2bits(params->tp_numerics[tpi]);
857                    bits[tpi][1] = vint_val2bits(bits[tpi][2]);
858                    need += (1 << bits[tpi][0])
859                         +  (1 << bits[tpi][1])
860                         +  (1 << bits[tpi][2]);
861                }
862                else if (params->tp_numerics[tpi] > max_vals[tpi])
863                {
864                    LSQ_DEBUG("numeric value of %s is too large (%"PRIu64" vs "
865                        "maximum of %"PRIu64")", tpi2str[tpi],
866                        params->tp_numerics[tpi], max_vals[tpi]);
867                    return -1;
868                }
869                else
870                {
871                    LSQ_DEBUG("numeric value of %s is too small (%"PRIu64" vs "
872                        "minimum " "of %"PRIu64")",
873                        tpi2str[tpi], params->tp_numerics[tpi], min_vals[tpi]);
874                    return -1;
875                }
876            }
877            else
878                set &= ~(1 << tpi);     /* Don't write default value */
879        }
880
881    for (; tpi <= MAX_EMPTY_TPI; ++tpi)
882        if (set & (1 << tpi))
883        {
884            bits[tpi][0] = vint_val2bits(enum_2_tpi_val[tpi]);
885            need += (1 << bits[tpi][0]) + 1 /* Zero length byte */;
886        }
887
888    if (need > bufsz || need > UINT16_MAX)
889    {
890        errno = ENOBUFS;
891        return -1;
892    }
893
894    p = buf;
895
896#define WRITE_TO_P(src, len) do {                                       \
897    memcpy(p, src, len);                                                \
898    p += len;                                                           \
899} while (0)
900
901#if __BYTE_ORDER == __LITTLE_ENDIAN
902#define WRITE_UINT_TO_P(val, width) do {                                \
903    u##width = bswap_##width(val);                                      \
904    WRITE_TO_P(&u##width, sizeof(u##width));                            \
905} while (0)
906#else
907#define WRITE_UINT_TO_P(val, width) do {                                \
908    u##width = val;                                                     \
909    WRITE_TO_P(&u##width, sizeof(u##width));                            \
910} while (0)
911#endif
912
913    for (tpi = 0; tpi <= LAST_TPI; ++tpi)
914        if (set & (1 << tpi))
915        {
916            vint_write(p, enum_2_tpi_val[tpi], bits[tpi][0],
917                                                        1 << bits[tpi][0]);
918            p += 1 << bits[tpi][0];
919            switch (tpi)
920            {
921            case TPI_MAX_IDLE_TIMEOUT:
922            case TPI_MAX_UDP_PAYLOAD_SIZE:
923            case TPI_INIT_MAX_DATA:
924            case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL:
925            case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE:
926            case TPI_INIT_MAX_STREAM_DATA_UNI:
927            case TPI_INIT_MAX_STREAMS_BIDI:
928            case TPI_INIT_MAX_STREAMS_UNI:
929            case TPI_ACK_DELAY_EXPONENT:
930            case TPI_MAX_ACK_DELAY:
931            case TPI_ACTIVE_CONNECTION_ID_LIMIT:
932            case TPI_LOSS_BITS:
933            case TPI_MIN_ACK_DELAY:
934            case TPI_MIN_ACK_DELAY_02:
935            case TPI_TIMESTAMPS:
936            case TPI_MAX_DATAGRAM_FRAME_SIZE:
937                vint_write(p, 1 << bits[tpi][2], bits[tpi][1],
938                                                            1 << bits[tpi][1]);
939                p += 1 << bits[tpi][1];
940                vint_write(p, params->tp_numerics[tpi], bits[tpi][2],
941                                                            1 << bits[tpi][2]);
942                p += 1 << bits[tpi][2];
943                break;
944            case TPI_INITIAL_SOURCE_CID:
945            case TPI_RETRY_SOURCE_CID:
946                assert(0);
947                return -1;
948            case TPI_ORIGINAL_DEST_CID:
949                vint_write(p, params->tp_original_dest_cid.len, bits[tpi][1],
950                                                            1 << bits[tpi][1]);
951                p += 1 << bits[tpi][1];
952                WRITE_TO_P(params->tp_original_dest_cid.idbuf,
953                                            params->tp_original_dest_cid.len);
954                break;
955            case TPI_STATELESS_RESET_TOKEN:
956                vint_write(p, sizeof(params->tp_stateless_reset_token),
957                                            bits[tpi][1], 1 << bits[tpi][1]);
958                p += 1 << bits[tpi][1];
959                WRITE_TO_P(params->tp_stateless_reset_token,
960                                sizeof(params->tp_stateless_reset_token));
961                break;
962            case TPI_PREFERRED_ADDRESS:
963                vint_write(p, preferred_address_size(params),
964                                            bits[tpi][1], 1 << bits[tpi][1]);
965                p += 1 << bits[tpi][1];
966                WRITE_TO_P(&params->tp_preferred_address.ipv4_addr,
967                        sizeof(params->tp_preferred_address.ipv4_addr));
968                WRITE_UINT_TO_P(params->tp_preferred_address.ipv4_port, 16);
969                WRITE_TO_P(&params->tp_preferred_address.ipv6_addr,
970                        sizeof(params->tp_preferred_address.ipv6_addr));
971                WRITE_UINT_TO_P(params->tp_preferred_address.ipv6_port, 16);
972                *p++ = params->tp_preferred_address.cid.len;
973                WRITE_TO_P(params->tp_preferred_address.cid.idbuf,
974                                    params->tp_preferred_address.cid.len);
975                WRITE_TO_P(params->tp_preferred_address.srst,
976                                sizeof(params->tp_preferred_address.srst));
977                break;
978            case TPI_DISABLE_ACTIVE_MIGRATION:
979            case TPI_GREASE_QUIC_BIT:
980                *p++ = 0;
981                break;
982#if LSQUIC_TEST_QUANTUM_READINESS
983            case TPI_QUANTUM_READINESS:
984                LSQ_DEBUG("encoded %zd bytes of quantum readiness", quantum_sz);
985                vint_write(p, quantum_sz, bits[tpi][1], 1 << bits[tpi][1]);
986                p += 1 << bits[tpi][1];
987                memset(p, 'Q', quantum_sz);
988                p += quantum_sz;
989                break;
990#endif
991            }
992        }
993
994    assert(buf + need == p);
995    return (int) (p - buf);
996
997#undef WRITE_TO_P
998#undef WRITE_UINT_TO_P
999}
1000
1001
1002int
1003lsquic_tp_decode_27 (const unsigned char *const buf, size_t bufsz,
1004                  int is_server,
1005                  struct transport_params *params)
1006{
1007    const unsigned char *p, *end, *q;
1008    uint64_t len, param_id;
1009    uint16_t tlen;
1010    enum transport_param_id tpi;
1011    unsigned set_of_ids;
1012    int s;
1013
1014    p = buf;
1015    end = buf + bufsz;
1016
1017    *params = TP_INITIALIZER();
1018
1019#define EXPECT_LEN(expected_len) do {                               \
1020    if (expected_len != len)                                        \
1021        return -1;                                                  \
1022} while (0)
1023
1024#define EXPECT_AT_LEAST(expected_len) do {                          \
1025    if ((expected_len) > (uintptr_t) (p + len - q))                 \
1026        return -1;                                                  \
1027} while (0)
1028
1029    set_of_ids = 0;
1030    while (p < end)
1031    {
1032        s = vint_read(p, end, &param_id);
1033        if (s < 0)
1034            return -1;
1035        p += s;
1036        s = vint_read(p, end, &len);
1037        if (s < 0)
1038            return -1;
1039        p += s;
1040        if ((ptrdiff_t) len > end - p)
1041            return -1;
1042        tpi = tpi_val_2_enum(param_id);
1043        if (tpi <= LAST_TPI)
1044        {
1045            if (set_of_ids & (1 << tpi))
1046                return -1;
1047            set_of_ids |= 1 << tpi;
1048        }
1049        switch (tpi)
1050        {
1051        case TPI_MAX_IDLE_TIMEOUT:
1052        case TPI_MAX_UDP_PAYLOAD_SIZE:
1053        case TPI_INIT_MAX_DATA:
1054        case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL:
1055        case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE:
1056        case TPI_INIT_MAX_STREAM_DATA_UNI:
1057        case TPI_INIT_MAX_STREAMS_BIDI:
1058        case TPI_INIT_MAX_STREAMS_UNI:
1059        case TPI_ACK_DELAY_EXPONENT:
1060        case TPI_MAX_ACK_DELAY:
1061        case TPI_ACTIVE_CONNECTION_ID_LIMIT:
1062        case TPI_LOSS_BITS:
1063        case TPI_MIN_ACK_DELAY:
1064        case TPI_MIN_ACK_DELAY_02:
1065        case TPI_TIMESTAMPS:
1066        case TPI_MAX_DATAGRAM_FRAME_SIZE:
1067            switch (len)
1068            {
1069            case 1:
1070            case 2:
1071            case 4:
1072            case 8:
1073                s = vint_read(p, p + len, &params->tp_numerics[tpi]);
1074                if (s == (int) len)
1075                {
1076                    if (params->tp_numerics[tpi] > max_vals[tpi])
1077                    {
1078                        LSQ_DEBUG("numeric value of %s is too large "
1079                            "(%"PRIu64" vs maximum of %"PRIu64, tpi2str[tpi],
1080                            params->tp_numerics[tpi], max_vals[tpi]);
1081                        return -1;
1082                    }
1083                    else if (params->tp_numerics[tpi] < min_vals[tpi])
1084                    {
1085                        LSQ_DEBUG("numeric value of %s is too small "
1086                            "(%"PRIu64" vs minimum of %"PRIu64, tpi2str[tpi],
1087                            params->tp_numerics[tpi], min_vals[tpi]);
1088                        return -1;
1089                    }
1090                    break;
1091                }
1092                else
1093                {
1094                    LSQ_DEBUG("cannot read the value of numeric transport "
1095                            "param %s of length %"PRIu64, tpi2str[tpi], len);
1096                    return -1;
1097                }
1098            default:
1099                LSQ_DEBUG("invalid length=%"PRIu64" for numeric transport "
1100                                            "parameter %s", len, tpi2str[tpi]);
1101                return -1;
1102            }
1103            break;
1104        case TPI_DISABLE_ACTIVE_MIGRATION:
1105            EXPECT_LEN(0);
1106            break;
1107        case TPI_STATELESS_RESET_TOKEN:
1108            /* Client MUST not include reset token,
1109             * see [draft-ietf-quic-transport-11], Section 6.4.1
1110             */
1111            if (!is_server)
1112                return -1;
1113            EXPECT_LEN(sizeof(params->tp_stateless_reset_token));
1114            memcpy(params->tp_stateless_reset_token, p,
1115                                sizeof(params->tp_stateless_reset_token));
1116            break;
1117        case TPI_ORIGINAL_DEST_CID:
1118            /* Client MUST not original connecti ID,
1119             * see [draft-ietf-quic-transport-15], Section 6.6.1
1120             */
1121            if (!is_server)
1122                return -1;
1123            if (len > MAX_CID_LEN)
1124                return -1;
1125            memcpy(params->tp_original_dest_cid.idbuf, p, len);
1126            params->tp_original_dest_cid.len = len;
1127            break;
1128        case TPI_PREFERRED_ADDRESS:
1129            /* Client MUST not include preferred address,
1130             * see [draft-ietf-quic-transport-12], Section 6.4.1
1131             */
1132            if (!is_server)
1133                return -1;
1134            q = p;
1135            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_addr));
1136            memcpy(params->tp_preferred_address.ipv4_addr, q,
1137                        sizeof(params->tp_preferred_address.ipv4_addr));
1138            q += sizeof(params->tp_preferred_address.ipv4_addr);
1139            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_port));
1140            READ_UINT(params->tp_preferred_address.ipv4_port, 16, q, 2);
1141            q += 2;
1142            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_addr));
1143            memcpy(params->tp_preferred_address.ipv6_addr, q,
1144                        sizeof(params->tp_preferred_address.ipv6_addr));
1145            q += sizeof(params->tp_preferred_address.ipv6_addr);
1146            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_port));
1147            READ_UINT(params->tp_preferred_address.ipv6_port, 16, q, 2);
1148            q += 2;
1149            EXPECT_AT_LEAST(1);
1150            tlen = *q;
1151            q += 1;
1152            if (tlen > MAX_CID_LEN)
1153            {
1154                LSQ_DEBUG("preferred server address contains invalid "
1155                    "CID length of %"PRIu16" bytes", tlen);
1156                return -1;
1157            }
1158            EXPECT_AT_LEAST(tlen);
1159            memcpy(params->tp_preferred_address.cid.idbuf, q, tlen);
1160            params->tp_preferred_address.cid.len = tlen;
1161            q += tlen;
1162            EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.srst));
1163            memcpy(params->tp_preferred_address.srst, q,
1164                            sizeof(params->tp_preferred_address.srst));
1165            q += sizeof(params->tp_preferred_address.srst);
1166            if (q != p + len)
1167                return -1;
1168            break;
1169        default:
1170            /* Do nothing: skip this transport parameter */
1171            break;
1172        }
1173        p += len;
1174        if (tpi <= LAST_TPI)
1175        {
1176            params->tp_set |= 1 << tpi;
1177            params->tp_decoded |= 1 << tpi;
1178        }
1179    }
1180
1181    if (p != end)
1182        return -1;
1183
1184    if ((params->tp_set & (1 << TPI_MIN_ACK_DELAY))
1185            && params->tp_numerics[TPI_MIN_ACK_DELAY]
1186                            > params->tp_numerics[TPI_MAX_ACK_DELAY] * 1000)
1187    {
1188        LSQ_DEBUG("min_ack_delay (%"PRIu64" usec) is larger than "
1189            "max_ack_delay (%"PRIu64" ms)",
1190            params->tp_numerics[TPI_MIN_ACK_DELAY],
1191            params->tp_numerics[TPI_MAX_ACK_DELAY]);
1192        return -1;
1193    }
1194
1195    if ((params->tp_set & (1 << TPI_MIN_ACK_DELAY_02))
1196            && params->tp_numerics[TPI_MIN_ACK_DELAY_02]
1197                            > params->tp_numerics[TPI_MAX_ACK_DELAY] * 1000)
1198    {
1199        LSQ_DEBUG("min_ack_delay_02 (%"PRIu64" usec) is larger than "
1200            "max_ack_delay (%"PRIu64" ms)",
1201            params->tp_numerics[TPI_MIN_ACK_DELAY_02],
1202            params->tp_numerics[TPI_MAX_ACK_DELAY]);
1203        return -1;
1204    }
1205
1206    return (int) (end - buf);
1207#undef EXPECT_LEN
1208}
1209
1210
1211void
1212lsquic_tp_to_str_27 (const struct transport_params *params, char *buf, size_t sz)
1213{
1214    char *const end = buf + sz;
1215    int nw;
1216    enum transport_param_id tpi;
1217    char tok_str[sizeof(params->tp_stateless_reset_token) * 2 + 1];
1218    char addr_str[INET6_ADDRSTRLEN];
1219
1220    for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi)
1221        if (params->tp_set & (1 << tpi))
1222        {
1223            nw = snprintf(buf, end - buf, "%.*s%s: %"PRIu64,
1224                (buf + sz > end) << 1, "; ", tpi2str[tpi],
1225                params->tp_numerics[tpi]);
1226            buf += nw;
1227            if (buf >= end)
1228                return;
1229        }
1230    for (; tpi <= MAX_EMPTY_TPI; ++tpi)
1231        if (params->tp_set & (1 << tpi))
1232        {
1233            nw = snprintf(buf, end - buf, "%.*s%s",
1234                                    (buf + sz > end) << 1, "; ", tpi2str[tpi]);
1235            buf += nw;
1236            if (buf >= end)
1237                return;
1238        }
1239#if LSQUIC_TEST_QUANTUM_READINESS
1240    if (params->tp_set & (1 << TPI_QUANTUM_READINESS))
1241    {
1242        nw = snprintf(buf, end - buf, "%.*s%s",
1243                (buf + sz > end) << 1, "; ", tpi2str[TPI_QUANTUM_READINESS]);
1244        buf += nw;
1245        if (buf >= end)
1246            return;
1247    }
1248#endif
1249    if (params->tp_set & (1 << TPI_STATELESS_RESET_TOKEN))
1250    {
1251        lsquic_hexstr(params->tp_stateless_reset_token,
1252            sizeof(params->tp_stateless_reset_token), tok_str, sizeof(tok_str));
1253        nw = snprintf(buf, end - buf, "; stateless_reset_token: %s", tok_str);
1254        buf += nw;
1255        if (buf >= end)
1256            return;
1257    }
1258    if (params->tp_set & (1 << TPI_ORIGINAL_DEST_CID))
1259    {
1260        char cidbuf_[MAX_CID_LEN * 2 + 1];
1261        nw = snprintf(buf, end - buf, "; original DCID (ODCID): %"CID_FMT,
1262                                    CID_BITS(&params->tp_original_dest_cid));
1263        buf += nw;
1264        if (buf >= end)
1265            return;
1266    }
1267    if (lsquic_tp_has_pref_ipv4(params))
1268    {
1269        if (inet_ntop(AF_INET, params->tp_preferred_address.ipv4_addr,
1270                                                addr_str, sizeof(addr_str)))
1271        {
1272            nw = snprintf(buf, end - buf, "; IPv4 preferred address: %s:%u",
1273                            addr_str, params->tp_preferred_address.ipv4_port);
1274            buf += nw;
1275            if (buf >= end)
1276                return;
1277        }
1278    }
1279    if (lsquic_tp_has_pref_ipv6(params))
1280    {
1281        if (inet_ntop(AF_INET6, params->tp_preferred_address.ipv6_addr,
1282                                                addr_str, sizeof(addr_str)))
1283        {
1284            nw = snprintf(buf, end - buf, "; IPv6 preferred address: %s:%u",
1285                            addr_str, params->tp_preferred_address.ipv6_port);
1286            buf += nw;
1287            if (buf >= end)
1288                return;
1289        }
1290    }
1291}
1292