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