lsquic_parse_iquic_common.c revision 5392f7a3
1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech/*
35392f7a3SLiteSpeed Tech * Parsing routines shared by all IETF QUIC versions.
45392f7a3SLiteSpeed Tech */
55392f7a3SLiteSpeed Tech
65392f7a3SLiteSpeed Tech#include <assert.h>
79626cfc2SDmitri Tikhonov#include <stddef.h>
89626cfc2SDmitri Tikhonov#include <stdint.h>
95392f7a3SLiteSpeed Tech#include <stdlib.h>
109626cfc2SDmitri Tikhonov#include <string.h>
119626cfc2SDmitri Tikhonov#include <sys/queue.h>
129626cfc2SDmitri Tikhonov#include <sys/types.h>
139626cfc2SDmitri Tikhonov
149626cfc2SDmitri Tikhonov#include <openssl/rand.h>
159626cfc2SDmitri Tikhonov
169626cfc2SDmitri Tikhonov#include "lsquic_types.h"
179626cfc2SDmitri Tikhonov#include "lsquic_int_types.h"
189626cfc2SDmitri Tikhonov#include "lsquic_packet_common.h"
199626cfc2SDmitri Tikhonov#include "lsquic_packet_in.h"
209626cfc2SDmitri Tikhonov#include "lsquic_parse_common.h"
219626cfc2SDmitri Tikhonov#include "lsquic_parse.h"
229626cfc2SDmitri Tikhonov#include "lsquic_version.h"
239626cfc2SDmitri Tikhonov#include "lsquic.h"
249626cfc2SDmitri Tikhonov#include "lsquic_logger.h"
259626cfc2SDmitri Tikhonov#include "lsquic_byteswap.h"
265392f7a3SLiteSpeed Tech#include "lsquic_varint.h"
275392f7a3SLiteSpeed Tech#include "lsquic_enc_sess.h"
285392f7a3SLiteSpeed Tech#include "lsquic_tokgen.h"
295392f7a3SLiteSpeed Tech#include "lsquic.h"
305392f7a3SLiteSpeed Tech#include "lsquic_mm.h"
315392f7a3SLiteSpeed Tech#include "lsquic_engine_public.h"
329626cfc2SDmitri Tikhonov
339626cfc2SDmitri Tikhonov
34c7d81ce1SDmitri Tikhonov/* [draft-ietf-quic-transport-17] Section-17.2 */
35c7d81ce1SDmitri Tikhonovstatic const enum header_type bits2ht[4] =
36c7d81ce1SDmitri Tikhonov{
37c7d81ce1SDmitri Tikhonov    [0] = HETY_INITIAL,
38c7d81ce1SDmitri Tikhonov    [1] = HETY_0RTT,
39c7d81ce1SDmitri Tikhonov    [2] = HETY_HANDSHAKE,
40c7d81ce1SDmitri Tikhonov    [3] = HETY_RETRY,
41c7d81ce1SDmitri Tikhonov};
42c7d81ce1SDmitri Tikhonov
43c7d81ce1SDmitri Tikhonov
449626cfc2SDmitri Tikhonovint
455392f7a3SLiteSpeed Techlsquic_Q046_parse_packet_in_long_begin (struct lsquic_packet_in *packet_in,
465392f7a3SLiteSpeed Tech                size_t length, int is_server, unsigned cid_len,
475392f7a3SLiteSpeed Tech                struct packin_parse_state *state)
489626cfc2SDmitri Tikhonov{
499626cfc2SDmitri Tikhonov    const unsigned char *p = packet_in->pi_data;
509626cfc2SDmitri Tikhonov    const unsigned char *const end = p + length;
519626cfc2SDmitri Tikhonov    lsquic_ver_tag_t tag;
529626cfc2SDmitri Tikhonov    enum header_type header_type;
53c7d81ce1SDmitri Tikhonov    unsigned dcil, scil, packet_len;
549626cfc2SDmitri Tikhonov    int verneg;
559626cfc2SDmitri Tikhonov    unsigned char first_byte;
565392f7a3SLiteSpeed Tech    lsquic_packno_t packno;
579626cfc2SDmitri Tikhonov
589626cfc2SDmitri Tikhonov    if (length < 6)
599626cfc2SDmitri Tikhonov        return -1;
609626cfc2SDmitri Tikhonov    first_byte = *p++;
619626cfc2SDmitri Tikhonov
629626cfc2SDmitri Tikhonov    memcpy(&tag, p, 4);
639626cfc2SDmitri Tikhonov    p += 4;
649626cfc2SDmitri Tikhonov    verneg = 0 == tag;
659626cfc2SDmitri Tikhonov    if (!verneg)
665392f7a3SLiteSpeed Tech        header_type = bits2ht[ (first_byte >> 4) & 3 ];
679626cfc2SDmitri Tikhonov    else
689626cfc2SDmitri Tikhonov        header_type = HETY_VERNEG;
699626cfc2SDmitri Tikhonov
709626cfc2SDmitri Tikhonov    packet_in->pi_header_type = header_type;
719626cfc2SDmitri Tikhonov
729626cfc2SDmitri Tikhonov    dcil = p[0] >> 4;
739626cfc2SDmitri Tikhonov    if (dcil)
749626cfc2SDmitri Tikhonov        dcil += 3;
759626cfc2SDmitri Tikhonov    scil = p[0] & 0xF;
769626cfc2SDmitri Tikhonov    if (scil)
779626cfc2SDmitri Tikhonov        scil += 3;
789626cfc2SDmitri Tikhonov    ++p;
799626cfc2SDmitri Tikhonov
809626cfc2SDmitri Tikhonov    /* Chromium comments state that the client sends packets with destination
819626cfc2SDmitri Tikhonov     * CID of 8 bytes and source CID of 0 bytes and the server does it the
829626cfc2SDmitri Tikhonov     * other way around.
839626cfc2SDmitri Tikhonov     */
849626cfc2SDmitri Tikhonov    if (is_server)
859626cfc2SDmitri Tikhonov    {
869626cfc2SDmitri Tikhonov        if (!(dcil == cid_len && scil == 0))
879626cfc2SDmitri Tikhonov            return -1;
889626cfc2SDmitri Tikhonov    }
899626cfc2SDmitri Tikhonov    else
905392f7a3SLiteSpeed Tech    if (!(dcil == 0 && scil == cid_len))
915392f7a3SLiteSpeed Tech        return -1;
929626cfc2SDmitri Tikhonov
93c7d81ce1SDmitri Tikhonov    if (!verneg)
94c7d81ce1SDmitri Tikhonov    {
955392f7a3SLiteSpeed Tech        packet_in->pi_flags |= (first_byte & 3) << PIBIT_BITS_SHIFT;
965392f7a3SLiteSpeed Tech        packet_len = 1 + (first_byte & 3);
97c7d81ce1SDmitri Tikhonov        if (end - p < (ptrdiff_t) (dcil + scil + packet_len))
98c7d81ce1SDmitri Tikhonov            return -1;
99c7d81ce1SDmitri Tikhonov    }
100c7d81ce1SDmitri Tikhonov    else
101c7d81ce1SDmitri Tikhonov    {
102c7d81ce1SDmitri Tikhonov        /* Need at least one version in the version array: add 4 */
103c7d81ce1SDmitri Tikhonov        if (end - p < (ptrdiff_t) (dcil + scil + 4))
104c7d81ce1SDmitri Tikhonov            return -1;
105e5d4bc6dSDmitri Tikhonov#ifdef WIN32
106e5d4bc6dSDmitri Tikhonov        /* Useless initialization: */
107e5d4bc6dSDmitri Tikhonov        packet_len = 0;
108e5d4bc6dSDmitri Tikhonov#endif
109c7d81ce1SDmitri Tikhonov    }
1109626cfc2SDmitri Tikhonov
1115392f7a3SLiteSpeed Tech    memcpy(&packet_in->pi_dcid.idbuf, p, cid_len);
1125392f7a3SLiteSpeed Tech    packet_in->pi_dcid.len = cid_len;
1139626cfc2SDmitri Tikhonov    p += cid_len;
1149626cfc2SDmitri Tikhonov    packet_in->pi_flags |= PI_CONN_ID;
1159626cfc2SDmitri Tikhonov
1169626cfc2SDmitri Tikhonov    if (!verneg)
1179626cfc2SDmitri Tikhonov    {
1185392f7a3SLiteSpeed Tech        READ_UINT(packno, 64, p, packet_len);
1195392f7a3SLiteSpeed Tech        packet_in->pi_packno = packno;
1209626cfc2SDmitri Tikhonov        p += packet_len;
1219626cfc2SDmitri Tikhonov        packet_in->pi_quic_ver = 1;
1229626cfc2SDmitri Tikhonov        if (is_server || HETY_0RTT != header_type)
1239626cfc2SDmitri Tikhonov            packet_in->pi_nonce = 0;
1249626cfc2SDmitri Tikhonov        else
1259626cfc2SDmitri Tikhonov        {
1269626cfc2SDmitri Tikhonov            packet_in->pi_nonce = p - packet_in->pi_data;
1279626cfc2SDmitri Tikhonov            p += 32;
1289626cfc2SDmitri Tikhonov        }
1299626cfc2SDmitri Tikhonov    }
1309626cfc2SDmitri Tikhonov    else
1319626cfc2SDmitri Tikhonov    {
1325392f7a3SLiteSpeed Tech        if (p >= end || (3 & (uintptr_t) (end - p)))
1339626cfc2SDmitri Tikhonov            return -1;
1349626cfc2SDmitri Tikhonov        packet_in->pi_quic_ver = p - packet_in->pi_data;
1355392f7a3SLiteSpeed Tech        p = end;
1369626cfc2SDmitri Tikhonov    }
1379626cfc2SDmitri Tikhonov
1389626cfc2SDmitri Tikhonov    packet_in->pi_header_sz    = p - packet_in->pi_data;
1399626cfc2SDmitri Tikhonov    packet_in->pi_frame_types  = 0;
1409626cfc2SDmitri Tikhonov    packet_in->pi_data_sz      = length;
1419626cfc2SDmitri Tikhonov    packet_in->pi_refcnt       = 0;
1429626cfc2SDmitri Tikhonov    packet_in->pi_received     = 0;
1439626cfc2SDmitri Tikhonov
1449626cfc2SDmitri Tikhonov    return 0;
1459626cfc2SDmitri Tikhonov}
1469626cfc2SDmitri Tikhonov
1479626cfc2SDmitri Tikhonov
1489626cfc2SDmitri Tikhonovint
1495392f7a3SLiteSpeed Techlsquic_Q046_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in,
1505392f7a3SLiteSpeed Tech            size_t length, int is_server, unsigned cid_len,
1515392f7a3SLiteSpeed Tech            struct packin_parse_state *state)
1529626cfc2SDmitri Tikhonov{
1539626cfc2SDmitri Tikhonov    const unsigned char *p = packet_in->pi_data;
1549626cfc2SDmitri Tikhonov    const unsigned char *const pend = packet_in->pi_data + length;
1555392f7a3SLiteSpeed Tech    unsigned packet_len, header_len;
1565392f7a3SLiteSpeed Tech    lsquic_packno_t packno;
1579626cfc2SDmitri Tikhonov
158c7d81ce1SDmitri Tikhonov    if (*p & 0x40)  /* Q046 and higher */
159c7d81ce1SDmitri Tikhonov        packet_len = 1 + (*p & 3);
160c7d81ce1SDmitri Tikhonov    else
1615392f7a3SLiteSpeed Tech        return -1;
1625392f7a3SLiteSpeed Tech
1635392f7a3SLiteSpeed Tech    if (is_server)
1645392f7a3SLiteSpeed Tech        header_len = 1 + cid_len + packet_len;
1655392f7a3SLiteSpeed Tech    else
1665392f7a3SLiteSpeed Tech        header_len = 1 + packet_len;
1679626cfc2SDmitri Tikhonov
1685392f7a3SLiteSpeed Tech    if (pend - p < (ptrdiff_t) header_len)
1699626cfc2SDmitri Tikhonov        return -1;
1709626cfc2SDmitri Tikhonov
171c7d81ce1SDmitri Tikhonov    packet_in->pi_flags |= (*p & 3) << PIBIT_BITS_SHIFT;
1729626cfc2SDmitri Tikhonov    ++p;
1739626cfc2SDmitri Tikhonov    if (is_server)
1749626cfc2SDmitri Tikhonov    {
1755392f7a3SLiteSpeed Tech        memcpy(packet_in->pi_dcid.idbuf, packet_in->pi_data + 1, cid_len);
1765392f7a3SLiteSpeed Tech        packet_in->pi_dcid.len = cid_len;
177dee31d56SDmitri Tikhonov        packet_in->pi_flags |= PI_CONN_ID;
1785392f7a3SLiteSpeed Tech        p += cid_len;
1799626cfc2SDmitri Tikhonov    }
1809626cfc2SDmitri Tikhonov
1815392f7a3SLiteSpeed Tech    READ_UINT(packno, 64, p, packet_len);
1825392f7a3SLiteSpeed Tech    packet_in->pi_packno = packno;
1839626cfc2SDmitri Tikhonov    p += packet_len;
1849626cfc2SDmitri Tikhonov
1859626cfc2SDmitri Tikhonov    packet_in->pi_header_type  = HETY_NOT_SET;
1869626cfc2SDmitri Tikhonov    packet_in->pi_quic_ver     = 0;
1879626cfc2SDmitri Tikhonov    packet_in->pi_nonce        = 0;
1889626cfc2SDmitri Tikhonov    packet_in->pi_header_sz    = p - packet_in->pi_data;
1899626cfc2SDmitri Tikhonov    packet_in->pi_frame_types  = 0;
1909626cfc2SDmitri Tikhonov    packet_in->pi_data_sz      = length;
1919626cfc2SDmitri Tikhonov    packet_in->pi_refcnt       = 0;
1929626cfc2SDmitri Tikhonov    packet_in->pi_received     = 0;
1939626cfc2SDmitri Tikhonov
1949626cfc2SDmitri Tikhonov    return 0;
1959626cfc2SDmitri Tikhonov}
1969626cfc2SDmitri Tikhonov
1979626cfc2SDmitri Tikhonov
1985392f7a3SLiteSpeed Tech/* TODO: this only works Q044? XXX */
1995392f7a3SLiteSpeed Techssize_t
2005392f7a3SLiteSpeed Techlsquic_generate_iquic_reset (const lsquic_cid_t *cidp, unsigned char *buf,
2015392f7a3SLiteSpeed Tech                                                            size_t buf_sz)
2025392f7a3SLiteSpeed Tech{
2035392f7a3SLiteSpeed Tech    size_t need;
2045392f7a3SLiteSpeed Tech    uint64_t id;
2055392f7a3SLiteSpeed Tech
2065392f7a3SLiteSpeed Tech    need = 1 /* Type */ + 20 /* Random bytes */ + 16 /* Reset token */;
2075392f7a3SLiteSpeed Tech    if (buf_sz < need)
2085392f7a3SLiteSpeed Tech        return -1;
2095392f7a3SLiteSpeed Tech
2105392f7a3SLiteSpeed Tech    *buf = 0x30;
2115392f7a3SLiteSpeed Tech    (void) RAND_pseudo_bytes(buf + 1, 20);
2125392f7a3SLiteSpeed Tech    /* XXX code duplication here and lsquic_generate_reset_token().  Which
2135392f7a3SLiteSpeed Tech     * should call which: parse function the crypto functions or the other
2145392f7a3SLiteSpeed Tech     * way around?
2155392f7a3SLiteSpeed Tech     */
2165392f7a3SLiteSpeed Tech    /* TODO test this */
2175392f7a3SLiteSpeed Tech    memcpy(&id, cidp->idbuf, GQUIC_CID_LEN);
2185392f7a3SLiteSpeed Tech#if __BYTE_ORDER == __LITTLE_ENDIAN
2195392f7a3SLiteSpeed Tech    id = bswap_64(id);
2205392f7a3SLiteSpeed Tech#endif
2215392f7a3SLiteSpeed Tech    memcpy(buf + 21, &id, sizeof(id));
2225392f7a3SLiteSpeed Tech    memset(buf + 21 + sizeof(id), 0, SRST_LENGTH - sizeof(id));
2235392f7a3SLiteSpeed Tech    return need;
2245392f7a3SLiteSpeed Tech}
2255392f7a3SLiteSpeed Tech
2265392f7a3SLiteSpeed Tech
2275392f7a3SLiteSpeed Tech/* This is a bare-bones version of lsquic_Q046_parse_packet_in_long_begin()
2285392f7a3SLiteSpeed Tech */
2295392f7a3SLiteSpeed Techint
2305392f7a3SLiteSpeed Techlsquic_is_valid_iquic_hs_packet (const unsigned char *buf, size_t length,
2315392f7a3SLiteSpeed Tech                                                        lsquic_ver_tag_t *tagp)
2325392f7a3SLiteSpeed Tech{
2335392f7a3SLiteSpeed Tech    const unsigned char *p = buf;
2345392f7a3SLiteSpeed Tech    const unsigned char *const end = p + length;
2355392f7a3SLiteSpeed Tech    lsquic_ver_tag_t tag;
2365392f7a3SLiteSpeed Tech    unsigned dcil, scil, packet_len;
2375392f7a3SLiteSpeed Tech    unsigned char first_byte;
2385392f7a3SLiteSpeed Tech    const unsigned cid_len = 8;
2395392f7a3SLiteSpeed Tech
2405392f7a3SLiteSpeed Tech    if (length < 6)
2415392f7a3SLiteSpeed Tech        return 0;
2425392f7a3SLiteSpeed Tech    first_byte = *p++;
2435392f7a3SLiteSpeed Tech
2445392f7a3SLiteSpeed Tech    memcpy(&tag, p, 4);
2455392f7a3SLiteSpeed Tech    p += 4;
2465392f7a3SLiteSpeed Tech    if (0 == tag)
2475392f7a3SLiteSpeed Tech        return 0;   /* Client never sends version negotiation */
2485392f7a3SLiteSpeed Tech
2495392f7a3SLiteSpeed Tech    dcil = p[0] >> 4;
2505392f7a3SLiteSpeed Tech    if (dcil)
2515392f7a3SLiteSpeed Tech        dcil += 3;
2525392f7a3SLiteSpeed Tech    scil = p[0] & 0xF;
2535392f7a3SLiteSpeed Tech    if (scil)
2545392f7a3SLiteSpeed Tech        scil += 3;
2555392f7a3SLiteSpeed Tech    ++p;
2565392f7a3SLiteSpeed Tech
2575392f7a3SLiteSpeed Tech    if (!(dcil == cid_len && scil == 0))
2585392f7a3SLiteSpeed Tech        return 0;
2595392f7a3SLiteSpeed Tech
2605392f7a3SLiteSpeed Tech    packet_len = first_byte & 3;
2615392f7a3SLiteSpeed Tech
2625392f7a3SLiteSpeed Tech    if (end - p >= (ptrdiff_t) (dcil + scil + packet_len))
2635392f7a3SLiteSpeed Tech    {
2645392f7a3SLiteSpeed Tech        *tagp = tag;
2655392f7a3SLiteSpeed Tech        return 1;
2665392f7a3SLiteSpeed Tech    }
2675392f7a3SLiteSpeed Tech    else
2685392f7a3SLiteSpeed Tech        return 0;
2695392f7a3SLiteSpeed Tech}
2705392f7a3SLiteSpeed Tech
2715392f7a3SLiteSpeed Tech
2725392f7a3SLiteSpeed Techconst enum quic_frame_type lsquic_iquic_byte2type[0x100] =
2735392f7a3SLiteSpeed Tech{
2745392f7a3SLiteSpeed Tech    [0x00] = QUIC_FRAME_PADDING,
2755392f7a3SLiteSpeed Tech    [0x01] = QUIC_FRAME_PING,
2765392f7a3SLiteSpeed Tech    [0x02] = QUIC_FRAME_ACK,
2775392f7a3SLiteSpeed Tech    [0x03] = QUIC_FRAME_ACK,
2785392f7a3SLiteSpeed Tech    [0x04] = QUIC_FRAME_RST_STREAM,
2795392f7a3SLiteSpeed Tech    [0x05] = QUIC_FRAME_STOP_SENDING,
2805392f7a3SLiteSpeed Tech    [0x06] = QUIC_FRAME_CRYPTO,
2815392f7a3SLiteSpeed Tech    [0x07] = QUIC_FRAME_NEW_TOKEN,
2825392f7a3SLiteSpeed Tech    [0x08] = QUIC_FRAME_STREAM,
2835392f7a3SLiteSpeed Tech    [0x09] = QUIC_FRAME_STREAM,
2845392f7a3SLiteSpeed Tech    [0x0A] = QUIC_FRAME_STREAM,
2855392f7a3SLiteSpeed Tech    [0x0B] = QUIC_FRAME_STREAM,
2865392f7a3SLiteSpeed Tech    [0x0C] = QUIC_FRAME_STREAM,
2875392f7a3SLiteSpeed Tech    [0x0D] = QUIC_FRAME_STREAM,
2885392f7a3SLiteSpeed Tech    [0x0E] = QUIC_FRAME_STREAM,
2895392f7a3SLiteSpeed Tech    [0x0F] = QUIC_FRAME_STREAM,
2905392f7a3SLiteSpeed Tech    [0x10] = QUIC_FRAME_MAX_DATA,
2915392f7a3SLiteSpeed Tech    [0x11] = QUIC_FRAME_MAX_STREAM_DATA,
2925392f7a3SLiteSpeed Tech    [0x12] = QUIC_FRAME_MAX_STREAMS,
2935392f7a3SLiteSpeed Tech    [0x13] = QUIC_FRAME_MAX_STREAMS,
2945392f7a3SLiteSpeed Tech    [0x14] = QUIC_FRAME_BLOCKED,
2955392f7a3SLiteSpeed Tech    [0x15] = QUIC_FRAME_STREAM_BLOCKED,
2965392f7a3SLiteSpeed Tech    [0x16] = QUIC_FRAME_STREAMS_BLOCKED,
2975392f7a3SLiteSpeed Tech    [0x17] = QUIC_FRAME_STREAMS_BLOCKED,
2985392f7a3SLiteSpeed Tech    [0x18] = QUIC_FRAME_NEW_CONNECTION_ID,
2995392f7a3SLiteSpeed Tech    [0x19] = QUIC_FRAME_RETIRE_CONNECTION_ID,
3005392f7a3SLiteSpeed Tech    [0x1A] = QUIC_FRAME_PATH_CHALLENGE,
3015392f7a3SLiteSpeed Tech    [0x1B] = QUIC_FRAME_PATH_RESPONSE,
3025392f7a3SLiteSpeed Tech    [0x1C] = QUIC_FRAME_CONNECTION_CLOSE,
3035392f7a3SLiteSpeed Tech    [0x1D] = QUIC_FRAME_CONNECTION_CLOSE,
3045392f7a3SLiteSpeed Tech    [0x1E] = QUIC_FRAME_INVALID,
3055392f7a3SLiteSpeed Tech    [0x1F] = QUIC_FRAME_INVALID,
3065392f7a3SLiteSpeed Tech    [0x20] = QUIC_FRAME_INVALID,
3075392f7a3SLiteSpeed Tech    [0x21] = QUIC_FRAME_INVALID,
3085392f7a3SLiteSpeed Tech    [0x22] = QUIC_FRAME_INVALID,
3095392f7a3SLiteSpeed Tech    [0x23] = QUIC_FRAME_INVALID,
3105392f7a3SLiteSpeed Tech    [0x24] = QUIC_FRAME_INVALID,
3115392f7a3SLiteSpeed Tech    [0x25] = QUIC_FRAME_INVALID,
3125392f7a3SLiteSpeed Tech    [0x26] = QUIC_FRAME_INVALID,
3135392f7a3SLiteSpeed Tech    [0x27] = QUIC_FRAME_INVALID,
3145392f7a3SLiteSpeed Tech    [0x28] = QUIC_FRAME_INVALID,
3155392f7a3SLiteSpeed Tech    [0x29] = QUIC_FRAME_INVALID,
3165392f7a3SLiteSpeed Tech    [0x2A] = QUIC_FRAME_INVALID,
3175392f7a3SLiteSpeed Tech    [0x2B] = QUIC_FRAME_INVALID,
3185392f7a3SLiteSpeed Tech    [0x2C] = QUIC_FRAME_INVALID,
3195392f7a3SLiteSpeed Tech    [0x2D] = QUIC_FRAME_INVALID,
3205392f7a3SLiteSpeed Tech    [0x2E] = QUIC_FRAME_INVALID,
3215392f7a3SLiteSpeed Tech    [0x2F] = QUIC_FRAME_INVALID,
3225392f7a3SLiteSpeed Tech    [0x30] = QUIC_FRAME_INVALID,
3235392f7a3SLiteSpeed Tech    [0x31] = QUIC_FRAME_INVALID,
3245392f7a3SLiteSpeed Tech    [0x32] = QUIC_FRAME_INVALID,
3255392f7a3SLiteSpeed Tech    [0x33] = QUIC_FRAME_INVALID,
3265392f7a3SLiteSpeed Tech    [0x34] = QUIC_FRAME_INVALID,
3275392f7a3SLiteSpeed Tech    [0x35] = QUIC_FRAME_INVALID,
3285392f7a3SLiteSpeed Tech    [0x36] = QUIC_FRAME_INVALID,
3295392f7a3SLiteSpeed Tech    [0x37] = QUIC_FRAME_INVALID,
3305392f7a3SLiteSpeed Tech    [0x38] = QUIC_FRAME_INVALID,
3315392f7a3SLiteSpeed Tech    [0x39] = QUIC_FRAME_INVALID,
3325392f7a3SLiteSpeed Tech    [0x3A] = QUIC_FRAME_INVALID,
3335392f7a3SLiteSpeed Tech    [0x3B] = QUIC_FRAME_INVALID,
3345392f7a3SLiteSpeed Tech    [0x3C] = QUIC_FRAME_INVALID,
3355392f7a3SLiteSpeed Tech    [0x3D] = QUIC_FRAME_INVALID,
3365392f7a3SLiteSpeed Tech    [0x3E] = QUIC_FRAME_INVALID,
3375392f7a3SLiteSpeed Tech    [0x3F] = QUIC_FRAME_INVALID,
3385392f7a3SLiteSpeed Tech    [0x40] = QUIC_FRAME_INVALID,
3395392f7a3SLiteSpeed Tech    [0x41] = QUIC_FRAME_INVALID,
3405392f7a3SLiteSpeed Tech    [0x42] = QUIC_FRAME_INVALID,
3415392f7a3SLiteSpeed Tech    [0x43] = QUIC_FRAME_INVALID,
3425392f7a3SLiteSpeed Tech    [0x44] = QUIC_FRAME_INVALID,
3435392f7a3SLiteSpeed Tech    [0x45] = QUIC_FRAME_INVALID,
3445392f7a3SLiteSpeed Tech    [0x46] = QUIC_FRAME_INVALID,
3455392f7a3SLiteSpeed Tech    [0x47] = QUIC_FRAME_INVALID,
3465392f7a3SLiteSpeed Tech    [0x48] = QUIC_FRAME_INVALID,
3475392f7a3SLiteSpeed Tech    [0x49] = QUIC_FRAME_INVALID,
3485392f7a3SLiteSpeed Tech    [0x4A] = QUIC_FRAME_INVALID,
3495392f7a3SLiteSpeed Tech    [0x4B] = QUIC_FRAME_INVALID,
3505392f7a3SLiteSpeed Tech    [0x4C] = QUIC_FRAME_INVALID,
3515392f7a3SLiteSpeed Tech    [0x4D] = QUIC_FRAME_INVALID,
3525392f7a3SLiteSpeed Tech    [0x4E] = QUIC_FRAME_INVALID,
3535392f7a3SLiteSpeed Tech    [0x4F] = QUIC_FRAME_INVALID,
3545392f7a3SLiteSpeed Tech    [0x50] = QUIC_FRAME_INVALID,
3555392f7a3SLiteSpeed Tech    [0x51] = QUIC_FRAME_INVALID,
3565392f7a3SLiteSpeed Tech    [0x52] = QUIC_FRAME_INVALID,
3575392f7a3SLiteSpeed Tech    [0x53] = QUIC_FRAME_INVALID,
3585392f7a3SLiteSpeed Tech    [0x54] = QUIC_FRAME_INVALID,
3595392f7a3SLiteSpeed Tech    [0x55] = QUIC_FRAME_INVALID,
3605392f7a3SLiteSpeed Tech    [0x56] = QUIC_FRAME_INVALID,
3615392f7a3SLiteSpeed Tech    [0x57] = QUIC_FRAME_INVALID,
3625392f7a3SLiteSpeed Tech    [0x58] = QUIC_FRAME_INVALID,
3635392f7a3SLiteSpeed Tech    [0x59] = QUIC_FRAME_INVALID,
3645392f7a3SLiteSpeed Tech    [0x5A] = QUIC_FRAME_INVALID,
3655392f7a3SLiteSpeed Tech    [0x5B] = QUIC_FRAME_INVALID,
3665392f7a3SLiteSpeed Tech    [0x5C] = QUIC_FRAME_INVALID,
3675392f7a3SLiteSpeed Tech    [0x5D] = QUIC_FRAME_INVALID,
3685392f7a3SLiteSpeed Tech    [0x5E] = QUIC_FRAME_INVALID,
3695392f7a3SLiteSpeed Tech    [0x5F] = QUIC_FRAME_INVALID,
3705392f7a3SLiteSpeed Tech    [0x60] = QUIC_FRAME_INVALID,
3715392f7a3SLiteSpeed Tech    [0x61] = QUIC_FRAME_INVALID,
3725392f7a3SLiteSpeed Tech    [0x62] = QUIC_FRAME_INVALID,
3735392f7a3SLiteSpeed Tech    [0x63] = QUIC_FRAME_INVALID,
3745392f7a3SLiteSpeed Tech    [0x64] = QUIC_FRAME_INVALID,
3755392f7a3SLiteSpeed Tech    [0x65] = QUIC_FRAME_INVALID,
3765392f7a3SLiteSpeed Tech    [0x66] = QUIC_FRAME_INVALID,
3775392f7a3SLiteSpeed Tech    [0x67] = QUIC_FRAME_INVALID,
3785392f7a3SLiteSpeed Tech    [0x68] = QUIC_FRAME_INVALID,
3795392f7a3SLiteSpeed Tech    [0x69] = QUIC_FRAME_INVALID,
3805392f7a3SLiteSpeed Tech    [0x6A] = QUIC_FRAME_INVALID,
3815392f7a3SLiteSpeed Tech    [0x6B] = QUIC_FRAME_INVALID,
3825392f7a3SLiteSpeed Tech    [0x6C] = QUIC_FRAME_INVALID,
3835392f7a3SLiteSpeed Tech    [0x6D] = QUIC_FRAME_INVALID,
3845392f7a3SLiteSpeed Tech    [0x6E] = QUIC_FRAME_INVALID,
3855392f7a3SLiteSpeed Tech    [0x6F] = QUIC_FRAME_INVALID,
3865392f7a3SLiteSpeed Tech    [0x70] = QUIC_FRAME_INVALID,
3875392f7a3SLiteSpeed Tech    [0x71] = QUIC_FRAME_INVALID,
3885392f7a3SLiteSpeed Tech    [0x72] = QUIC_FRAME_INVALID,
3895392f7a3SLiteSpeed Tech    [0x73] = QUIC_FRAME_INVALID,
3905392f7a3SLiteSpeed Tech    [0x74] = QUIC_FRAME_INVALID,
3915392f7a3SLiteSpeed Tech    [0x75] = QUIC_FRAME_INVALID,
3925392f7a3SLiteSpeed Tech    [0x76] = QUIC_FRAME_INVALID,
3935392f7a3SLiteSpeed Tech    [0x77] = QUIC_FRAME_INVALID,
3945392f7a3SLiteSpeed Tech    [0x78] = QUIC_FRAME_INVALID,
3955392f7a3SLiteSpeed Tech    [0x79] = QUIC_FRAME_INVALID,
3965392f7a3SLiteSpeed Tech    [0x7A] = QUIC_FRAME_INVALID,
3975392f7a3SLiteSpeed Tech    [0x7B] = QUIC_FRAME_INVALID,
3985392f7a3SLiteSpeed Tech    [0x7C] = QUIC_FRAME_INVALID,
3995392f7a3SLiteSpeed Tech    [0x7D] = QUIC_FRAME_INVALID,
4005392f7a3SLiteSpeed Tech    [0x7E] = QUIC_FRAME_INVALID,
4015392f7a3SLiteSpeed Tech    [0x7F] = QUIC_FRAME_INVALID,
4025392f7a3SLiteSpeed Tech    [0x80] = QUIC_FRAME_INVALID,
4035392f7a3SLiteSpeed Tech    [0x81] = QUIC_FRAME_INVALID,
4045392f7a3SLiteSpeed Tech    [0x82] = QUIC_FRAME_INVALID,
4055392f7a3SLiteSpeed Tech    [0x83] = QUIC_FRAME_INVALID,
4065392f7a3SLiteSpeed Tech    [0x84] = QUIC_FRAME_INVALID,
4075392f7a3SLiteSpeed Tech    [0x85] = QUIC_FRAME_INVALID,
4085392f7a3SLiteSpeed Tech    [0x86] = QUIC_FRAME_INVALID,
4095392f7a3SLiteSpeed Tech    [0x87] = QUIC_FRAME_INVALID,
4105392f7a3SLiteSpeed Tech    [0x88] = QUIC_FRAME_INVALID,
4115392f7a3SLiteSpeed Tech    [0x89] = QUIC_FRAME_INVALID,
4125392f7a3SLiteSpeed Tech    [0x8A] = QUIC_FRAME_INVALID,
4135392f7a3SLiteSpeed Tech    [0x8B] = QUIC_FRAME_INVALID,
4145392f7a3SLiteSpeed Tech    [0x8C] = QUIC_FRAME_INVALID,
4155392f7a3SLiteSpeed Tech    [0x8D] = QUIC_FRAME_INVALID,
4165392f7a3SLiteSpeed Tech    [0x8E] = QUIC_FRAME_INVALID,
4175392f7a3SLiteSpeed Tech    [0x8F] = QUIC_FRAME_INVALID,
4185392f7a3SLiteSpeed Tech    [0x90] = QUIC_FRAME_INVALID,
4195392f7a3SLiteSpeed Tech    [0x91] = QUIC_FRAME_INVALID,
4205392f7a3SLiteSpeed Tech    [0x92] = QUIC_FRAME_INVALID,
4215392f7a3SLiteSpeed Tech    [0x93] = QUIC_FRAME_INVALID,
4225392f7a3SLiteSpeed Tech    [0x94] = QUIC_FRAME_INVALID,
4235392f7a3SLiteSpeed Tech    [0x95] = QUIC_FRAME_INVALID,
4245392f7a3SLiteSpeed Tech    [0x96] = QUIC_FRAME_INVALID,
4255392f7a3SLiteSpeed Tech    [0x97] = QUIC_FRAME_INVALID,
4265392f7a3SLiteSpeed Tech    [0x98] = QUIC_FRAME_INVALID,
4275392f7a3SLiteSpeed Tech    [0x99] = QUIC_FRAME_INVALID,
4285392f7a3SLiteSpeed Tech    [0x9A] = QUIC_FRAME_INVALID,
4295392f7a3SLiteSpeed Tech    [0x9B] = QUIC_FRAME_INVALID,
4305392f7a3SLiteSpeed Tech    [0x9C] = QUIC_FRAME_INVALID,
4315392f7a3SLiteSpeed Tech    [0x9D] = QUIC_FRAME_INVALID,
4325392f7a3SLiteSpeed Tech    [0x9E] = QUIC_FRAME_INVALID,
4335392f7a3SLiteSpeed Tech    [0x9F] = QUIC_FRAME_INVALID,
4345392f7a3SLiteSpeed Tech    [0xA0] = QUIC_FRAME_INVALID,
4355392f7a3SLiteSpeed Tech    [0xA1] = QUIC_FRAME_INVALID,
4365392f7a3SLiteSpeed Tech    [0xA2] = QUIC_FRAME_INVALID,
4375392f7a3SLiteSpeed Tech    [0xA3] = QUIC_FRAME_INVALID,
4385392f7a3SLiteSpeed Tech    [0xA4] = QUIC_FRAME_INVALID,
4395392f7a3SLiteSpeed Tech    [0xA5] = QUIC_FRAME_INVALID,
4405392f7a3SLiteSpeed Tech    [0xA6] = QUIC_FRAME_INVALID,
4415392f7a3SLiteSpeed Tech    [0xA7] = QUIC_FRAME_INVALID,
4425392f7a3SLiteSpeed Tech    [0xA8] = QUIC_FRAME_INVALID,
4435392f7a3SLiteSpeed Tech    [0xA9] = QUIC_FRAME_INVALID,
4445392f7a3SLiteSpeed Tech    [0xAA] = QUIC_FRAME_INVALID,
4455392f7a3SLiteSpeed Tech    [0xAB] = QUIC_FRAME_INVALID,
4465392f7a3SLiteSpeed Tech    [0xAC] = QUIC_FRAME_INVALID,
4475392f7a3SLiteSpeed Tech    [0xAD] = QUIC_FRAME_INVALID,
4485392f7a3SLiteSpeed Tech    [0xAE] = QUIC_FRAME_INVALID,
4495392f7a3SLiteSpeed Tech    [0xAF] = QUIC_FRAME_INVALID,
4505392f7a3SLiteSpeed Tech    [0xB0] = QUIC_FRAME_INVALID,
4515392f7a3SLiteSpeed Tech    [0xB1] = QUIC_FRAME_INVALID,
4525392f7a3SLiteSpeed Tech    [0xB2] = QUIC_FRAME_INVALID,
4535392f7a3SLiteSpeed Tech    [0xB3] = QUIC_FRAME_INVALID,
4545392f7a3SLiteSpeed Tech    [0xB4] = QUIC_FRAME_INVALID,
4555392f7a3SLiteSpeed Tech    [0xB5] = QUIC_FRAME_INVALID,
4565392f7a3SLiteSpeed Tech    [0xB6] = QUIC_FRAME_INVALID,
4575392f7a3SLiteSpeed Tech    [0xB7] = QUIC_FRAME_INVALID,
4585392f7a3SLiteSpeed Tech    [0xB8] = QUIC_FRAME_INVALID,
4595392f7a3SLiteSpeed Tech    [0xB9] = QUIC_FRAME_INVALID,
4605392f7a3SLiteSpeed Tech    [0xBA] = QUIC_FRAME_INVALID,
4615392f7a3SLiteSpeed Tech    [0xBB] = QUIC_FRAME_INVALID,
4625392f7a3SLiteSpeed Tech    [0xBC] = QUIC_FRAME_INVALID,
4635392f7a3SLiteSpeed Tech    [0xBD] = QUIC_FRAME_INVALID,
4645392f7a3SLiteSpeed Tech    [0xBE] = QUIC_FRAME_INVALID,
4655392f7a3SLiteSpeed Tech    [0xBF] = QUIC_FRAME_INVALID,
4665392f7a3SLiteSpeed Tech    [0xC0] = QUIC_FRAME_INVALID,
4675392f7a3SLiteSpeed Tech    [0xC1] = QUIC_FRAME_INVALID,
4685392f7a3SLiteSpeed Tech    [0xC2] = QUIC_FRAME_INVALID,
4695392f7a3SLiteSpeed Tech    [0xC3] = QUIC_FRAME_INVALID,
4705392f7a3SLiteSpeed Tech    [0xC4] = QUIC_FRAME_INVALID,
4715392f7a3SLiteSpeed Tech    [0xC5] = QUIC_FRAME_INVALID,
4725392f7a3SLiteSpeed Tech    [0xC6] = QUIC_FRAME_INVALID,
4735392f7a3SLiteSpeed Tech    [0xC7] = QUIC_FRAME_INVALID,
4745392f7a3SLiteSpeed Tech    [0xC8] = QUIC_FRAME_INVALID,
4755392f7a3SLiteSpeed Tech    [0xC9] = QUIC_FRAME_INVALID,
4765392f7a3SLiteSpeed Tech    [0xCA] = QUIC_FRAME_INVALID,
4775392f7a3SLiteSpeed Tech    [0xCB] = QUIC_FRAME_INVALID,
4785392f7a3SLiteSpeed Tech    [0xCC] = QUIC_FRAME_INVALID,
4795392f7a3SLiteSpeed Tech    [0xCD] = QUIC_FRAME_INVALID,
4805392f7a3SLiteSpeed Tech    [0xCE] = QUIC_FRAME_INVALID,
4815392f7a3SLiteSpeed Tech    [0xCF] = QUIC_FRAME_INVALID,
4825392f7a3SLiteSpeed Tech    [0xD0] = QUIC_FRAME_INVALID,
4835392f7a3SLiteSpeed Tech    [0xD1] = QUIC_FRAME_INVALID,
4845392f7a3SLiteSpeed Tech    [0xD2] = QUIC_FRAME_INVALID,
4855392f7a3SLiteSpeed Tech    [0xD3] = QUIC_FRAME_INVALID,
4865392f7a3SLiteSpeed Tech    [0xD4] = QUIC_FRAME_INVALID,
4875392f7a3SLiteSpeed Tech    [0xD5] = QUIC_FRAME_INVALID,
4885392f7a3SLiteSpeed Tech    [0xD6] = QUIC_FRAME_INVALID,
4895392f7a3SLiteSpeed Tech    [0xD7] = QUIC_FRAME_INVALID,
4905392f7a3SLiteSpeed Tech    [0xD8] = QUIC_FRAME_INVALID,
4915392f7a3SLiteSpeed Tech    [0xD9] = QUIC_FRAME_INVALID,
4925392f7a3SLiteSpeed Tech    [0xDA] = QUIC_FRAME_INVALID,
4935392f7a3SLiteSpeed Tech    [0xDB] = QUIC_FRAME_INVALID,
4945392f7a3SLiteSpeed Tech    [0xDC] = QUIC_FRAME_INVALID,
4955392f7a3SLiteSpeed Tech    [0xDD] = QUIC_FRAME_INVALID,
4965392f7a3SLiteSpeed Tech    [0xDE] = QUIC_FRAME_INVALID,
4975392f7a3SLiteSpeed Tech    [0xDF] = QUIC_FRAME_INVALID,
4985392f7a3SLiteSpeed Tech    [0xE0] = QUIC_FRAME_INVALID,
4995392f7a3SLiteSpeed Tech    [0xE1] = QUIC_FRAME_INVALID,
5005392f7a3SLiteSpeed Tech    [0xE2] = QUIC_FRAME_INVALID,
5015392f7a3SLiteSpeed Tech    [0xE3] = QUIC_FRAME_INVALID,
5025392f7a3SLiteSpeed Tech    [0xE4] = QUIC_FRAME_INVALID,
5035392f7a3SLiteSpeed Tech    [0xE5] = QUIC_FRAME_INVALID,
5045392f7a3SLiteSpeed Tech    [0xE6] = QUIC_FRAME_INVALID,
5055392f7a3SLiteSpeed Tech    [0xE7] = QUIC_FRAME_INVALID,
5065392f7a3SLiteSpeed Tech    [0xE8] = QUIC_FRAME_INVALID,
5075392f7a3SLiteSpeed Tech    [0xE9] = QUIC_FRAME_INVALID,
5085392f7a3SLiteSpeed Tech    [0xEA] = QUIC_FRAME_INVALID,
5095392f7a3SLiteSpeed Tech    [0xEB] = QUIC_FRAME_INVALID,
5105392f7a3SLiteSpeed Tech    [0xEC] = QUIC_FRAME_INVALID,
5115392f7a3SLiteSpeed Tech    [0xED] = QUIC_FRAME_INVALID,
5125392f7a3SLiteSpeed Tech    [0xEE] = QUIC_FRAME_INVALID,
5135392f7a3SLiteSpeed Tech    [0xEF] = QUIC_FRAME_INVALID,
5145392f7a3SLiteSpeed Tech    [0xF0] = QUIC_FRAME_INVALID,
5155392f7a3SLiteSpeed Tech    [0xF1] = QUIC_FRAME_INVALID,
5165392f7a3SLiteSpeed Tech    [0xF2] = QUIC_FRAME_INVALID,
5175392f7a3SLiteSpeed Tech    [0xF3] = QUIC_FRAME_INVALID,
5185392f7a3SLiteSpeed Tech    [0xF4] = QUIC_FRAME_INVALID,
5195392f7a3SLiteSpeed Tech    [0xF5] = QUIC_FRAME_INVALID,
5205392f7a3SLiteSpeed Tech    [0xF6] = QUIC_FRAME_INVALID,
5215392f7a3SLiteSpeed Tech    [0xF7] = QUIC_FRAME_INVALID,
5225392f7a3SLiteSpeed Tech    [0xF8] = QUIC_FRAME_INVALID,
5235392f7a3SLiteSpeed Tech    [0xF9] = QUIC_FRAME_INVALID,
5245392f7a3SLiteSpeed Tech    [0xFA] = QUIC_FRAME_INVALID,
5255392f7a3SLiteSpeed Tech    [0xFB] = QUIC_FRAME_INVALID,
5265392f7a3SLiteSpeed Tech    [0xFC] = QUIC_FRAME_INVALID,
5275392f7a3SLiteSpeed Tech    [0xFD] = QUIC_FRAME_INVALID,
5285392f7a3SLiteSpeed Tech    [0xFE] = QUIC_FRAME_INVALID,
5295392f7a3SLiteSpeed Tech    [0xFF] = QUIC_FRAME_INVALID,
5305392f7a3SLiteSpeed Tech};
5315392f7a3SLiteSpeed Tech
5325392f7a3SLiteSpeed Tech
5335392f7a3SLiteSpeed Tech#if __GNUC__
5345392f7a3SLiteSpeed Tech#   define popcount __builtin_popcount
5355392f7a3SLiteSpeed Tech#else
5365392f7a3SLiteSpeed Techstatic int
5375392f7a3SLiteSpeed Techpopcount (unsigned v)
5385392f7a3SLiteSpeed Tech{
5395392f7a3SLiteSpeed Tech    int count, i;
5405392f7a3SLiteSpeed Tech    for (i = 0, count = 0; i < sizeof(v) * 8; ++i)
5415392f7a3SLiteSpeed Tech        if (v & (1 << i))
5425392f7a3SLiteSpeed Tech            ++count;
5435392f7a3SLiteSpeed Tech    return count;
5445392f7a3SLiteSpeed Tech}
5455392f7a3SLiteSpeed Tech
5465392f7a3SLiteSpeed Tech
5475392f7a3SLiteSpeed Tech#endif
5485392f7a3SLiteSpeed Tech
5495392f7a3SLiteSpeed Tech
5505392f7a3SLiteSpeed Techint
5515392f7a3SLiteSpeed Techlsquic_Q046_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz,
5525392f7a3SLiteSpeed Tech         const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions)
5535392f7a3SLiteSpeed Tech{
5545392f7a3SLiteSpeed Tech    unsigned slen, dlen;
5555392f7a3SLiteSpeed Tech    size_t need;
5565392f7a3SLiteSpeed Tech    int r;
5575392f7a3SLiteSpeed Tech
5585392f7a3SLiteSpeed Tech    need = 1 /* Type */ + 4 /* Packet number */ + 1 /* SCIL */
5595392f7a3SLiteSpeed Tech                        + scid->len + dcid->len + popcount(versions) * 4;
5605392f7a3SLiteSpeed Tech
5615392f7a3SLiteSpeed Tech    if (need > bufsz)
5625392f7a3SLiteSpeed Tech        return -1;
5635392f7a3SLiteSpeed Tech
5645392f7a3SLiteSpeed Tech    *buf++ = 0x80 | 0x40 | rand();
5655392f7a3SLiteSpeed Tech    memset(buf, 0, 4);
5665392f7a3SLiteSpeed Tech    buf += 4;
5675392f7a3SLiteSpeed Tech
5685392f7a3SLiteSpeed Tech    /* From [draft-ietf-quic-transport-11], Section 4.3:
5695392f7a3SLiteSpeed Tech     *
5705392f7a3SLiteSpeed Tech     *  The server MUST include the value from the Source Connection ID field
5715392f7a3SLiteSpeed Tech     *  of the packet it receives in the Destination Connection ID field.
5725392f7a3SLiteSpeed Tech     *  The value for Source Connection ID MUST be copied from the
5735392f7a3SLiteSpeed Tech     *  Destination Connection ID of the received packet, which is initially
5745392f7a3SLiteSpeed Tech     *  randomly selected by a client.  Echoing both connection IDs gives
5755392f7a3SLiteSpeed Tech     *  clients some assurance that the server received the packet and that
5765392f7a3SLiteSpeed Tech     *  the Version Negotiation packet was not generated by an off-path
5775392f7a3SLiteSpeed Tech     *  attacker.
5785392f7a3SLiteSpeed Tech     */
5795392f7a3SLiteSpeed Tech
5805392f7a3SLiteSpeed Tech    dlen = dcid->len;
5815392f7a3SLiteSpeed Tech    if (dlen)
5825392f7a3SLiteSpeed Tech        dlen -= 3;
5835392f7a3SLiteSpeed Tech    slen = scid->len;
5845392f7a3SLiteSpeed Tech    if (slen)
5855392f7a3SLiteSpeed Tech        slen -= 3;
5865392f7a3SLiteSpeed Tech    *buf++ = (dlen << 4) | slen;
5875392f7a3SLiteSpeed Tech
5885392f7a3SLiteSpeed Tech    memcpy(buf, dcid->idbuf, dcid->len);
5895392f7a3SLiteSpeed Tech    buf += dcid->len;
5905392f7a3SLiteSpeed Tech    memcpy(buf, scid->idbuf, scid->len);
5915392f7a3SLiteSpeed Tech    buf += scid->len;
5925392f7a3SLiteSpeed Tech
5935392f7a3SLiteSpeed Tech    r = lsquic_gen_ver_tags(buf, bufsz - 1 - 4 - 1 - dcid->len - scid->len,
5945392f7a3SLiteSpeed Tech                                                                    versions);
5955392f7a3SLiteSpeed Tech    if (r < 0)
5965392f7a3SLiteSpeed Tech        return -1;
5975392f7a3SLiteSpeed Tech    assert((unsigned) r == popcount(versions) * 4u);
5985392f7a3SLiteSpeed Tech
5995392f7a3SLiteSpeed Tech    return need;
6005392f7a3SLiteSpeed Tech}
6015392f7a3SLiteSpeed Tech
6025392f7a3SLiteSpeed Tech
603