lsquic_parse_common.c revision 5392f7a3
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <string.h>
4#include <sys/queue.h>
5#include <sys/types.h>
6
7#include "lsquic.h"
8#include "lsquic_types.h"
9#include "lsquic_int_types.h"
10#include "lsquic_packet_common.h"
11#include "lsquic_packet_in.h"
12#include "lsquic_parse_common.h"
13#include "lsquic_parse.h"
14#include "lsquic_enc_sess.h"
15#include "lsquic_version.h"
16
17
18static int
19parse_ietf_v1_or_Q046_long_begin (struct lsquic_packet_in *packet_in,
20                size_t length, int is_server, unsigned cid_len,
21                struct packin_parse_state *state)
22{
23    enum lsquic_version version;
24    lsquic_ver_tag_t tag;
25
26    if (length >= 5)
27    {
28        memcpy(&tag, packet_in->pi_data + 1, 4);
29        version = lsquic_tag2ver(tag);
30        if (version == LSQVER_046)
31            return lsquic_Q046_parse_packet_in_long_begin(packet_in, length,
32                                                    is_server, cid_len, state);
33        else
34            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in, length,
35                                                    is_server, cid_len, state);
36    }
37    else
38        return -1;
39}
40
41
42static int (* const parse_begin_funcs[32]) (struct lsquic_packet_in *,
43                size_t length, int is_server, unsigned cid_len,
44                struct packin_parse_state *) =
45{
46    /* Xs vary, Gs are iGnored: */
47#define PBEL(mask) [(mask) >> 3]
48    /* 1X11 XGGG: */
49    PBEL(0x80|0x40|0x20|0x10|0x08)  = lsquic_Q046_parse_packet_in_long_begin,
50    PBEL(0x80|0x00|0x20|0x10|0x08)  = lsquic_Q046_parse_packet_in_long_begin,
51    PBEL(0x80|0x40|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_long_begin,
52    PBEL(0x80|0x00|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_long_begin,
53    /* 1X00 XGGG: */
54    PBEL(0x80|0x40|0x00|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
55    PBEL(0x80|0x00|0x00|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
56    PBEL(0x80|0x40|0x00|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
57    PBEL(0x80|0x00|0x00|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
58    /* 1X01 XGGG: */
59    PBEL(0x80|0x40|0x00|0x10|0x08)  = parse_ietf_v1_or_Q046_long_begin,
60    PBEL(0x80|0x00|0x00|0x10|0x08)  = parse_ietf_v1_or_Q046_long_begin,
61    PBEL(0x80|0x40|0x00|0x10|0x00)  = parse_ietf_v1_or_Q046_long_begin,
62    PBEL(0x80|0x00|0x00|0x10|0x00)  = parse_ietf_v1_or_Q046_long_begin,
63    /* 1X10 XGGG: */
64    PBEL(0x80|0x40|0x20|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
65    PBEL(0x80|0x00|0x20|0x00|0x08)  = parse_ietf_v1_or_Q046_long_begin,
66    PBEL(0x80|0x40|0x20|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
67    PBEL(0x80|0x00|0x20|0x00|0x00)  = parse_ietf_v1_or_Q046_long_begin,
68    /* 01XX XGGG */
69    PBEL(0x00|0x40|0x00|0x00|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
70    PBEL(0x00|0x40|0x00|0x00|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
71    PBEL(0x00|0x40|0x00|0x10|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
72    PBEL(0x00|0x40|0x00|0x10|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
73    PBEL(0x00|0x40|0x20|0x00|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
74    PBEL(0x00|0x40|0x20|0x00|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
75    PBEL(0x00|0x40|0x20|0x10|0x00)  = lsquic_ietf_v1_parse_packet_in_short_begin,
76    PBEL(0x00|0x40|0x20|0x10|0x08)  = lsquic_ietf_v1_parse_packet_in_short_begin,
77    /* 00XX 0GGG */
78    PBEL(0x00|0x00|0x00|0x00|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
79    PBEL(0x00|0x00|0x00|0x10|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
80    PBEL(0x00|0x00|0x20|0x00|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
81    PBEL(0x00|0x00|0x20|0x10|0x00)  = lsquic_Q046_parse_packet_in_short_begin,
82    /* 00XX 1GGG */
83    PBEL(0x00|0x00|0x00|0x00|0x08)  = lsquic_gquic_parse_packet_in_begin,
84    PBEL(0x00|0x00|0x00|0x10|0x08)  = lsquic_gquic_parse_packet_in_begin,
85    PBEL(0x00|0x00|0x20|0x00|0x08)  = lsquic_gquic_parse_packet_in_begin,
86    PBEL(0x00|0x00|0x20|0x10|0x08)  = lsquic_gquic_parse_packet_in_begin,
87#undef PBEL
88};
89
90
91int
92lsquic_parse_packet_in_server_begin (struct lsquic_packet_in *packet_in,
93                    size_t length, int is_server_UNUSED, unsigned cid_len,
94                    struct packin_parse_state *state)
95{
96    if (length)
97        return parse_begin_funcs[ packet_in->pi_data[0] >> 3 ](
98                                    packet_in, length, 1, cid_len, state);
99    else
100        return -1;
101
102}
103
104
105/* This function does not support Q046 */
106int
107lsquic_parse_packet_in_begin (lsquic_packet_in_t *packet_in, size_t length,
108            int is_server, unsigned cid_len, struct packin_parse_state *state)
109{
110    if (length > 0)
111    {
112        switch (packet_in->pi_data[0] & 0xC0)
113        {
114        /* XXX Revisit this: does this logic check out? */
115        case 0xC0:
116        case 0x80:
117            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in,
118                                        length, is_server, cid_len, state);
119        case 0x00:
120            return lsquic_gquic_parse_packet_in_begin(packet_in, length,
121                                                    is_server, cid_len, state);
122        default:
123            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in,
124                                        length, is_server, cid_len, state);
125        }
126    }
127    else
128        return -1;
129}
130
131
132int
133lsquic_ietf_v1_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
134            size_t length, int is_server, unsigned cid_len,
135            struct packin_parse_state *state)
136{
137    if (length > 0)
138    {
139        if (0 == (packet_in->pi_data[0] & 0x80))
140            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in, length,
141                                                    is_server, cid_len, state);
142        else
143            return lsquic_ietf_v1_parse_packet_in_long_begin(packet_in, length,
144                                                    is_server, cid_len, state);
145    }
146    else
147        return -1;
148}
149
150
151int
152lsquic_Q046_parse_packet_in_begin (struct lsquic_packet_in *packet_in,
153            size_t length, int is_server, unsigned cid_len,
154            struct packin_parse_state *state)
155{
156    assert(!is_server);
157    assert(cid_len == GQUIC_CID_LEN);
158    if (length > 0)
159    {
160        if (0 == (packet_in->pi_data[0] & 0x80))
161            return lsquic_ietf_v1_parse_packet_in_short_begin(packet_in, length,
162                                    is_server, is_server ? cid_len : 0, state);
163        else
164            return lsquic_Q046_parse_packet_in_long_begin(packet_in, length,
165                                                    is_server, cid_len, state);
166    }
167    else
168        return -1;
169}
170
171
172/* TODO This function uses the full packet parsing functionality to get at
173 * the CID.  This is an overkill and could be optimized -- at the cost of
174 * some code duplication, of course.
175 */
176int
177lsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
178                                                            lsquic_cid_t *cid)
179{
180    struct lsquic_packet_in packet_in;
181    struct packin_parse_state pps;
182    int s;
183
184    packet_in.pi_data = (unsigned char *) buf;
185    s = lsquic_parse_packet_in_server_begin(&packet_in, bufsz, 1, 8, &pps);
186    if (0 == s && (packet_in.pi_flags & PI_CONN_ID))
187    {
188        *cid = packet_in.pi_dcid;
189        return 0;
190    }
191    else
192        return -1;
193}
194
195
196/* See [draft-ietf-quic-tls-19], Section 4 */
197const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
198{
199    [ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
200                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
201    [ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
202                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
203                    | QUIC_FTBIT_BLOCKED
204                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
205                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
206                    | QUIC_FTBIT_STREAMS_BLOCKED
207                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
208                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
209                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN,
210    [ENC_LEV_INIT]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
211                    | QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
212    [ENC_LEV_FORW]  = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
213                    | QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
214                    | QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
215                    | QUIC_FTBIT_BLOCKED
216                    | QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
217                    | QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
218                    | QUIC_FTBIT_STREAMS_BLOCKED
219                    | QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
220                    | QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
221                    | QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN,
222};
223