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