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