1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
|
/*
* Copyright (C) Nginx, Inc.
*/
#ifndef _NGX_EVENT_QUIC_TRANSPORT_H_INCLUDED_
#define _NGX_EVENT_QUIC_TRANSPORT_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
/*
* RFC 9000, 17.2. Long Header Packets
* 17.3. Short Header Packets
*
* QUIC flags in first byte
*/
#define NGX_QUIC_PKT_LONG 0x80 /* header form */
#define NGX_QUIC_PKT_FIXED_BIT 0x40
#define NGX_QUIC_PKT_TYPE 0x30 /* in long packet */
#define NGX_QUIC_PKT_KPHASE 0x04 /* in short packet */
#define ngx_quic_long_pkt(flags) ((flags) & NGX_QUIC_PKT_LONG)
#define ngx_quic_short_pkt(flags) (((flags) & NGX_QUIC_PKT_LONG) == 0)
/* Long packet types */
#define NGX_QUIC_PKT_INITIAL 0x00
#define NGX_QUIC_PKT_ZRTT 0x10
#define NGX_QUIC_PKT_HANDSHAKE 0x20
#define NGX_QUIC_PKT_RETRY 0x30
#define ngx_quic_pkt_in(flags) \
(((flags) & NGX_QUIC_PKT_TYPE) == NGX_QUIC_PKT_INITIAL)
#define ngx_quic_pkt_zrtt(flags) \
(((flags) & NGX_QUIC_PKT_TYPE) == NGX_QUIC_PKT_ZRTT)
#define ngx_quic_pkt_hs(flags) \
(((flags) & NGX_QUIC_PKT_TYPE) == NGX_QUIC_PKT_HANDSHAKE)
#define ngx_quic_pkt_retry(flags) \
(((flags) & NGX_QUIC_PKT_TYPE) == NGX_QUIC_PKT_RETRY)
#define ngx_quic_pkt_rb_mask(flags) \
(ngx_quic_long_pkt(flags) ? 0x0C : 0x18)
#define ngx_quic_pkt_hp_mask(flags) \
(ngx_quic_long_pkt(flags) ? 0x0F : 0x1F)
#define ngx_quic_level_name(lvl) \
(lvl == ssl_encryption_application) ? "app" \
: (lvl == ssl_encryption_initial) ? "init" \
: (lvl == ssl_encryption_handshake) ? "hs" : "early"
#define NGX_QUIC_MAX_CID_LEN 20
#define NGX_QUIC_SERVER_CID_LEN NGX_QUIC_MAX_CID_LEN
/* 12.4. Frames and Frame Types */
#define NGX_QUIC_FT_PADDING 0x00
#define NGX_QUIC_FT_PING 0x01
#define NGX_QUIC_FT_ACK 0x02
#define NGX_QUIC_FT_ACK_ECN 0x03
#define NGX_QUIC_FT_RESET_STREAM 0x04
#define NGX_QUIC_FT_STOP_SENDING 0x05
#define NGX_QUIC_FT_CRYPTO 0x06
#define NGX_QUIC_FT_NEW_TOKEN 0x07
#define NGX_QUIC_FT_STREAM 0x08
#define NGX_QUIC_FT_STREAM1 0x09
#define NGX_QUIC_FT_STREAM2 0x0A
#define NGX_QUIC_FT_STREAM3 0x0B
#define NGX_QUIC_FT_STREAM4 0x0C
#define NGX_QUIC_FT_STREAM5 0x0D
#define NGX_QUIC_FT_STREAM6 0x0E
#define NGX_QUIC_FT_STREAM7 0x0F
#define NGX_QUIC_FT_MAX_DATA 0x10
#define NGX_QUIC_FT_MAX_STREAM_DATA 0x11
#define NGX_QUIC_FT_MAX_STREAMS 0x12
#define NGX_QUIC_FT_MAX_STREAMS2 0x13
#define NGX_QUIC_FT_DATA_BLOCKED 0x14
#define NGX_QUIC_FT_STREAM_DATA_BLOCKED 0x15
#define NGX_QUIC_FT_STREAMS_BLOCKED 0x16
#define NGX_QUIC_FT_STREAMS_BLOCKED2 0x17
#define NGX_QUIC_FT_NEW_CONNECTION_ID 0x18
#define NGX_QUIC_FT_RETIRE_CONNECTION_ID 0x19
#define NGX_QUIC_FT_PATH_CHALLENGE 0x1A
#define NGX_QUIC_FT_PATH_RESPONSE 0x1B
#define NGX_QUIC_FT_CONNECTION_CLOSE 0x1C
#define NGX_QUIC_FT_CONNECTION_CLOSE_APP 0x1D
#define NGX_QUIC_FT_HANDSHAKE_DONE 0x1E
#define NGX_QUIC_FT_LAST NGX_QUIC_FT_HANDSHAKE_DONE
/* 22.5. QUIC Transport Error Codes Registry */
#define NGX_QUIC_ERR_NO_ERROR 0x00
#define NGX_QUIC_ERR_INTERNAL_ERROR 0x01
#define NGX_QUIC_ERR_CONNECTION_REFUSED 0x02
#define NGX_QUIC_ERR_FLOW_CONTROL_ERROR 0x03
#define NGX_QUIC_ERR_STREAM_LIMIT_ERROR 0x04
#define NGX_QUIC_ERR_STREAM_STATE_ERROR 0x05
#define NGX_QUIC_ERR_FINAL_SIZE_ERROR 0x06
#define NGX_QUIC_ERR_FRAME_ENCODING_ERROR 0x07
#define NGX_QUIC_ERR_TRANSPORT_PARAMETER_ERROR 0x08
#define NGX_QUIC_ERR_CONNECTION_ID_LIMIT_ERROR 0x09
#define NGX_QUIC_ERR_PROTOCOL_VIOLATION 0x0A
#define NGX_QUIC_ERR_INVALID_TOKEN 0x0B
#define NGX_QUIC_ERR_APPLICATION_ERROR 0x0C
#define NGX_QUIC_ERR_CRYPTO_BUFFER_EXCEEDED 0x0D
#define NGX_QUIC_ERR_KEY_UPDATE_ERROR 0x0E
#define NGX_QUIC_ERR_AEAD_LIMIT_REACHED 0x0F
#define NGX_QUIC_ERR_NO_VIABLE_PATH 0x10
#define NGX_QUIC_ERR_CRYPTO_ERROR 0x100
#define NGX_QUIC_ERR_CRYPTO(e) (NGX_QUIC_ERR_CRYPTO_ERROR + (e))
/* 22.3. QUIC Transport Parameters Registry */
#define NGX_QUIC_TP_ORIGINAL_DCID 0x00
#define NGX_QUIC_TP_MAX_IDLE_TIMEOUT 0x01
#define NGX_QUIC_TP_SR_TOKEN 0x02
#define NGX_QUIC_TP_MAX_UDP_PAYLOAD_SIZE 0x03
#define NGX_QUIC_TP_INITIAL_MAX_DATA 0x04
#define NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05
#define NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06
#define NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI 0x07
#define NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI 0x08
#define NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI 0x09
#define NGX_QUIC_TP_ACK_DELAY_EXPONENT 0x0A
#define NGX_QUIC_TP_MAX_ACK_DELAY 0x0B
#define NGX_QUIC_TP_DISABLE_ACTIVE_MIGRATION 0x0C
#define NGX_QUIC_TP_PREFERRED_ADDRESS 0x0D
#define NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT 0x0E
#define NGX_QUIC_TP_INITIAL_SCID 0x0F
#define NGX_QUIC_TP_RETRY_SCID 0x10
#define NGX_QUIC_CID_LEN_MIN 8
#define NGX_QUIC_CID_LEN_MAX 20
#define NGX_QUIC_MAX_RANGES 10
typedef struct {
uint64_t gap;
uint64_t range;
} ngx_quic_ack_range_t;
typedef struct {
uint64_t largest;
uint64_t delay;
uint64_t range_count;
uint64_t first_range;
uint64_t ect0;
uint64_t ect1;
uint64_t ce;
uint64_t ranges_length;
} ngx_quic_ack_frame_t;
typedef struct {
uint64_t seqnum;
uint64_t retire;
uint8_t len;
u_char cid[NGX_QUIC_CID_LEN_MAX];
u_char srt[NGX_QUIC_SR_TOKEN_LEN];
} ngx_quic_new_conn_id_frame_t;
typedef struct {
uint64_t length;
} ngx_quic_new_token_frame_t;
/*
* common layout for CRYPTO and STREAM frames;
* conceptually, CRYPTO frame is also a stream
* frame lacking some properties
*/
typedef struct {
uint64_t offset;
uint64_t length;
} ngx_quic_ordered_frame_t;
typedef ngx_quic_ordered_frame_t ngx_quic_crypto_frame_t;
typedef struct {
/* initial fields same as in ngx_quic_ordered_frame_t */
uint64_t offset;
uint64_t length;
uint64_t stream_id;
unsigned off:1;
unsigned len:1;
unsigned fin:1;
} ngx_quic_stream_frame_t;
typedef struct {
uint64_t max_data;
} ngx_quic_max_data_frame_t;
typedef struct {
uint64_t error_code;
uint64_t frame_type;
ngx_str_t reason;
} ngx_quic_close_frame_t;
typedef struct {
uint64_t id;
uint64_t error_code;
uint64_t final_size;
} ngx_quic_reset_stream_frame_t;
typedef struct {
uint64_t id;
uint64_t error_code;
} ngx_quic_stop_sending_frame_t;
typedef struct {
uint64_t limit;
ngx_uint_t bidi; /* unsigned: bidi:1 */
} ngx_quic_streams_blocked_frame_t;
typedef struct {
uint64_t limit;
ngx_uint_t bidi; /* unsigned: bidi:1 */
} ngx_quic_max_streams_frame_t;
typedef struct {
uint64_t id;
uint64_t limit;
} ngx_quic_max_stream_data_frame_t;
typedef struct {
uint64_t limit;
} ngx_quic_data_blocked_frame_t;
typedef struct {
uint64_t id;
uint64_t limit;
} ngx_quic_stream_data_blocked_frame_t;
typedef struct {
uint64_t sequence_number;
} ngx_quic_retire_cid_frame_t;
typedef struct {
u_char data[8];
} ngx_quic_path_challenge_frame_t;
typedef struct ngx_quic_frame_s ngx_quic_frame_t;
struct ngx_quic_frame_s {
ngx_uint_t type;
enum ssl_encryption_level_t level;
ngx_queue_t queue;
uint64_t pnum;
size_t plen;
ngx_msec_t send_time;
ssize_t len;
unsigned need_ack:1;
unsigned pkt_need_ack:1;
unsigned ignore_congestion:1;
ngx_chain_t *data;
union {
ngx_quic_ack_frame_t ack;
ngx_quic_crypto_frame_t crypto;
ngx_quic_ordered_frame_t ord;
ngx_quic_new_conn_id_frame_t ncid;
ngx_quic_new_token_frame_t token;
ngx_quic_stream_frame_t stream;
ngx_quic_max_data_frame_t max_data;
ngx_quic_close_frame_t close;
ngx_quic_reset_stream_frame_t reset_stream;
ngx_quic_stop_sending_frame_t stop_sending;
ngx_quic_streams_blocked_frame_t streams_blocked;
ngx_quic_max_streams_frame_t max_streams;
ngx_quic_max_stream_data_frame_t max_stream_data;
ngx_quic_data_blocked_frame_t data_blocked;
ngx_quic_stream_data_blocked_frame_t stream_data_blocked;
ngx_quic_retire_cid_frame_t retire_cid;
ngx_quic_path_challenge_frame_t path_challenge;
ngx_quic_path_challenge_frame_t path_response;
} u;
};
typedef struct {
ngx_log_t *log;
ngx_quic_path_t *path;
ngx_quic_keys_t *keys;
ngx_msec_t received;
uint64_t number;
uint8_t num_len;
uint32_t trunc;
uint8_t flags;
uint32_t version;
ngx_str_t token;
enum ssl_encryption_level_t level;
ngx_uint_t error;
/* filled in by parser */
ngx_buf_t *raw; /* udp datagram */
u_char *data; /* quic packet */
size_t len;
/* cleartext fields */
ngx_str_t odcid; /* retry packet tag */
u_char odcid_buf[NGX_QUIC_MAX_CID_LEN];
ngx_str_t dcid;
ngx_str_t scid;
uint64_t pn;
u_char *plaintext;
ngx_str_t payload; /* decrypted data */
unsigned need_ack:1;
unsigned key_phase:1;
unsigned key_update:1;
unsigned parsed:1;
unsigned decrypted:1;
unsigned validated:1;
unsigned retried:1;
unsigned first:1;
unsigned rebound:1;
unsigned path_challenged:1;
} ngx_quic_header_t;
typedef struct {
ngx_msec_t max_idle_timeout;
ngx_msec_t max_ack_delay;
size_t max_udp_payload_size;
size_t initial_max_data;
size_t initial_max_stream_data_bidi_local;
size_t initial_max_stream_data_bidi_remote;
size_t initial_max_stream_data_uni;
ngx_uint_t initial_max_streams_bidi;
ngx_uint_t initial_max_streams_uni;
ngx_uint_t ack_delay_exponent;
ngx_uint_t active_connection_id_limit;
ngx_flag_t disable_active_migration;
ngx_str_t original_dcid;
ngx_str_t initial_scid;
ngx_str_t retry_scid;
u_char sr_token[NGX_QUIC_SR_TOKEN_LEN];
/* TODO */
void *preferred_address;
} ngx_quic_tp_t;
ngx_int_t ngx_quic_parse_packet(ngx_quic_header_t *pkt);
size_t ngx_quic_create_version_negotiation(ngx_quic_header_t *pkt, u_char *out);
size_t ngx_quic_payload_size(ngx_quic_header_t *pkt, size_t pkt_len);
size_t ngx_quic_create_header(ngx_quic_header_t *pkt, u_char *out,
u_char **pnp);
size_t ngx_quic_create_retry_itag(ngx_quic_header_t *pkt, u_char *out,
u_char **start);
ssize_t ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end,
ngx_quic_frame_t *frame);
ssize_t ngx_quic_create_frame(u_char *p, ngx_quic_frame_t *f);
ssize_t ngx_quic_parse_ack_range(ngx_log_t *log, u_char *start,
u_char *end, uint64_t *gap, uint64_t *range);
size_t ngx_quic_create_ack_range(u_char *p, uint64_t gap, uint64_t range);
ngx_int_t ngx_quic_init_transport_params(ngx_quic_tp_t *tp,
ngx_quic_conf_t *qcf);
ngx_int_t ngx_quic_parse_transport_params(u_char *p, u_char *end,
ngx_quic_tp_t *tp, ngx_log_t *log);
ssize_t ngx_quic_create_transport_params(u_char *p, u_char *end,
ngx_quic_tp_t *tp, size_t *clen);
void ngx_quic_dcid_encode_key(u_char *dcid, uint64_t key);
#endif /* _NGX_EVENT_QUIC_TRANSPORT_H_INCLUDED_ */
|