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