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