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