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