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