1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech#include <assert.h>
39626cfc2SDmitri Tikhonov#include <string.h>
49626cfc2SDmitri Tikhonov#include <sys/queue.h>
59626cfc2SDmitri Tikhonov#include <sys/types.h>
69626cfc2SDmitri Tikhonov
75392f7a3SLiteSpeed Tech#include "lsquic.h"
89626cfc2SDmitri Tikhonov#include "lsquic_types.h"
99626cfc2SDmitri Tikhonov#include "lsquic_int_types.h"
109626cfc2SDmitri Tikhonov#include "lsquic_packet_common.h"
119626cfc2SDmitri Tikhonov#include "lsquic_packet_in.h"
129626cfc2SDmitri Tikhonov#include "lsquic_parse_common.h"
139626cfc2SDmitri Tikhonov#include "lsquic_parse.h"
145392f7a3SLiteSpeed Tech#include "lsquic_enc_sess.h"
155392f7a3SLiteSpeed Tech#include "lsquic_version.h"
167a8b2eceSDmitri Tikhonov#include "lsquic_qtags.h"
175392f7a3SLiteSpeed Tech
185392f7a3SLiteSpeed Tech
195392f7a3SLiteSpeed Techstatic int
207a8b2eceSDmitri Tikhonovparse_ietf_v1_or_Q046plus_long_begin (struct lsquic_packet_in *packet_in,
215392f7a3SLiteSpeed Tech                size_t length, int is_server, unsigned cid_len,
225392f7a3SLiteSpeed Tech                struct packin_parse_state *state)
235392f7a3SLiteSpeed Tech{
245392f7a3SLiteSpeed Tech    lsquic_ver_tag_t tag;
255392f7a3SLiteSpeed Tech
265392f7a3SLiteSpeed Tech    if (length >= 5)
275392f7a3SLiteSpeed Tech    {
285392f7a3SLiteSpeed Tech        memcpy(&tag, packet_in->pi_data + 1, 4);
297a8b2eceSDmitri Tikhonov        switch (tag)
307a8b2eceSDmitri Tikhonov        {
317a8b2eceSDmitri Tikhonov        case TAG('Q', '0', '4', '6'):
325392f7a3SLiteSpeed Tech            return lsquic_Q046_parse_packet_in_long_begin(packet_in, length,
335392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
347a8b2eceSDmitri Tikhonov        case TAG('Q', '0', '5', '0'):
357a8b2eceSDmitri Tikhonov            return lsquic_Q050_parse_packet_in_long_begin(packet_in, length,
367a8b2eceSDmitri Tikhonov                                                    is_server, cid_len, state);
377a8b2eceSDmitri Tikhonov        default:
385392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in, length,
395392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
407a8b2eceSDmitri Tikhonov        }
415392f7a3SLiteSpeed Tech    }
425392f7a3SLiteSpeed Tech    else
435392f7a3SLiteSpeed Tech        return -1;
445392f7a3SLiteSpeed Tech}
455392f7a3SLiteSpeed Tech
465392f7a3SLiteSpeed Tech
475392f7a3SLiteSpeed Techstatic int (* const parse_begin_funcs[32]) (struct lsquic_packet_in *,
485392f7a3SLiteSpeed Tech                size_t length, int is_server, unsigned cid_len,
495392f7a3SLiteSpeed Tech                struct packin_parse_state *) =
505392f7a3SLiteSpeed Tech{
515392f7a3SLiteSpeed Tech    /* Xs vary, Gs are iGnored: */
525392f7a3SLiteSpeed Tech#define PBEL(mask) [(mask) >> 3]
535392f7a3SLiteSpeed Tech    /* 1X11 XGGG: */
545392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x20|0x10|0x08)  = lsquic_Q046_parse_packet_in_long_begin,
555392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x20|0x10|0x08)  = lsquic_Q046_parse_packet_in_long_begin,
565392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_long_begin,
575392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_long_begin,
585392f7a3SLiteSpeed Tech    /* 1X00 XGGG: */
597a8b2eceSDmitri Tikhonov    PBEL(0x80|0x40|0x00|0x00|0x08)  = parse_ietf_v1_or_Q046plus_long_begin,
607a8b2eceSDmitri Tikhonov    PBEL(0x80|0x00|0x00|0x00|0x08)  = parse_ietf_v1_or_Q046plus_long_begin,
617a8b2eceSDmitri Tikhonov    PBEL(0x80|0x40|0x00|0x00|0x00)  = parse_ietf_v1_or_Q046plus_long_begin,
627a8b2eceSDmitri Tikhonov    PBEL(0x80|0x00|0x00|0x00|0x00)  = parse_ietf_v1_or_Q046plus_long_begin,
635392f7a3SLiteSpeed Tech    /* 1X01 XGGG: */
647a8b2eceSDmitri Tikhonov    PBEL(0x80|0x40|0x00|0x10|0x08)  = parse_ietf_v1_or_Q046plus_long_begin,
657a8b2eceSDmitri Tikhonov    PBEL(0x80|0x00|0x00|0x10|0x08)  = parse_ietf_v1_or_Q046plus_long_begin,
667a8b2eceSDmitri Tikhonov    PBEL(0x80|0x40|0x00|0x10|0x00)  = parse_ietf_v1_or_Q046plus_long_begin,
677a8b2eceSDmitri Tikhonov    PBEL(0x80|0x00|0x00|0x10|0x00)  = parse_ietf_v1_or_Q046plus_long_begin,
685392f7a3SLiteSpeed Tech    /* 1X10 XGGG: */
697a8b2eceSDmitri Tikhonov    PBEL(0x80|0x40|0x20|0x00|0x08)  = parse_ietf_v1_or_Q046plus_long_begin,
707a8b2eceSDmitri Tikhonov    PBEL(0x80|0x00|0x20|0x00|0x08)  = parse_ietf_v1_or_Q046plus_long_begin,
717a8b2eceSDmitri Tikhonov    PBEL(0x80|0x40|0x20|0x00|0x00)  = parse_ietf_v1_or_Q046plus_long_begin,
727a8b2eceSDmitri Tikhonov    PBEL(0x80|0x00|0x20|0x00|0x00)  = parse_ietf_v1_or_Q046plus_long_begin,
735392f7a3SLiteSpeed Tech    /* 01XX XGGG */
745392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x00|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
755392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x00|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
765392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x10|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
775392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x10|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
785392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x00|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
795392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x00|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
805392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x10|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
815392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x10|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
825392f7a3SLiteSpeed Tech    /* 00XX 0GGG */
835392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x00|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
845392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x10|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
855392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x00|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
865392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
875392f7a3SLiteSpeed Tech    /* 00XX 1GGG */
885392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x00|0x08)  = lsquic_gquic_parse_packet_in_begin,
895392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x10|0x08)  = lsquic_gquic_parse_packet_in_begin,
905392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x00|0x08)  = lsquic_gquic_parse_packet_in_begin,
915392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x10|0x08)  = lsquic_gquic_parse_packet_in_begin,
925392f7a3SLiteSpeed Tech#undef PBEL
935392f7a3SLiteSpeed Tech};
949626cfc2SDmitri Tikhonov
959626cfc2SDmitri Tikhonov
969626cfc2SDmitri Tikhonovint
975392f7a3SLiteSpeed Techlsquic_parse_packet_in_server_begin (struct lsquic_packet_in *packet_in,
985392f7a3SLiteSpeed Tech                    size_t length, int is_server_UNUSED, unsigned cid_len,
995392f7a3SLiteSpeed Tech                    struct packin_parse_state *state)
1005392f7a3SLiteSpeed Tech{
1015392f7a3SLiteSpeed Tech    if (length)
1025392f7a3SLiteSpeed Tech        return parse_begin_funcs[ packet_in->pi_data[0] >> 3 ](
1035392f7a3SLiteSpeed Tech                                    packet_in, length, 1, cid_len, state);
1045392f7a3SLiteSpeed Tech    else
1055392f7a3SLiteSpeed Tech        return -1;
1065392f7a3SLiteSpeed Tech
1075392f7a3SLiteSpeed Tech}
1085392f7a3SLiteSpeed Tech
1095392f7a3SLiteSpeed Tech
1105392f7a3SLiteSpeed Techint
1119626cfc2SDmitri Tikhonovlsquic_parse_packet_in_begin (lsquic_packet_in_t *packet_in, size_t length,
1125392f7a3SLiteSpeed Tech            int is_server, unsigned cid_len, struct packin_parse_state *state)
1139626cfc2SDmitri Tikhonov{
1149626cfc2SDmitri Tikhonov    if (length > 0)
1159626cfc2SDmitri Tikhonov    {
1165392f7a3SLiteSpeed Tech        switch (packet_in->pi_data[0] & 0xC0)
1179626cfc2SDmitri Tikhonov        {
118c7d81ce1SDmitri Tikhonov        case 0xC0:
1195392f7a3SLiteSpeed Tech        case 0x80:
1207a8b2eceSDmitri Tikhonov            return parse_ietf_v1_or_Q046plus_long_begin(packet_in,
1215392f7a3SLiteSpeed Tech                                        length, is_server, cid_len, state);
1225392f7a3SLiteSpeed Tech        case 0x00:
1239626cfc2SDmitri Tikhonov            return lsquic_gquic_parse_packet_in_begin(packet_in, length,
1245392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1259626cfc2SDmitri Tikhonov        default:
1265392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in,
1275392f7a3SLiteSpeed Tech                                        length, is_server, cid_len, state);
1289626cfc2SDmitri Tikhonov        }
1299626cfc2SDmitri Tikhonov    }
1309626cfc2SDmitri Tikhonov    else
1319626cfc2SDmitri Tikhonov        return -1;
1329626cfc2SDmitri Tikhonov}
1339626cfc2SDmitri Tikhonov
1349626cfc2SDmitri Tikhonov
1359626cfc2SDmitri Tikhonovint
1365392f7a3SLiteSpeed Techlsquic_ietf_v1_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
1375392f7a3SLiteSpeed Tech            size_t length, int is_server, unsigned cid_len,
1385392f7a3SLiteSpeed Tech            struct packin_parse_state *state)
1399626cfc2SDmitri Tikhonov{
1409626cfc2SDmitri Tikhonov    if (length > 0)
1419626cfc2SDmitri Tikhonov    {
1429626cfc2SDmitri Tikhonov        if (0 == (packet_in->pi_data[0] & 0x80))
1435392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in, length,
1445392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1459626cfc2SDmitri Tikhonov        else
1465392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in, length,
1475392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1489626cfc2SDmitri Tikhonov    }
1499626cfc2SDmitri Tikhonov    else
1509626cfc2SDmitri Tikhonov        return -1;
1519626cfc2SDmitri Tikhonov}
1529626cfc2SDmitri Tikhonov
1539626cfc2SDmitri Tikhonov
1545392f7a3SLiteSpeed Techint
1555392f7a3SLiteSpeed Techlsquic_Q046_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
1565392f7a3SLiteSpeed Tech            size_t length, int is_server, unsigned cid_len,
1575392f7a3SLiteSpeed Tech            struct packin_parse_state *state)
1585392f7a3SLiteSpeed Tech{
1595392f7a3SLiteSpeed Tech    assert(!is_server);
1605392f7a3SLiteSpeed Tech    assert(cid_len == GQUIC_CID_LEN);
1615392f7a3SLiteSpeed Tech    if (length > 0)
1625392f7a3SLiteSpeed Tech    {
1635392f7a3SLiteSpeed Tech        if (0 == (packet_in->pi_data[0] & 0x80))
1645392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in, length,
1655392f7a3SLiteSpeed Tech                                    is_server, is_server ? cid_len : 0, state);
1665392f7a3SLiteSpeed Tech        else
1675392f7a3SLiteSpeed Tech            return lsquic_Q046_parse_packet_in_long_begin(packet_in, length,
1685392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1695392f7a3SLiteSpeed Tech    }
1705392f7a3SLiteSpeed Tech    else
1715392f7a3SLiteSpeed Tech        return -1;
1725392f7a3SLiteSpeed Tech}
1735392f7a3SLiteSpeed Tech
1745392f7a3SLiteSpeed Tech
1757a8b2eceSDmitri Tikhonovint
1767a8b2eceSDmitri Tikhonovlsquic_Q050_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
1777a8b2eceSDmitri Tikhonov            size_t length, int is_server, unsigned cid_len,
1787a8b2eceSDmitri Tikhonov            struct packin_parse_state *state)
1797a8b2eceSDmitri Tikhonov{
1807a8b2eceSDmitri Tikhonov    assert(!is_server);
1817a8b2eceSDmitri Tikhonov    assert(cid_len == GQUIC_CID_LEN);
1827a8b2eceSDmitri Tikhonov    if (length > 0)
1837a8b2eceSDmitri Tikhonov    {
1847a8b2eceSDmitri Tikhonov        if (0 == (packet_in->pi_data[0] & 0x80))
1857a8b2eceSDmitri Tikhonov            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in, length,
1867a8b2eceSDmitri Tikhonov                                    is_server, is_server ? cid_len : 0, state);
1877a8b2eceSDmitri Tikhonov        else
1887a8b2eceSDmitri Tikhonov            return lsquic_Q050_parse_packet_in_long_begin(packet_in, length,
1897a8b2eceSDmitri Tikhonov                                                    is_server, cid_len, state);
1907a8b2eceSDmitri Tikhonov    }
1917a8b2eceSDmitri Tikhonov    else
1927a8b2eceSDmitri Tikhonov        return -1;
1937a8b2eceSDmitri Tikhonov}
1947a8b2eceSDmitri Tikhonov
1957a8b2eceSDmitri Tikhonov
1965392f7a3SLiteSpeed Tech/* TODO This function uses the full packet parsing functionality to get at
1975392f7a3SLiteSpeed Tech * the CID.  This is an overkill and could be optimized -- at the cost of
1985392f7a3SLiteSpeed Tech * some code duplication, of course.
1995392f7a3SLiteSpeed Tech */
2005392f7a3SLiteSpeed Techint
2015392f7a3SLiteSpeed Techlsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
2025392f7a3SLiteSpeed Tech                                                            lsquic_cid_t *cid)
2035392f7a3SLiteSpeed Tech{
2045392f7a3SLiteSpeed Tech    struct lsquic_packet_in packet_in;
2055392f7a3SLiteSpeed Tech    struct packin_parse_state pps;
2065392f7a3SLiteSpeed Tech    int s;
2075392f7a3SLiteSpeed Tech
2085392f7a3SLiteSpeed Tech    packet_in.pi_data = (unsigned char *) buf;
2095392f7a3SLiteSpeed Tech    s = lsquic_parse_packet_in_server_begin(&packet_in, bufsz, 1, 8, &pps);
2105392f7a3SLiteSpeed Tech    if (0 == s && (packet_in.pi_flags & PI_CONN_ID))
2115392f7a3SLiteSpeed Tech    {
2125392f7a3SLiteSpeed Tech        *cid = packet_in.pi_dcid;
2135392f7a3SLiteSpeed Tech        return 0;
2145392f7a3SLiteSpeed Tech    }
2155392f7a3SLiteSpeed Tech    else
2165392f7a3SLiteSpeed Tech        return -1;
2175392f7a3SLiteSpeed Tech}
2185392f7a3SLiteSpeed Tech
2195392f7a3SLiteSpeed Tech
220c2faf032SDmitri Tikhonovint
221c2faf032SDmitri Tikhonovlsquic_dcid_from_packet (const unsigned char *buf, size_t bufsz,
222c2faf032SDmitri Tikhonov                                unsigned server_cid_len, unsigned *cid_len)
223c2faf032SDmitri Tikhonov{
224c2faf032SDmitri Tikhonov    const unsigned char *p;
225c2faf032SDmitri Tikhonov    unsigned dcil, scil;
226c2faf032SDmitri Tikhonov
227c2faf032SDmitri Tikhonov    if (bufsz < 9)
228c2faf032SDmitri Tikhonov        return -1;
229c2faf032SDmitri Tikhonov
230c2faf032SDmitri Tikhonov    switch (buf[0] >> 3)
231c2faf032SDmitri Tikhonov    {
232c2faf032SDmitri Tikhonov    /* Xs vary, Gs are iGnored: */
233c2faf032SDmitri Tikhonov    /* 1X11 XGGG: */
234c2faf032SDmitri Tikhonov    case (0x80|0x40|0x20|0x10|0x08) >> 3:
235c2faf032SDmitri Tikhonov    case (0x80|0x00|0x20|0x10|0x08) >> 3:
236c2faf032SDmitri Tikhonov    case (0x80|0x40|0x20|0x10|0x00) >> 3:
237c2faf032SDmitri Tikhonov    case (0x80|0x00|0x20|0x10|0x00) >> 3:
238c2faf032SDmitri Tikhonov  Q046_long:
239c2faf032SDmitri Tikhonov        /* lsquic_Q046_parse_packet_in_long_begin */
240c2faf032SDmitri Tikhonov        if (bufsz < 14)
241c2faf032SDmitri Tikhonov            return -1;
242c2faf032SDmitri Tikhonov        p = buf + 5;
243c2faf032SDmitri Tikhonov        dcil = p[0] >> 4;
244c2faf032SDmitri Tikhonov        if (dcil)
245c2faf032SDmitri Tikhonov            dcil += 3;
246c2faf032SDmitri Tikhonov        scil = p[0] & 0xF;
247c2faf032SDmitri Tikhonov        if (scil)
248c2faf032SDmitri Tikhonov            scil += 3;
249c2faf032SDmitri Tikhonov        ++p;
250c2faf032SDmitri Tikhonov        if (dcil == GQUIC_CID_LEN && scil == 0)
251c2faf032SDmitri Tikhonov        {
252c2faf032SDmitri Tikhonov            *cid_len = GQUIC_CID_LEN;
253c2faf032SDmitri Tikhonov            return (unsigned) (p - buf);
254c2faf032SDmitri Tikhonov        }
255c2faf032SDmitri Tikhonov        else
256c2faf032SDmitri Tikhonov            return -1;
257c2faf032SDmitri Tikhonov    /* 1X00 XGGG: */
258c2faf032SDmitri Tikhonov    /*
259c2faf032SDmitri Tikhonov    case (0x80|0x40|0x00|0x00|0x08) >> 3:
260c2faf032SDmitri Tikhonov    case (0x80|0x00|0x00|0x00|0x08) >> 3:
261c2faf032SDmitri Tikhonov    case (0x80|0x40|0x00|0x00|0x00) >> 3:
262c2faf032SDmitri Tikhonov    case (0x80|0x00|0x00|0x00|0x00) >> 3:
263c2faf032SDmitri Tikhonov    case (0x80|0x40|0x00|0x10|0x08) >> 3:
264c2faf032SDmitri Tikhonov    case (0x80|0x00|0x00|0x10|0x08) >> 3:
265c2faf032SDmitri Tikhonov    case (0x80|0x40|0x00|0x10|0x00) >> 3:
266c2faf032SDmitri Tikhonov    case (0x80|0x00|0x00|0x10|0x00) >> 3:
267c2faf032SDmitri Tikhonov    case (0x80|0x40|0x20|0x00|0x08) >> 3:
268c2faf032SDmitri Tikhonov    case (0x80|0x00|0x20|0x00|0x08) >> 3:
269c2faf032SDmitri Tikhonov    case (0x80|0x40|0x20|0x00|0x00) >> 3:
270c2faf032SDmitri Tikhonov    case (0x80|0x00|0x20|0x00|0x00) >> 3:
271c2faf032SDmitri Tikhonov    */
272c2faf032SDmitri Tikhonov    default:
273c2faf032SDmitri Tikhonov        /* parse_ietf_v1_or_Q046plus_long_begin */
274c2faf032SDmitri Tikhonov        if (buf[4] == (unsigned) '6')
275c2faf032SDmitri Tikhonov            goto Q046_long;
276c2faf032SDmitri Tikhonov        /* lsquic_Q050_parse_packet_in_long_begin or
277c2faf032SDmitri Tikhonov            lsquic_ietf_v1_parse_packet_in_long_begin */
278c2faf032SDmitri Tikhonov        if (bufsz < 14)
279c2faf032SDmitri Tikhonov            return -1;
280c2faf032SDmitri Tikhonov        dcil = buf[5];
281c2faf032SDmitri Tikhonov        if (dcil <= MAX_CID_LEN && 6 + dcil < bufsz)
282c2faf032SDmitri Tikhonov        {
283c2faf032SDmitri Tikhonov            *cid_len = dcil;
284c2faf032SDmitri Tikhonov            return 6;
285c2faf032SDmitri Tikhonov        }
286c2faf032SDmitri Tikhonov        else
287c2faf032SDmitri Tikhonov            return -1;
288c2faf032SDmitri Tikhonov    /* 01XX XGGG */
289c2faf032SDmitri Tikhonov    case (0x00|0x40|0x00|0x00|0x00) >> 3:
290c2faf032SDmitri Tikhonov    case (0x00|0x40|0x00|0x00|0x08) >> 3:
291c2faf032SDmitri Tikhonov    case (0x00|0x40|0x00|0x10|0x00) >> 3:
292c2faf032SDmitri Tikhonov    case (0x00|0x40|0x00|0x10|0x08) >> 3:
293c2faf032SDmitri Tikhonov    case (0x00|0x40|0x20|0x00|0x00) >> 3:
294c2faf032SDmitri Tikhonov    case (0x00|0x40|0x20|0x00|0x08) >> 3:
295c2faf032SDmitri Tikhonov    case (0x00|0x40|0x20|0x10|0x00) >> 3:
296c2faf032SDmitri Tikhonov    case (0x00|0x40|0x20|0x10|0x08) >> 3:
297c2faf032SDmitri Tikhonov        /* lsquic_ietf_v1_parse_packet_in_short_begin */
298c2faf032SDmitri Tikhonov        if (1 + server_cid_len <= bufsz)
299c2faf032SDmitri Tikhonov        {
300c2faf032SDmitri Tikhonov            *cid_len = server_cid_len;
301c2faf032SDmitri Tikhonov            return 1;
302c2faf032SDmitri Tikhonov        }
303c2faf032SDmitri Tikhonov        else
304c2faf032SDmitri Tikhonov            return -1;
305c2faf032SDmitri Tikhonov    /* 00XX 0GGG */
306c2faf032SDmitri Tikhonov    case (0x00|0x00|0x00|0x00|0x00) >> 3:
307c2faf032SDmitri Tikhonov    case (0x00|0x00|0x00|0x10|0x00) >> 3:
308c2faf032SDmitri Tikhonov    case (0x00|0x00|0x20|0x00|0x00) >> 3:
309c2faf032SDmitri Tikhonov    case (0x00|0x00|0x20|0x10|0x00) >> 3:
310c2faf032SDmitri Tikhonov        /* lsquic_Q046_parse_packet_in_short_begin */
311c2faf032SDmitri Tikhonov        if (1 + server_cid_len <= bufsz && (buf[0] & 0x40))
312c2faf032SDmitri Tikhonov        {
313c2faf032SDmitri Tikhonov            *cid_len = server_cid_len;
314c2faf032SDmitri Tikhonov            return 1;
315c2faf032SDmitri Tikhonov        }
316c2faf032SDmitri Tikhonov        else
317c2faf032SDmitri Tikhonov            return -1;
318c2faf032SDmitri Tikhonov    /* 00XX 1GGG */
319c2faf032SDmitri Tikhonov    case (0x00|0x00|0x00|0x00|0x08) >> 3:
320c2faf032SDmitri Tikhonov    case (0x00|0x00|0x00|0x10|0x08) >> 3:
321c2faf032SDmitri Tikhonov    case (0x00|0x00|0x20|0x00|0x08) >> 3:
322c2faf032SDmitri Tikhonov    case (0x00|0x00|0x20|0x10|0x08) >> 3:
323c2faf032SDmitri Tikhonov        /* lsquic_gquic_parse_packet_in_begin */
324c2faf032SDmitri Tikhonov        if (1 + GQUIC_CID_LEN <= bufsz
325c2faf032SDmitri Tikhonov                        && (buf[0] & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID))
326c2faf032SDmitri Tikhonov        {
327c2faf032SDmitri Tikhonov            *cid_len = server_cid_len;
328c2faf032SDmitri Tikhonov            return 1;
329c2faf032SDmitri Tikhonov        }
330c2faf032SDmitri Tikhonov        else
331c2faf032SDmitri Tikhonov            return -1;
332c2faf032SDmitri Tikhonov    }
333c2faf032SDmitri Tikhonov}
334c2faf032SDmitri Tikhonov
335c2faf032SDmitri Tikhonov
336fb73393fSDmitri Tikhonov/* See [draft-ietf-quic-transport-28], Section 12.4 (Table 3) */
337fb73393fSDmitri Tikhonovconst enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
3385392f7a3SLiteSpeed Tech{
33926e8f082SDmitri Tikhonov    [LSQVER_I001] = {
340b1a7c3f9SDmitri Tikhonov    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
341b1a7c3f9SDmitri Tikhonov                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
342b1a7c3f9SDmitri Tikhonov    [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
343b1a7c3f9SDmitri Tikhonov                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
3444051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
3454051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
3464051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
3474051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_STREAMS_BLOCKED
3484051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
34926e8f082SDmitri Tikhonov                    | QUIC_FTBIT_PATH_CHALLENGE
350b1a7c3f9SDmitri Tikhonov                    | QUIC_FTBIT_DATAGRAM
3514051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_RETIRE_CONNECTION_ID,
3524051ae3aSDmitri Tikhonov    [ENC_LEV_INIT]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
3534051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
3544051ae3aSDmitri Tikhonov    [ENC_LEV_FORW]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
3554051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
3564051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
3574051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_BLOCKED
3584051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
3594051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
3604051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_STREAMS_BLOCKED
3614051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
3624051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
3634051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
3644051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
3654051ae3aSDmitri Tikhonov                    | QUIC_FTBIT_TIMESTAMP
366b1a7c3f9SDmitri Tikhonov                    | QUIC_FTBIT_DATAGRAM
3674051ae3aSDmitri Tikhonov                    ,
3684051ae3aSDmitri Tikhonov    },
36926e8f082SDmitri Tikhonov    [LSQVER_ID29] = {
370fb73393fSDmitri Tikhonov    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
371fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
372fb73393fSDmitri Tikhonov    [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
373fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
374fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
375fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
376fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
377fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_STREAMS_BLOCKED
378fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
379fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
38026e8f082SDmitri Tikhonov                    | QUIC_FTBIT_DATAGRAM
381fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_RETIRE_CONNECTION_ID,
382fb73393fSDmitri Tikhonov    [ENC_LEV_INIT]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
383fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
384fb73393fSDmitri Tikhonov    [ENC_LEV_FORW]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
385fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
386fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
387fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_BLOCKED
388fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
389fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
390fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_STREAMS_BLOCKED
391fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
392fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
393fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
394fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
395fb73393fSDmitri Tikhonov                    | QUIC_FTBIT_TIMESTAMP
39626e8f082SDmitri Tikhonov                    | QUIC_FTBIT_DATAGRAM
397fb73393fSDmitri Tikhonov                    ,
398fb73393fSDmitri Tikhonov    },
399fb73393fSDmitri Tikhonov    [LSQVER_ID27] = {
4005392f7a3SLiteSpeed Tech    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
4015392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
4025392f7a3SLiteSpeed Tech    [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
4035392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
4045392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_BLOCKED
4055392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
4065392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
4075392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAMS_BLOCKED
4085392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
4095392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
410b1a7c3f9SDmitri Tikhonov                    | QUIC_FTBIT_RETIRE_CONNECTION_ID
411b1a7c3f9SDmitri Tikhonov                    | QUIC_FTBIT_DATAGRAM
412b1a7c3f9SDmitri Tikhonov                    ,
4135392f7a3SLiteSpeed Tech    [ENC_LEV_INIT]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
4145392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
4155392f7a3SLiteSpeed Tech    [ENC_LEV_FORW]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
4165392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
4175392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
4185392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_BLOCKED
4195392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
4205392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
4215392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAMS_BLOCKED
4225392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
4235392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
424feca77f5SDmitri Tikhonov                    | QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
425afe3d363SDmitri Tikhonov                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
426afe3d363SDmitri Tikhonov                    | QUIC_FTBIT_TIMESTAMP
427b1a7c3f9SDmitri Tikhonov                    | QUIC_FTBIT_DATAGRAM
428afe3d363SDmitri Tikhonov                    ,
429fb73393fSDmitri Tikhonov    },
4305392f7a3SLiteSpeed Tech};
431