lsquic_parse_common.c revision 5392f7a3
1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 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"
165392f7a3SLiteSpeed Tech
175392f7a3SLiteSpeed Tech
185392f7a3SLiteSpeed Techstatic int
195392f7a3SLiteSpeed Techparse_ietf_v1_or_Q046_long_begin (struct lsquic_packet_in *packet_in,
205392f7a3SLiteSpeed Tech                size_t length, int is_server, unsigned cid_len,
215392f7a3SLiteSpeed Tech                struct packin_parse_state *state)
225392f7a3SLiteSpeed Tech{
235392f7a3SLiteSpeed Tech    enum lsquic_version version;
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);
295392f7a3SLiteSpeed Tech        version = lsquic_tag2ver(tag);
305392f7a3SLiteSpeed Tech        if (version == LSQVER_046)
315392f7a3SLiteSpeed Tech            return lsquic_Q046_parse_packet_in_long_begin(packet_in, length,
325392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
335392f7a3SLiteSpeed Tech        else
345392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in, length,
355392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
365392f7a3SLiteSpeed Tech    }
375392f7a3SLiteSpeed Tech    else
385392f7a3SLiteSpeed Tech        return -1;
395392f7a3SLiteSpeed Tech}
405392f7a3SLiteSpeed Tech
415392f7a3SLiteSpeed Tech
425392f7a3SLiteSpeed Techstatic int (* const parse_begin_funcs[32]) (struct lsquic_packet_in *,
435392f7a3SLiteSpeed Tech                size_t length, int is_server, unsigned cid_len,
445392f7a3SLiteSpeed Tech                struct packin_parse_state *) =
455392f7a3SLiteSpeed Tech{
465392f7a3SLiteSpeed Tech    /* Xs vary, Gs are iGnored: */
475392f7a3SLiteSpeed Tech#define PBEL(mask) [(mask) >> 3]
485392f7a3SLiteSpeed Tech    /* 1X11 XGGG: */
495392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x20|0x10|0x08)  = lsquic_Q046_parse_packet_in_long_begin,
505392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x20|0x10|0x08)  = lsquic_Q046_parse_packet_in_long_begin,
515392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_long_begin,
525392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_long_begin,
535392f7a3SLiteSpeed Tech    /* 1X00 XGGG: */
545392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x00|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
555392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x00|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
565392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x00|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
575392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x00|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
585392f7a3SLiteSpeed Tech    /* 1X01 XGGG: */
595392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x00|0x10|0x08)  = parse_ietf_v1_or_Q046_long_begin,
605392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x00|0x10|0x08)  = parse_ietf_v1_or_Q046_long_begin,
615392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x00|0x10|0x00)  = parse_ietf_v1_or_Q046_long_begin,
625392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x00|0x10|0x00)  = parse_ietf_v1_or_Q046_long_begin,
635392f7a3SLiteSpeed Tech    /* 1X10 XGGG: */
645392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x20|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
655392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x20|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
665392f7a3SLiteSpeed Tech    PBEL(0x80|0x40|0x20|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
675392f7a3SLiteSpeed Tech    PBEL(0x80|0x00|0x20|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
685392f7a3SLiteSpeed Tech    /* 01XX XGGG */
695392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x00|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
705392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x00|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
715392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x10|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
725392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x00|0x10|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
735392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x00|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
745392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x00|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
755392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x10|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
765392f7a3SLiteSpeed Tech    PBEL(0x00|0x40|0x20|0x10|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
775392f7a3SLiteSpeed Tech    /* 00XX 0GGG */
785392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x00|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
795392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x10|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
805392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x00|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
815392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
825392f7a3SLiteSpeed Tech    /* 00XX 1GGG */
835392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x00|0x08)  = lsquic_gquic_parse_packet_in_begin,
845392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x00|0x10|0x08)  = lsquic_gquic_parse_packet_in_begin,
855392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x00|0x08)  = lsquic_gquic_parse_packet_in_begin,
865392f7a3SLiteSpeed Tech    PBEL(0x00|0x00|0x20|0x10|0x08)  = lsquic_gquic_parse_packet_in_begin,
875392f7a3SLiteSpeed Tech#undef PBEL
885392f7a3SLiteSpeed Tech};
899626cfc2SDmitri Tikhonov
909626cfc2SDmitri Tikhonov
919626cfc2SDmitri Tikhonovint
925392f7a3SLiteSpeed Techlsquic_parse_packet_in_server_begin (struct lsquic_packet_in *packet_in,
935392f7a3SLiteSpeed Tech                    size_t length, int is_server_UNUSED, unsigned cid_len,
945392f7a3SLiteSpeed Tech                    struct packin_parse_state *state)
955392f7a3SLiteSpeed Tech{
965392f7a3SLiteSpeed Tech    if (length)
975392f7a3SLiteSpeed Tech        return parse_begin_funcs[ packet_in->pi_data[0] >> 3 ](
985392f7a3SLiteSpeed Tech                                    packet_in, length, 1, cid_len, state);
995392f7a3SLiteSpeed Tech    else
1005392f7a3SLiteSpeed Tech        return -1;
1015392f7a3SLiteSpeed Tech
1025392f7a3SLiteSpeed Tech}
1035392f7a3SLiteSpeed Tech
1045392f7a3SLiteSpeed Tech
1055392f7a3SLiteSpeed Tech/* This function does not support Q046 */
1065392f7a3SLiteSpeed Techint
1079626cfc2SDmitri Tikhonovlsquic_parse_packet_in_begin (lsquic_packet_in_t *packet_in, size_t length,
1085392f7a3SLiteSpeed Tech            int is_server, unsigned cid_len, struct packin_parse_state *state)
1099626cfc2SDmitri Tikhonov{
1109626cfc2SDmitri Tikhonov    if (length > 0)
1119626cfc2SDmitri Tikhonov    {
1125392f7a3SLiteSpeed Tech        switch (packet_in->pi_data[0] & 0xC0)
1139626cfc2SDmitri Tikhonov        {
1145392f7a3SLiteSpeed Tech        /* XXX Revisit this: does this logic check out? */
115c7d81ce1SDmitri Tikhonov        case 0xC0:
1165392f7a3SLiteSpeed Tech        case 0x80:
1175392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in,
1185392f7a3SLiteSpeed Tech                                        length, is_server, cid_len, state);
1195392f7a3SLiteSpeed Tech        case 0x00:
1209626cfc2SDmitri Tikhonov            return lsquic_gquic_parse_packet_in_begin(packet_in, length,
1215392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1229626cfc2SDmitri Tikhonov        default:
1235392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in,
1245392f7a3SLiteSpeed Tech                                        length, is_server, cid_len, state);
1259626cfc2SDmitri Tikhonov        }
1269626cfc2SDmitri Tikhonov    }
1279626cfc2SDmitri Tikhonov    else
1289626cfc2SDmitri Tikhonov        return -1;
1299626cfc2SDmitri Tikhonov}
1309626cfc2SDmitri Tikhonov
1319626cfc2SDmitri Tikhonov
1329626cfc2SDmitri Tikhonovint
1335392f7a3SLiteSpeed Techlsquic_ietf_v1_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
1345392f7a3SLiteSpeed Tech            size_t length, int is_server, unsigned cid_len,
1355392f7a3SLiteSpeed Tech            struct packin_parse_state *state)
1369626cfc2SDmitri Tikhonov{
1379626cfc2SDmitri Tikhonov    if (length > 0)
1389626cfc2SDmitri Tikhonov    {
1399626cfc2SDmitri Tikhonov        if (0 == (packet_in->pi_data[0] & 0x80))
1405392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in, length,
1415392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1429626cfc2SDmitri Tikhonov        else
1435392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in, length,
1445392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1459626cfc2SDmitri Tikhonov    }
1469626cfc2SDmitri Tikhonov    else
1479626cfc2SDmitri Tikhonov        return -1;
1489626cfc2SDmitri Tikhonov}
1499626cfc2SDmitri Tikhonov
1509626cfc2SDmitri Tikhonov
1515392f7a3SLiteSpeed Techint
1525392f7a3SLiteSpeed Techlsquic_Q046_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
1535392f7a3SLiteSpeed Tech            size_t length, int is_server, unsigned cid_len,
1545392f7a3SLiteSpeed Tech            struct packin_parse_state *state)
1555392f7a3SLiteSpeed Tech{
1565392f7a3SLiteSpeed Tech    assert(!is_server);
1575392f7a3SLiteSpeed Tech    assert(cid_len == GQUIC_CID_LEN);
1585392f7a3SLiteSpeed Tech    if (length > 0)
1595392f7a3SLiteSpeed Tech    {
1605392f7a3SLiteSpeed Tech        if (0 == (packet_in->pi_data[0] & 0x80))
1615392f7a3SLiteSpeed Tech            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in, length,
1625392f7a3SLiteSpeed Tech                                    is_server, is_server ? cid_len : 0, state);
1635392f7a3SLiteSpeed Tech        else
1645392f7a3SLiteSpeed Tech            return lsquic_Q046_parse_packet_in_long_begin(packet_in, length,
1655392f7a3SLiteSpeed Tech                                                    is_server, cid_len, state);
1665392f7a3SLiteSpeed Tech    }
1675392f7a3SLiteSpeed Tech    else
1685392f7a3SLiteSpeed Tech        return -1;
1695392f7a3SLiteSpeed Tech}
1705392f7a3SLiteSpeed Tech
1715392f7a3SLiteSpeed Tech
1725392f7a3SLiteSpeed Tech/* TODO This function uses the full packet parsing functionality to get at
1735392f7a3SLiteSpeed Tech * the CID.  This is an overkill and could be optimized -- at the cost of
1745392f7a3SLiteSpeed Tech * some code duplication, of course.
1755392f7a3SLiteSpeed Tech */
1765392f7a3SLiteSpeed Techint
1775392f7a3SLiteSpeed Techlsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
1785392f7a3SLiteSpeed Tech                                                            lsquic_cid_t *cid)
1795392f7a3SLiteSpeed Tech{
1805392f7a3SLiteSpeed Tech    struct lsquic_packet_in packet_in;
1815392f7a3SLiteSpeed Tech    struct packin_parse_state pps;
1825392f7a3SLiteSpeed Tech    int s;
1835392f7a3SLiteSpeed Tech
1845392f7a3SLiteSpeed Tech    packet_in.pi_data = (unsigned char *) buf;
1855392f7a3SLiteSpeed Tech    s = lsquic_parse_packet_in_server_begin(&packet_in, bufsz, 1, 8, &pps);
1865392f7a3SLiteSpeed Tech    if (0 == s && (packet_in.pi_flags & PI_CONN_ID))
1875392f7a3SLiteSpeed Tech    {
1885392f7a3SLiteSpeed Tech        *cid = packet_in.pi_dcid;
1895392f7a3SLiteSpeed Tech        return 0;
1905392f7a3SLiteSpeed Tech    }
1915392f7a3SLiteSpeed Tech    else
1925392f7a3SLiteSpeed Tech        return -1;
1935392f7a3SLiteSpeed Tech}
1945392f7a3SLiteSpeed Tech
1955392f7a3SLiteSpeed Tech
1965392f7a3SLiteSpeed Tech/* See [draft-ietf-quic-tls-19], Section 4 */
1975392f7a3SLiteSpeed Techconst enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
1985392f7a3SLiteSpeed Tech{
1995392f7a3SLiteSpeed Tech    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
2005392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
2015392f7a3SLiteSpeed Tech    [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
2025392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
2035392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_BLOCKED
2045392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
2055392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
2065392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAMS_BLOCKED
2075392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
2085392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
2095392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN,
2105392f7a3SLiteSpeed Tech    [ENC_LEV_INIT]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
2115392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
2125392f7a3SLiteSpeed Tech    [ENC_LEV_FORW]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
2135392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
2145392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
2155392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_BLOCKED
2165392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
2175392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
2185392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_STREAMS_BLOCKED
2195392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
2205392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
2215392f7a3SLiteSpeed Tech                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN,
2225392f7a3SLiteSpeed Tech};
223