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