comparison src/event/quic/ngx_event_quic_transport.c @ 8673:046c951e393a quic

QUIC: moved all quic sources into src/event/quic.
author Vladimir Homutov <vl@nginx.com>
date Fri, 25 Dec 2020 14:01:28 +0300
parents src/event/ngx_event_quic_transport.c@5247461c17e1
children 7df607cb2d11
comparison
equal deleted inserted replaced
8672:13c537def699 8673:046c951e393a
1
2 /*
3 * Copyright (C) Nginx, Inc.
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10 #include <ngx_event_quic_transport.h>
11
12
13 #define NGX_QUIC_LONG_DCID_LEN_OFFSET 5
14 #define NGX_QUIC_LONG_DCID_OFFSET 6
15 #define NGX_QUIC_SHORT_DCID_OFFSET 1
16
17
18 #if (NGX_HAVE_NONALIGNED)
19
20 #define ngx_quic_parse_uint16(p) ntohs(*(uint16_t *) (p))
21 #define ngx_quic_parse_uint32(p) ntohl(*(uint32_t *) (p))
22
23 #define ngx_quic_write_uint16 ngx_quic_write_uint16_aligned
24 #define ngx_quic_write_uint32 ngx_quic_write_uint32_aligned
25
26 #else
27
28 #define ngx_quic_parse_uint16(p) ((p)[0] << 8 | (p)[1])
29 #define ngx_quic_parse_uint32(p) \
30 ((uint32_t) (p)[0] << 24 | (p)[1] << 16 | (p)[2] << 8 | (p)[3])
31
32 #define ngx_quic_write_uint16(p, s) \
33 ((p)[0] = (u_char) ((s) >> 8), \
34 (p)[1] = (u_char) (s), \
35 (p) + sizeof(uint16_t))
36
37 #define ngx_quic_write_uint32(p, s) \
38 ((p)[0] = (u_char) ((s) >> 24), \
39 (p)[1] = (u_char) ((s) >> 16), \
40 (p)[2] = (u_char) ((s) >> 8), \
41 (p)[3] = (u_char) (s), \
42 (p) + sizeof(uint32_t))
43
44 #endif
45
46 #define ngx_quic_write_uint24(p, s) \
47 ((p)[0] = (u_char) ((s) >> 16), \
48 (p)[1] = (u_char) ((s) >> 8), \
49 (p)[2] = (u_char) (s), \
50 (p) + 3)
51
52 #define ngx_quic_write_uint16_aligned(p, s) \
53 (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t))
54
55 #define ngx_quic_write_uint32_aligned(p, s) \
56 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t))
57
58 #define NGX_QUIC_VERSION(c) (0xff000000 + (c))
59
60
61 static u_char *ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out);
62 static ngx_uint_t ngx_quic_varint_len(uint64_t value);
63 static void ngx_quic_build_int(u_char **pos, uint64_t value);
64
65 static u_char *ngx_quic_read_uint8(u_char *pos, u_char *end, uint8_t *value);
66 static u_char *ngx_quic_read_uint32(u_char *pos, u_char *end, uint32_t *value);
67 static u_char *ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len,
68 u_char **out);
69 static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len,
70 u_char *dst);
71
72 static ngx_int_t ngx_quic_parse_short_header(ngx_quic_header_t *pkt,
73 size_t dcid_len);
74 static ngx_int_t ngx_quic_parse_long_header(ngx_quic_header_t *pkt);
75 static ngx_int_t ngx_quic_supported_version(uint32_t version);
76 static ngx_int_t ngx_quic_parse_long_header_v1(ngx_quic_header_t *pkt);
77
78 static size_t ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out,
79 size_t pkt_len, u_char **pnp);
80 static size_t ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out,
81 size_t pkt_len, u_char **pnp);
82
83 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt,
84 ngx_uint_t frame_type);
85 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack,
86 ngx_chain_t *ranges);
87 static size_t ngx_quic_create_stop_sending(u_char *p,
88 ngx_quic_stop_sending_frame_t *ss);
89 static size_t ngx_quic_create_crypto(u_char *p,
90 ngx_quic_crypto_frame_t *crypto, ngx_chain_t *data);
91 static size_t ngx_quic_create_hs_done(u_char *p);
92 static size_t ngx_quic_create_new_token(u_char *p,
93 ngx_quic_new_token_frame_t *token);
94 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf,
95 ngx_chain_t *data);
96 static size_t ngx_quic_create_max_streams(u_char *p,
97 ngx_quic_max_streams_frame_t *ms);
98 static size_t ngx_quic_create_max_stream_data(u_char *p,
99 ngx_quic_max_stream_data_frame_t *ms);
100 static size_t ngx_quic_create_max_data(u_char *p,
101 ngx_quic_max_data_frame_t *md);
102 static size_t ngx_quic_create_path_response(u_char *p,
103 ngx_quic_path_challenge_frame_t *pc);
104 static size_t ngx_quic_create_new_connection_id(u_char *p,
105 ngx_quic_new_conn_id_frame_t *rcid);
106 static size_t ngx_quic_create_retire_connection_id(u_char *p,
107 ngx_quic_retire_cid_frame_t *rcid);
108 static size_t ngx_quic_create_close(u_char *p, ngx_quic_close_frame_t *cl);
109
110 static ngx_int_t ngx_quic_parse_transport_param(u_char *p, u_char *end,
111 uint16_t id, ngx_quic_tp_t *dst);
112
113
114 uint32_t ngx_quic_versions[] = {
115 #if (NGX_QUIC_DRAFT_VERSION >= 29)
116 /* pretend we support all versions in range draft-29..v1 */
117 NGX_QUIC_VERSION(29),
118 NGX_QUIC_VERSION(30),
119 NGX_QUIC_VERSION(31),
120 NGX_QUIC_VERSION(32),
121 /* QUICv1 */
122 0x00000001
123 #else
124 NGX_QUIC_VERSION(NGX_QUIC_DRAFT_VERSION)
125 #endif
126 };
127
128 #define NGX_QUIC_NVERSIONS \
129 (sizeof(ngx_quic_versions) / sizeof(ngx_quic_versions[0]))
130
131
132 /* literal errors indexed by corresponding value */
133 static char *ngx_quic_errors[] = {
134 "NO_ERROR",
135 "INTERNAL_ERROR",
136 "CONNECTION_REFUSED",
137 "FLOW_CONTROL_ERROR",
138 "STREAM_LIMIT_ERROR",
139 "STREAM_STATE_ERROR",
140 "FINAL_SIZE_ERROR",
141 "FRAME_ENCODING_ERROR",
142 "TRANSPORT_PARAMETER_ERROR",
143 "CONNECTION_ID_LIMIT_ERROR",
144 "PROTOCOL_VIOLATION",
145 "INVALID_TOKEN",
146 "APPLICATION_ERROR",
147 "CRYPTO_BUFFER_EXCEEDED",
148 "KEY_UPDATE_ERROR",
149 };
150
151
152 static ngx_inline u_char *
153 ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out)
154 {
155 u_char *p;
156 uint64_t value;
157 ngx_uint_t len;
158
159 if (pos >= end) {
160 return NULL;
161 }
162
163 p = pos;
164 len = 1 << (*p >> 6);
165
166 value = *p++ & 0x3f;
167
168 if ((size_t)(end - p) < (len - 1)) {
169 return NULL;
170 }
171
172 while (--len) {
173 value = (value << 8) + *p++;
174 }
175
176 *out = value;
177
178 return p;
179 }
180
181
182 static ngx_inline u_char *
183 ngx_quic_read_uint8(u_char *pos, u_char *end, uint8_t *value)
184 {
185 if ((size_t)(end - pos) < 1) {
186 return NULL;
187 }
188
189 *value = *pos;
190
191 return pos + 1;
192 }
193
194
195 static ngx_inline u_char *
196 ngx_quic_read_uint32(u_char *pos, u_char *end, uint32_t *value)
197 {
198 if ((size_t)(end - pos) < sizeof(uint32_t)) {
199 return NULL;
200 }
201
202 *value = ngx_quic_parse_uint32(pos);
203
204 return pos + sizeof(uint32_t);
205 }
206
207
208 static ngx_inline u_char *
209 ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len, u_char **out)
210 {
211 if ((size_t)(end - pos) < len) {
212 return NULL;
213 }
214
215 *out = pos;
216
217 return pos + len;
218 }
219
220
221 static u_char *
222 ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, u_char *dst)
223 {
224 if ((size_t)(end - pos) < len) {
225 return NULL;
226 }
227
228 ngx_memcpy(dst, pos, len);
229
230 return pos + len;
231 }
232
233
234 static ngx_uint_t
235 ngx_quic_varint_len(uint64_t value)
236 {
237 ngx_uint_t bits;
238
239 bits = 0;
240 while (value >> ((8 << bits) - 2)) {
241 bits++;
242 }
243
244 return 1 << bits;
245 }
246
247
248 static void
249 ngx_quic_build_int(u_char **pos, uint64_t value)
250 {
251 u_char *p;
252 ngx_uint_t bits, len;
253
254 p = *pos;
255 bits = 0;
256
257 while (value >> ((8 << bits) - 2)) {
258 bits++;
259 }
260
261 len = (1 << bits);
262
263 while (len--) {
264 *p++ = value >> (len * 8);
265 }
266
267 **pos |= bits << 6;
268 *pos = p;
269 }
270
271
272 u_char *
273 ngx_quic_error_text(uint64_t error_code)
274 {
275 if (error_code >= NGX_QUIC_ERR_CRYPTO_ERROR) {
276 return (u_char *) "handshake error";
277 }
278
279 if (error_code >= NGX_QUIC_ERR_LAST) {
280 return (u_char *) "unknown error";
281 }
282
283 return (u_char *) ngx_quic_errors[error_code];
284 }
285
286
287 ngx_int_t
288 ngx_quic_parse_packet(ngx_quic_header_t *pkt)
289 {
290 if (!ngx_quic_long_pkt(pkt->flags)) {
291 pkt->level = ssl_encryption_application;
292
293 if (ngx_quic_parse_short_header(pkt, NGX_QUIC_SERVER_CID_LEN) != NGX_OK)
294 {
295 return NGX_DECLINED;
296 }
297
298 return NGX_OK;
299 }
300
301 if (ngx_quic_parse_long_header(pkt) != NGX_OK) {
302 return NGX_DECLINED;
303 }
304
305 if (!ngx_quic_supported_version(pkt->version)) {
306 return NGX_ABORT;
307 }
308
309 if (ngx_quic_parse_long_header_v1(pkt) != NGX_OK) {
310 return NGX_DECLINED;
311 }
312
313 return NGX_OK;
314 }
315
316
317 static ngx_int_t
318 ngx_quic_parse_short_header(ngx_quic_header_t *pkt, size_t dcid_len)
319 {
320 u_char *p, *end;
321
322 p = pkt->raw->pos;
323 end = pkt->data + pkt->len;
324
325 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
326 "quic packet rx short flags:%xd", pkt->flags);
327
328 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
329 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
330 return NGX_ERROR;
331 }
332
333 pkt->dcid.len = dcid_len;
334
335 p = ngx_quic_read_bytes(p, end, dcid_len, &pkt->dcid.data);
336 if (p == NULL) {
337 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
338 "quic packet is too small to read dcid");
339 return NGX_ERROR;
340 }
341
342 pkt->raw->pos = p;
343
344 return NGX_OK;
345 }
346
347
348 static ngx_int_t
349 ngx_quic_parse_long_header(ngx_quic_header_t *pkt)
350 {
351 u_char *p, *end;
352 uint8_t idlen;
353
354 p = pkt->raw->pos;
355 end = pkt->data + pkt->len;
356
357 p = ngx_quic_read_uint32(p, end, &pkt->version);
358 if (p == NULL) {
359 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
360 "quic packet is too small to read version");
361 return NGX_ERROR;
362 }
363
364 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
365 "quic packet rx long flags:%xd version:%xD",
366 pkt->flags, pkt->version);
367
368 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
369 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
370 return NGX_ERROR;
371 }
372
373 p = ngx_quic_read_uint8(p, end, &idlen);
374 if (p == NULL) {
375 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
376 "quic packet is too small to read dcid len");
377 return NGX_ERROR;
378 }
379
380 if (idlen > NGX_QUIC_CID_LEN_MAX) {
381 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
382 "quic packet dcid is too long");
383 return NGX_ERROR;
384 }
385
386 pkt->dcid.len = idlen;
387
388 p = ngx_quic_read_bytes(p, end, idlen, &pkt->dcid.data);
389 if (p == NULL) {
390 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
391 "quic packet is too small to read dcid");
392 return NGX_ERROR;
393 }
394
395 p = ngx_quic_read_uint8(p, end, &idlen);
396 if (p == NULL) {
397 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
398 "quic packet is too small to read scid len");
399 return NGX_ERROR;
400 }
401
402 if (idlen > NGX_QUIC_CID_LEN_MAX) {
403 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
404 "quic packet scid is too long");
405 return NGX_ERROR;
406 }
407
408 pkt->scid.len = idlen;
409
410 p = ngx_quic_read_bytes(p, end, idlen, &pkt->scid.data);
411 if (p == NULL) {
412 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
413 "quic packet is too small to read scid");
414 return NGX_ERROR;
415 }
416
417 pkt->raw->pos = p;
418
419 return NGX_OK;
420 }
421
422
423 static ngx_int_t
424 ngx_quic_supported_version(uint32_t version)
425 {
426 ngx_uint_t i;
427
428 for (i = 0; i < NGX_QUIC_NVERSIONS; i++) {
429 if (ngx_quic_versions[i] == version) {
430 return 1;
431 }
432 }
433
434 return 0;
435 }
436
437
438 static ngx_int_t
439 ngx_quic_parse_long_header_v1(ngx_quic_header_t *pkt)
440 {
441 u_char *p, *end;
442 uint64_t varint;
443
444 p = pkt->raw->pos;
445 end = pkt->raw->last;
446
447 pkt->log->action = "parsing quic long header";
448
449 if (ngx_quic_pkt_in(pkt->flags)) {
450
451 if (pkt->len < NGX_QUIC_MIN_INITIAL_SIZE) {
452 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
453 "quic UDP datagram is too small for initial packet");
454 return NGX_DECLINED;
455 }
456
457 p = ngx_quic_parse_int(p, end, &varint);
458 if (p == NULL) {
459 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
460 "quic failed to parse token length");
461 return NGX_ERROR;
462 }
463
464 pkt->token.len = varint;
465
466 p = ngx_quic_read_bytes(p, end, pkt->token.len, &pkt->token.data);
467 if (p == NULL) {
468 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
469 "quic packet too small to read token data");
470 return NGX_ERROR;
471 }
472
473 pkt->level = ssl_encryption_initial;
474
475 } else if (ngx_quic_pkt_zrtt(pkt->flags)) {
476 pkt->level = ssl_encryption_early_data;
477
478 } else if (ngx_quic_pkt_hs(pkt->flags)) {
479 pkt->level = ssl_encryption_handshake;
480
481 } else {
482 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
483 "quic bad packet type");
484 return NGX_DECLINED;
485 }
486
487 p = ngx_quic_parse_int(p, end, &varint);
488 if (p == NULL) {
489 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic bad packet length");
490 return NGX_ERROR;
491 }
492
493 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
494 "quic packet rx %s len:%uL",
495 ngx_quic_level_name(pkt->level), varint);
496
497 if (varint > (uint64_t) ((pkt->data + pkt->len) - p)) {
498 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic truncated %s packet",
499 ngx_quic_level_name(pkt->level));
500 return NGX_ERROR;
501 }
502
503 pkt->raw->pos = p;
504 pkt->len = p + varint - pkt->data;
505
506 return NGX_OK;
507 }
508
509
510 ngx_int_t
511 ngx_quic_get_packet_dcid(ngx_log_t *log, u_char *data, size_t n,
512 ngx_str_t *dcid)
513 {
514 size_t len, offset;
515
516 if (n == 0) {
517 goto failed;
518 }
519
520 if (ngx_quic_long_pkt(*data)) {
521 if (n < NGX_QUIC_LONG_DCID_LEN_OFFSET + 1) {
522 goto failed;
523 }
524
525 len = data[NGX_QUIC_LONG_DCID_LEN_OFFSET];
526 offset = NGX_QUIC_LONG_DCID_OFFSET;
527
528 } else {
529 len = NGX_QUIC_SERVER_CID_LEN;
530 offset = NGX_QUIC_SHORT_DCID_OFFSET;
531 }
532
533 if (n < len + offset) {
534 goto failed;
535 }
536
537 dcid->len = len;
538 dcid->data = &data[offset];
539
540 return NGX_OK;
541
542 failed:
543
544 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, log, 0, "quic malformed packet");
545
546 return NGX_ERROR;
547 }
548
549
550 size_t
551 ngx_quic_create_version_negotiation(ngx_quic_header_t *pkt, u_char *out)
552 {
553 u_char *p, *start;
554 ngx_uint_t i;
555
556 p = start = out;
557
558 *p++ = pkt->flags;
559
560 /*
561 * The Version field of a Version Negotiation packet
562 * MUST be set to 0x00000000
563 */
564 p = ngx_quic_write_uint32(p, 0);
565
566 *p++ = pkt->dcid.len;
567 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len);
568
569 *p++ = pkt->scid.len;
570 p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len);
571
572 for (i = 0; i < NGX_QUIC_NVERSIONS; i++) {
573 p = ngx_quic_write_uint32(p, ngx_quic_versions[i]);
574 }
575
576 return p - start;
577 }
578
579
580 size_t
581 ngx_quic_create_header(ngx_quic_header_t *pkt, u_char *out, size_t pkt_len,
582 u_char **pnp)
583 {
584 return ngx_quic_short_pkt(pkt->flags)
585 ? ngx_quic_create_short_header(pkt, out, pkt_len, pnp)
586 : ngx_quic_create_long_header(pkt, out, pkt_len, pnp);
587 }
588
589
590 static size_t
591 ngx_quic_create_long_header(ngx_quic_header_t *pkt, u_char *out,
592 size_t pkt_len, u_char **pnp)
593 {
594 u_char *p, *start;
595
596 if (out == NULL) {
597 return 5 + 2 + pkt->dcid.len + pkt->scid.len
598 + ngx_quic_varint_len(pkt_len + pkt->num_len) + pkt->num_len
599 + (pkt->level == ssl_encryption_initial ? 1 : 0);
600 }
601
602 p = start = out;
603
604 *p++ = pkt->flags;
605
606 p = ngx_quic_write_uint32(p, pkt->version);
607
608 *p++ = pkt->dcid.len;
609 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len);
610
611 *p++ = pkt->scid.len;
612 p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len);
613
614 if (pkt->level == ssl_encryption_initial) {
615 ngx_quic_build_int(&p, 0);
616 }
617
618 ngx_quic_build_int(&p, pkt_len + pkt->num_len);
619
620 *pnp = p;
621
622 switch (pkt->num_len) {
623 case 1:
624 *p++ = pkt->trunc;
625 break;
626 case 2:
627 p = ngx_quic_write_uint16(p, pkt->trunc);
628 break;
629 case 3:
630 p = ngx_quic_write_uint24(p, pkt->trunc);
631 break;
632 case 4:
633 p = ngx_quic_write_uint32(p, pkt->trunc);
634 break;
635 }
636
637 return p - start;
638 }
639
640
641 static size_t
642 ngx_quic_create_short_header(ngx_quic_header_t *pkt, u_char *out,
643 size_t pkt_len, u_char **pnp)
644 {
645 u_char *p, *start;
646
647 if (out == NULL) {
648 return 1 + pkt->dcid.len + pkt->num_len;
649 }
650
651 p = start = out;
652
653 *p++ = pkt->flags;
654
655 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len);
656
657 *pnp = p;
658
659 switch (pkt->num_len) {
660 case 1:
661 *p++ = pkt->trunc;
662 break;
663 case 2:
664 p = ngx_quic_write_uint16(p, pkt->trunc);
665 break;
666 case 3:
667 p = ngx_quic_write_uint24(p, pkt->trunc);
668 break;
669 case 4:
670 p = ngx_quic_write_uint32(p, pkt->trunc);
671 break;
672 }
673
674 return p - start;
675 }
676
677
678 size_t
679 ngx_quic_create_retry_itag(ngx_quic_header_t *pkt, u_char *out,
680 u_char **start)
681 {
682 u_char *p;
683
684 p = out;
685
686 *p++ = pkt->odcid.len;
687 p = ngx_cpymem(p, pkt->odcid.data, pkt->odcid.len);
688
689 *start = p;
690
691 *p++ = 0xff;
692
693 p = ngx_quic_write_uint32(p, pkt->version);
694
695 *p++ = pkt->dcid.len;
696 p = ngx_cpymem(p, pkt->dcid.data, pkt->dcid.len);
697
698 *p++ = pkt->scid.len;
699 p = ngx_cpymem(p, pkt->scid.data, pkt->scid.len);
700
701 p = ngx_cpymem(p, pkt->token.data, pkt->token.len);
702
703 return p - out;
704 }
705
706
707 #define ngx_quic_stream_bit_off(val) (((val) & 0x04) ? 1 : 0)
708 #define ngx_quic_stream_bit_len(val) (((val) & 0x02) ? 1 : 0)
709 #define ngx_quic_stream_bit_fin(val) (((val) & 0x01) ? 1 : 0)
710
711 ssize_t
712 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end,
713 ngx_quic_frame_t *f)
714 {
715 u_char *p;
716 uint64_t varint;
717 ngx_buf_t *b;
718 ngx_uint_t i;
719
720 b = f->data->buf;
721
722 p = start;
723
724 p = ngx_quic_parse_int(p, end, &varint);
725 if (p == NULL) {
726 pkt->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
727 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
728 "quic failed to obtain quic frame type");
729 return NGX_ERROR;
730 }
731
732 f->type = varint;
733
734 if (ngx_quic_frame_allowed(pkt, f->type) != NGX_OK) {
735 pkt->error = NGX_QUIC_ERR_PROTOCOL_VIOLATION;
736 return NGX_ERROR;
737 }
738
739 switch (f->type) {
740
741 case NGX_QUIC_FT_CRYPTO:
742
743 p = ngx_quic_parse_int(p, end, &f->u.crypto.offset);
744 if (p == NULL) {
745 goto error;
746 }
747
748 p = ngx_quic_parse_int(p, end, &f->u.crypto.length);
749 if (p == NULL) {
750 goto error;
751 }
752
753 p = ngx_quic_read_bytes(p, end, f->u.crypto.length, &b->pos);
754 if (p == NULL) {
755 goto error;
756 }
757
758 b->last = p;
759
760 break;
761
762 case NGX_QUIC_FT_PADDING:
763
764 while (p < end && *p == NGX_QUIC_FT_PADDING) {
765 p++;
766 }
767
768 break;
769
770 case NGX_QUIC_FT_ACK:
771 case NGX_QUIC_FT_ACK_ECN:
772
773 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.largest))
774 && (p = ngx_quic_parse_int(p, end, &f->u.ack.delay))
775 && (p = ngx_quic_parse_int(p, end, &f->u.ack.range_count))
776 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range))))
777 {
778 goto error;
779 }
780
781 b->pos = p;
782
783 /* process all ranges to get bounds, values are ignored */
784 for (i = 0; i < f->u.ack.range_count; i++) {
785
786 p = ngx_quic_parse_int(p, end, &varint);
787 if (p) {
788 p = ngx_quic_parse_int(p, end, &varint);
789 }
790
791 if (p == NULL) {
792 goto error;
793 }
794 }
795
796 b->last = p;
797
798 f->u.ack.ranges_length = b->last - b->pos;
799
800 if (f->type == NGX_QUIC_FT_ACK_ECN) {
801
802 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.ect0))
803 && (p = ngx_quic_parse_int(p, end, &f->u.ack.ect1))
804 && (p = ngx_quic_parse_int(p, end, &f->u.ack.ce))))
805 {
806 goto error;
807 }
808
809 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
810 "quic ACK ECN counters ect0:%uL ect1:%uL ce:%uL",
811 f->u.ack.ect0, f->u.ack.ect1, f->u.ack.ce);
812 }
813
814 break;
815
816 case NGX_QUIC_FT_PING:
817 break;
818
819 case NGX_QUIC_FT_NEW_CONNECTION_ID:
820
821 p = ngx_quic_parse_int(p, end, &f->u.ncid.seqnum);
822 if (p == NULL) {
823 goto error;
824 }
825
826 p = ngx_quic_parse_int(p, end, &f->u.ncid.retire);
827 if (p == NULL) {
828 goto error;
829 }
830
831 if (f->u.ncid.retire > f->u.ncid.seqnum) {
832 goto error;
833 }
834
835 p = ngx_quic_read_uint8(p, end, &f->u.ncid.len);
836 if (p == NULL) {
837 goto error;
838 }
839
840 if (f->u.ncid.len < 1 || f->u.ncid.len > NGX_QUIC_CID_LEN_MAX) {
841 goto error;
842 }
843
844 p = ngx_quic_copy_bytes(p, end, f->u.ncid.len, f->u.ncid.cid);
845 if (p == NULL) {
846 goto error;
847 }
848
849 p = ngx_quic_copy_bytes(p, end, NGX_QUIC_SR_TOKEN_LEN, f->u.ncid.srt);
850 if (p == NULL) {
851 goto error;
852 }
853
854 break;
855
856 case NGX_QUIC_FT_RETIRE_CONNECTION_ID:
857
858 p = ngx_quic_parse_int(p, end, &f->u.retire_cid.sequence_number);
859 if (p == NULL) {
860 goto error;
861 }
862
863 break;
864
865 case NGX_QUIC_FT_CONNECTION_CLOSE:
866 case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
867
868 p = ngx_quic_parse_int(p, end, &f->u.close.error_code);
869 if (p == NULL) {
870 goto error;
871 }
872
873 if (f->type == NGX_QUIC_FT_CONNECTION_CLOSE) {
874 p = ngx_quic_parse_int(p, end, &f->u.close.frame_type);
875 if (p == NULL) {
876 goto error;
877 }
878 }
879
880 p = ngx_quic_parse_int(p, end, &varint);
881 if (p == NULL) {
882 goto error;
883 }
884
885 f->u.close.reason.len = varint;
886
887 p = ngx_quic_read_bytes(p, end, f->u.close.reason.len,
888 &f->u.close.reason.data);
889 if (p == NULL) {
890 goto error;
891 }
892
893 break;
894
895 case NGX_QUIC_FT_STREAM0:
896 case NGX_QUIC_FT_STREAM1:
897 case NGX_QUIC_FT_STREAM2:
898 case NGX_QUIC_FT_STREAM3:
899 case NGX_QUIC_FT_STREAM4:
900 case NGX_QUIC_FT_STREAM5:
901 case NGX_QUIC_FT_STREAM6:
902 case NGX_QUIC_FT_STREAM7:
903
904 f->u.stream.type = f->type;
905
906 f->u.stream.off = ngx_quic_stream_bit_off(f->type);
907 f->u.stream.len = ngx_quic_stream_bit_len(f->type);
908 f->u.stream.fin = ngx_quic_stream_bit_fin(f->type);
909
910 p = ngx_quic_parse_int(p, end, &f->u.stream.stream_id);
911 if (p == NULL) {
912 goto error;
913 }
914
915 if (f->type & 0x04) {
916 p = ngx_quic_parse_int(p, end, &f->u.stream.offset);
917 if (p == NULL) {
918 goto error;
919 }
920
921 } else {
922 f->u.stream.offset = 0;
923 }
924
925 if (f->type & 0x02) {
926 p = ngx_quic_parse_int(p, end, &f->u.stream.length);
927 if (p == NULL) {
928 goto error;
929 }
930
931 } else {
932 f->u.stream.length = end - p; /* up to packet end */
933 }
934
935 p = ngx_quic_read_bytes(p, end, f->u.stream.length, &b->pos);
936 if (p == NULL) {
937 goto error;
938 }
939
940 b->last = p;
941 break;
942
943 case NGX_QUIC_FT_MAX_DATA:
944
945 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data);
946 if (p == NULL) {
947 goto error;
948 }
949
950 break;
951
952 case NGX_QUIC_FT_RESET_STREAM:
953
954 if (!((p = ngx_quic_parse_int(p, end, &f->u.reset_stream.id))
955 && (p = ngx_quic_parse_int(p, end, &f->u.reset_stream.error_code))
956 && (p = ngx_quic_parse_int(p, end,
957 &f->u.reset_stream.final_size))))
958 {
959 goto error;
960 }
961
962 break;
963
964 case NGX_QUIC_FT_STOP_SENDING:
965
966 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.id);
967 if (p == NULL) {
968 goto error;
969 }
970
971 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.error_code);
972 if (p == NULL) {
973 goto error;
974 }
975
976 break;
977
978 case NGX_QUIC_FT_STREAMS_BLOCKED:
979 case NGX_QUIC_FT_STREAMS_BLOCKED2:
980
981 p = ngx_quic_parse_int(p, end, &f->u.streams_blocked.limit);
982 if (p == NULL) {
983 goto error;
984 }
985
986 f->u.streams_blocked.bidi =
987 (f->type == NGX_QUIC_FT_STREAMS_BLOCKED) ? 1 : 0;
988 break;
989
990 case NGX_QUIC_FT_MAX_STREAMS:
991 case NGX_QUIC_FT_MAX_STREAMS2:
992
993 p = ngx_quic_parse_int(p, end, &f->u.max_streams.limit);
994 if (p == NULL) {
995 goto error;
996 }
997
998 f->u.max_streams.bidi = (f->type == NGX_QUIC_FT_MAX_STREAMS) ? 1 : 0;
999
1000 break;
1001
1002 case NGX_QUIC_FT_MAX_STREAM_DATA:
1003
1004 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.id);
1005 if (p == NULL) {
1006 goto error;
1007 }
1008
1009 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.limit);
1010 if (p == NULL) {
1011 goto error;
1012 }
1013
1014 break;
1015
1016 case NGX_QUIC_FT_DATA_BLOCKED:
1017
1018 p = ngx_quic_parse_int(p, end, &f->u.data_blocked.limit);
1019 if (p == NULL) {
1020 goto error;
1021 }
1022
1023 break;
1024
1025 case NGX_QUIC_FT_STREAM_DATA_BLOCKED:
1026
1027 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.id);
1028 if (p == NULL) {
1029 goto error;
1030 }
1031
1032 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.limit);
1033 if (p == NULL) {
1034 goto error;
1035 }
1036
1037 break;
1038
1039 case NGX_QUIC_FT_PATH_CHALLENGE:
1040
1041 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_challenge.data);
1042 if (p == NULL) {
1043 goto error;
1044 }
1045
1046 break;
1047
1048 case NGX_QUIC_FT_PATH_RESPONSE:
1049
1050 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_response.data);
1051 if (p == NULL) {
1052 goto error;
1053 }
1054
1055 break;
1056
1057 default:
1058 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
1059 "quic unknown frame type 0x%xi", f->type);
1060 return NGX_ERROR;
1061 }
1062
1063 f->level = pkt->level;
1064
1065 return p - start;
1066
1067 error:
1068
1069 pkt->error = NGX_QUIC_ERR_FRAME_ENCODING_ERROR;
1070
1071 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
1072 "quic failed to parse frame type:0x%xi", f->type);
1073
1074 return NGX_ERROR;
1075 }
1076
1077
1078 static ngx_int_t
1079 ngx_quic_frame_allowed(ngx_quic_header_t *pkt, ngx_uint_t frame_type)
1080 {
1081 uint8_t ptype;
1082
1083 /* frame permissions per packet: 4 bits: IH01: 12.4, Table 3 */
1084 static uint8_t ngx_quic_frame_masks[] = {
1085 /* PADDING */ 0xF,
1086 /* PING */ 0xF,
1087 /* ACK */ 0xD,
1088 /* ACK_ECN */ 0xD,
1089 /* RESET_STREAM */ 0x3,
1090 /* STOP_SENDING */ 0x3,
1091 /* CRYPTO */ 0xD,
1092 /* NEW_TOKEN */ 0x0, /* only sent by server */
1093 /* STREAM0 */ 0x3,
1094 /* STREAM1 */ 0x3,
1095 /* STREAM2 */ 0x3,
1096 /* STREAM3 */ 0x3,
1097 /* STREAM4 */ 0x3,
1098 /* STREAM5 */ 0x3,
1099 /* STREAM6 */ 0x3,
1100 /* STREAM7 */ 0x3,
1101 /* MAX_DATA */ 0x3,
1102 /* MAX_STREAM_DATA */ 0x3,
1103 /* MAX_STREAMS */ 0x3,
1104 /* MAX_STREAMS2 */ 0x3,
1105 /* DATA_BLOCKED */ 0x3,
1106 /* STREAM_DATA_BLOCKED */ 0x3,
1107 /* STREAMS_BLOCKED */ 0x3,
1108 /* STREAMS_BLOCKED2 */ 0x3,
1109 /* NEW_CONNECTION_ID */ 0x3,
1110 /* RETIRE_CONNECTION_ID */ 0x3,
1111 /* PATH_CHALLENGE */ 0x3,
1112 /* PATH_RESPONSE */ 0x3,
1113 #if (NGX_QUIC_DRAFT_VERSION >= 28)
1114 /* CONNECTION_CLOSE */ 0xF,
1115 /* CONNECTION_CLOSE2 */ 0x3,
1116 #else
1117 /* CONNECTION_CLOSE */ 0xD,
1118 /* CONNECTION_CLOSE2 */ 0x1,
1119 #endif
1120 /* HANDSHAKE_DONE */ 0x0, /* only sent by server */
1121 };
1122
1123 if (ngx_quic_long_pkt(pkt->flags)) {
1124
1125 if (ngx_quic_pkt_in(pkt->flags)) {
1126 ptype = 8; /* initial */
1127
1128 } else if (ngx_quic_pkt_hs(pkt->flags)) {
1129 ptype = 4; /* handshake */
1130
1131 } else {
1132 ptype = 2; /* zero-rtt */
1133 }
1134
1135 } else {
1136 ptype = 1; /* application data */
1137 }
1138
1139 if (ptype & ngx_quic_frame_masks[frame_type]) {
1140 return NGX_OK;
1141 }
1142
1143 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
1144 "quic frame type 0x%xi is not "
1145 "allowed in packet with flags 0x%xd",
1146 frame_type, pkt->flags);
1147
1148 return NGX_DECLINED;
1149 }
1150
1151
1152 ssize_t
1153 ngx_quic_parse_ack_range(ngx_log_t *log, u_char *start, u_char *end,
1154 uint64_t *gap, uint64_t *range)
1155 {
1156 u_char *p;
1157
1158 p = start;
1159
1160 p = ngx_quic_parse_int(p, end, gap);
1161 if (p == NULL) {
1162 ngx_log_error(NGX_LOG_INFO, log, 0,
1163 "quic failed to parse ack frame gap");
1164 return NGX_ERROR;
1165 }
1166
1167 p = ngx_quic_parse_int(p, end, range);
1168 if (p == NULL) {
1169 ngx_log_error(NGX_LOG_INFO, log, 0,
1170 "quic failed to parse ack frame range");
1171 return NGX_ERROR;
1172 }
1173
1174 return p - start;
1175 }
1176
1177
1178 size_t
1179 ngx_quic_create_ack_range(u_char *p, uint64_t gap, uint64_t range)
1180 {
1181 size_t len;
1182 u_char *start;
1183
1184 if (p == NULL) {
1185 len = ngx_quic_varint_len(gap);
1186 len += ngx_quic_varint_len(range);
1187 return len;
1188 }
1189
1190 start = p;
1191
1192 ngx_quic_build_int(&p, gap);
1193 ngx_quic_build_int(&p, range);
1194
1195 return p - start;
1196 }
1197
1198
1199 ssize_t
1200 ngx_quic_create_frame(u_char *p, ngx_quic_frame_t *f)
1201 {
1202 /*
1203 * QUIC-recovery, section 2:
1204 *
1205 * Ack-eliciting Frames: All frames other than ACK, PADDING, and
1206 * CONNECTION_CLOSE are considered ack-eliciting.
1207 */
1208 f->need_ack = 1;
1209
1210 switch (f->type) {
1211 case NGX_QUIC_FT_ACK:
1212 f->need_ack = 0;
1213 return ngx_quic_create_ack(p, &f->u.ack, f->data);
1214
1215 case NGX_QUIC_FT_STOP_SENDING:
1216 return ngx_quic_create_stop_sending(p, &f->u.stop_sending);
1217
1218 case NGX_QUIC_FT_CRYPTO:
1219 return ngx_quic_create_crypto(p, &f->u.crypto, f->data);
1220
1221 case NGX_QUIC_FT_HANDSHAKE_DONE:
1222 return ngx_quic_create_hs_done(p);
1223
1224 case NGX_QUIC_FT_NEW_TOKEN:
1225 return ngx_quic_create_new_token(p, &f->u.token);
1226
1227 case NGX_QUIC_FT_STREAM0:
1228 case NGX_QUIC_FT_STREAM1:
1229 case NGX_QUIC_FT_STREAM2:
1230 case NGX_QUIC_FT_STREAM3:
1231 case NGX_QUIC_FT_STREAM4:
1232 case NGX_QUIC_FT_STREAM5:
1233 case NGX_QUIC_FT_STREAM6:
1234 case NGX_QUIC_FT_STREAM7:
1235 return ngx_quic_create_stream(p, &f->u.stream, f->data);
1236
1237 case NGX_QUIC_FT_CONNECTION_CLOSE:
1238 case NGX_QUIC_FT_CONNECTION_CLOSE_APP:
1239 f->need_ack = 0;
1240 return ngx_quic_create_close(p, &f->u.close);
1241
1242 case NGX_QUIC_FT_MAX_STREAMS:
1243 return ngx_quic_create_max_streams(p, &f->u.max_streams);
1244
1245 case NGX_QUIC_FT_MAX_STREAM_DATA:
1246 return ngx_quic_create_max_stream_data(p, &f->u.max_stream_data);
1247
1248 case NGX_QUIC_FT_MAX_DATA:
1249 return ngx_quic_create_max_data(p, &f->u.max_data);
1250
1251 case NGX_QUIC_FT_PATH_RESPONSE:
1252 return ngx_quic_create_path_response(p, &f->u.path_response);
1253
1254 case NGX_QUIC_FT_NEW_CONNECTION_ID:
1255 return ngx_quic_create_new_connection_id(p, &f->u.ncid);
1256
1257 case NGX_QUIC_FT_RETIRE_CONNECTION_ID:
1258 return ngx_quic_create_retire_connection_id(p, &f->u.retire_cid);
1259
1260 default:
1261 /* BUG: unsupported frame type generated */
1262 return NGX_ERROR;
1263 }
1264 }
1265
1266
1267 static size_t
1268 ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack, ngx_chain_t *ranges)
1269 {
1270 size_t len;
1271 u_char *start;
1272 ngx_buf_t *b;
1273
1274 if (p == NULL) {
1275 len = ngx_quic_varint_len(NGX_QUIC_FT_ACK);
1276 len += ngx_quic_varint_len(ack->largest);
1277 len += ngx_quic_varint_len(ack->delay);
1278 len += ngx_quic_varint_len(ack->range_count);
1279 len += ngx_quic_varint_len(ack->first_range);
1280 len += ack->ranges_length;
1281
1282 return len;
1283 }
1284
1285 start = p;
1286
1287 ngx_quic_build_int(&p, NGX_QUIC_FT_ACK);
1288 ngx_quic_build_int(&p, ack->largest);
1289 ngx_quic_build_int(&p, ack->delay);
1290 ngx_quic_build_int(&p, ack->range_count);
1291 ngx_quic_build_int(&p, ack->first_range);
1292
1293 while (ranges) {
1294 b = ranges->buf;
1295 p = ngx_cpymem(p, b->pos, b->last - b->pos);
1296 ranges = ranges->next;
1297 }
1298
1299 return p - start;
1300 }
1301
1302
1303 static size_t
1304 ngx_quic_create_stop_sending(u_char *p, ngx_quic_stop_sending_frame_t *ss)
1305 {
1306 size_t len;
1307 u_char *start;
1308
1309 if (p == NULL) {
1310 len = ngx_quic_varint_len(NGX_QUIC_FT_STOP_SENDING);
1311 len += ngx_quic_varint_len(ss->id);
1312 len += ngx_quic_varint_len(ss->error_code);
1313 return len;
1314 }
1315
1316 start = p;
1317
1318 ngx_quic_build_int(&p, NGX_QUIC_FT_STOP_SENDING);
1319 ngx_quic_build_int(&p, ss->id);
1320 ngx_quic_build_int(&p, ss->error_code);
1321
1322 return p - start;
1323 }
1324
1325
1326 static size_t
1327 ngx_quic_create_crypto(u_char *p, ngx_quic_crypto_frame_t *crypto,
1328 ngx_chain_t *data)
1329 {
1330 size_t len;
1331 u_char *start;
1332 ngx_buf_t *b;
1333
1334 if (p == NULL) {
1335 len = ngx_quic_varint_len(NGX_QUIC_FT_CRYPTO);
1336 len += ngx_quic_varint_len(crypto->offset);
1337 len += ngx_quic_varint_len(crypto->length);
1338 len += crypto->length;
1339
1340 return len;
1341 }
1342
1343 start = p;
1344
1345 ngx_quic_build_int(&p, NGX_QUIC_FT_CRYPTO);
1346 ngx_quic_build_int(&p, crypto->offset);
1347 ngx_quic_build_int(&p, crypto->length);
1348
1349 while (data) {
1350 b = data->buf;
1351 p = ngx_cpymem(p, b->pos, b->last - b->pos);
1352 data = data->next;
1353 }
1354
1355 return p - start;
1356 }
1357
1358
1359 static size_t
1360 ngx_quic_create_hs_done(u_char *p)
1361 {
1362 u_char *start;
1363
1364 if (p == NULL) {
1365 return ngx_quic_varint_len(NGX_QUIC_FT_HANDSHAKE_DONE);
1366 }
1367
1368 start = p;
1369
1370 ngx_quic_build_int(&p, NGX_QUIC_FT_HANDSHAKE_DONE);
1371
1372 return p - start;
1373 }
1374
1375
1376 static size_t
1377 ngx_quic_create_new_token(u_char *p, ngx_quic_new_token_frame_t *token)
1378 {
1379 size_t len;
1380 u_char *start;
1381
1382 if (p == NULL) {
1383 len = ngx_quic_varint_len(NGX_QUIC_FT_NEW_TOKEN);
1384 len += ngx_quic_varint_len(token->length);
1385 len += token->length;
1386
1387 return len;
1388 }
1389
1390 start = p;
1391
1392 ngx_quic_build_int(&p, NGX_QUIC_FT_NEW_TOKEN);
1393 ngx_quic_build_int(&p, token->length);
1394 p = ngx_cpymem(p, token->data, token->length);
1395
1396 return p - start;
1397 }
1398
1399
1400 static size_t
1401 ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf,
1402 ngx_chain_t *data)
1403 {
1404 size_t len;
1405 u_char *start;
1406 ngx_buf_t *b;
1407
1408 if (p == NULL) {
1409 len = ngx_quic_varint_len(sf->type);
1410
1411 if (sf->off) {
1412 len += ngx_quic_varint_len(sf->offset);
1413 }
1414
1415 len += ngx_quic_varint_len(sf->stream_id);
1416
1417 /* length is always present in generated frames */
1418 len += ngx_quic_varint_len(sf->length);
1419
1420 len += sf->length;
1421
1422 return len;
1423 }
1424
1425 start = p;
1426
1427 ngx_quic_build_int(&p, sf->type);
1428 ngx_quic_build_int(&p, sf->stream_id);
1429
1430 if (sf->off) {
1431 ngx_quic_build_int(&p, sf->offset);
1432 }
1433
1434 /* length is always present in generated frames */
1435 ngx_quic_build_int(&p, sf->length);
1436
1437 while (data) {
1438 b = data->buf;
1439 p = ngx_cpymem(p, b->pos, b->last - b->pos);
1440 data = data->next;
1441 }
1442
1443 return p - start;
1444 }
1445
1446
1447 static size_t
1448 ngx_quic_create_max_streams(u_char *p, ngx_quic_max_streams_frame_t *ms)
1449 {
1450 size_t len;
1451 u_char *start;
1452 ngx_uint_t type;
1453
1454 type = ms->bidi ? NGX_QUIC_FT_MAX_STREAMS : NGX_QUIC_FT_MAX_STREAMS2;
1455
1456 if (p == NULL) {
1457 len = ngx_quic_varint_len(type);
1458 len += ngx_quic_varint_len(ms->limit);
1459 return len;
1460 }
1461
1462 start = p;
1463
1464 ngx_quic_build_int(&p, type);
1465 ngx_quic_build_int(&p, ms->limit);
1466
1467 return p - start;
1468 }
1469
1470
1471 static ngx_int_t
1472 ngx_quic_parse_transport_param(u_char *p, u_char *end, uint16_t id,
1473 ngx_quic_tp_t *dst)
1474 {
1475 uint64_t varint;
1476 ngx_str_t str;
1477
1478 varint = 0;
1479 ngx_str_null(&str);
1480
1481 switch (id) {
1482
1483 case NGX_QUIC_TP_DISABLE_ACTIVE_MIGRATION:
1484 /* zero-length option */
1485 if (end - p != 0) {
1486 return NGX_ERROR;
1487 }
1488 dst->disable_active_migration = 1;
1489 return NGX_OK;
1490
1491 case NGX_QUIC_TP_MAX_IDLE_TIMEOUT:
1492 case NGX_QUIC_TP_MAX_UDP_PAYLOAD_SIZE:
1493 case NGX_QUIC_TP_INITIAL_MAX_DATA:
1494 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
1495 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
1496 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI:
1497 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI:
1498 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI:
1499 case NGX_QUIC_TP_ACK_DELAY_EXPONENT:
1500 case NGX_QUIC_TP_MAX_ACK_DELAY:
1501 case NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT:
1502
1503 p = ngx_quic_parse_int(p, end, &varint);
1504 if (p == NULL) {
1505 return NGX_ERROR;
1506 }
1507 break;
1508
1509 case NGX_QUIC_TP_INITIAL_SCID:
1510
1511 str.len = end - p;
1512 str.data = p;
1513 break;
1514
1515 default:
1516 return NGX_DECLINED;
1517 }
1518
1519 switch (id) {
1520
1521 case NGX_QUIC_TP_MAX_IDLE_TIMEOUT:
1522 dst->max_idle_timeout = varint;
1523 break;
1524
1525 case NGX_QUIC_TP_MAX_UDP_PAYLOAD_SIZE:
1526 dst->max_udp_payload_size = varint;
1527 break;
1528
1529 case NGX_QUIC_TP_INITIAL_MAX_DATA:
1530 dst->initial_max_data = varint;
1531 break;
1532
1533 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
1534 dst->initial_max_stream_data_bidi_local = varint;
1535 break;
1536
1537 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
1538 dst->initial_max_stream_data_bidi_remote = varint;
1539 break;
1540
1541 case NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI:
1542 dst->initial_max_stream_data_uni = varint;
1543 break;
1544
1545 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI:
1546 dst->initial_max_streams_bidi = varint;
1547 break;
1548
1549 case NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI:
1550 dst->initial_max_streams_uni = varint;
1551 break;
1552
1553 case NGX_QUIC_TP_ACK_DELAY_EXPONENT:
1554 dst->ack_delay_exponent = varint;
1555 break;
1556
1557 case NGX_QUIC_TP_MAX_ACK_DELAY:
1558 dst->max_ack_delay = varint;
1559 break;
1560
1561 case NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT:
1562 dst->active_connection_id_limit = varint;
1563 break;
1564
1565 case NGX_QUIC_TP_INITIAL_SCID:
1566 dst->initial_scid = str;
1567 break;
1568
1569 default:
1570 return NGX_ERROR;
1571 }
1572
1573 return NGX_OK;
1574 }
1575
1576
1577 ngx_int_t
1578 ngx_quic_parse_transport_params(u_char *p, u_char *end, ngx_quic_tp_t *tp,
1579 ngx_log_t *log)
1580 {
1581 uint64_t id, len;
1582 ngx_int_t rc;
1583
1584 while (p < end) {
1585 p = ngx_quic_parse_int(p, end, &id);
1586 if (p == NULL) {
1587 ngx_log_error(NGX_LOG_INFO, log, 0,
1588 "quic failed to parse transport param id");
1589 return NGX_ERROR;
1590 }
1591
1592 switch (id) {
1593 case NGX_QUIC_TP_ORIGINAL_DCID:
1594 case NGX_QUIC_TP_PREFERRED_ADDRESS:
1595 case NGX_QUIC_TP_RETRY_SCID:
1596 case NGX_QUIC_TP_SR_TOKEN:
1597 ngx_log_error(NGX_LOG_INFO, log, 0,
1598 "quic client sent forbidden transport param"
1599 " id:0x%xL", id);
1600 return NGX_ERROR;
1601 }
1602
1603 p = ngx_quic_parse_int(p, end, &len);
1604 if (p == NULL) {
1605 ngx_log_error(NGX_LOG_INFO, log, 0,
1606 "quic failed to parse"
1607 " transport param id:0x%xL length", id);
1608 return NGX_ERROR;
1609 }
1610
1611 rc = ngx_quic_parse_transport_param(p, p + len, id, tp);
1612
1613 if (rc == NGX_ERROR) {
1614 ngx_log_error(NGX_LOG_INFO, log, 0,
1615 "quic failed to parse"
1616 " transport param id:0x%xL data", id);
1617 return NGX_ERROR;
1618 }
1619
1620 if (rc == NGX_DECLINED) {
1621 ngx_log_error(NGX_LOG_INFO, log, 0,
1622 "quic unknown transport param id:0x%xL, skipped", id);
1623 }
1624
1625 p += len;
1626 }
1627
1628 if (p != end) {
1629 ngx_log_error(NGX_LOG_INFO, log, 0,
1630 "quic trailing garbage in"
1631 " transport parameters: bytes:%ui",
1632 end - p);
1633 return NGX_ERROR;
1634 }
1635
1636 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, log, 0,
1637 "quic transport parameters parsed ok");
1638
1639 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1640 "quic tp disable active migration: %ui",
1641 tp->disable_active_migration);
1642
1643 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "quic tp idle_timeout:%ui",
1644 tp->max_idle_timeout);
1645
1646 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1647 "quic tp max_udp_payload_size:%ui",
1648 tp->max_udp_payload_size);
1649
1650 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "quic tp max_data:%ui",
1651 tp->initial_max_data);
1652
1653 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1654 "quic tp max_stream_data_bidi_local:%ui",
1655 tp->initial_max_stream_data_bidi_local);
1656
1657 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1658 "quic tp max_stream_data_bidi_remote:%ui",
1659 tp->initial_max_stream_data_bidi_remote);
1660
1661 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1662 "quic tp max_stream_data_uni:%ui",
1663 tp->initial_max_stream_data_uni);
1664
1665 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1666 "quic tp initial_max_streams_bidi:%ui",
1667 tp->initial_max_streams_bidi);
1668
1669 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1670 "quic tp initial_max_streams_uni:%ui",
1671 tp->initial_max_streams_uni);
1672
1673 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1674 "quic tp ack_delay_exponent:%ui",
1675 tp->ack_delay_exponent);
1676
1677 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "quic tp max_ack_delay:%ui",
1678 tp->max_ack_delay);
1679
1680 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
1681 "quic tp active_connection_id_limit:%ui",
1682 tp->active_connection_id_limit);
1683
1684 #if (NGX_QUIC_DRAFT_VERSION >= 28)
1685 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
1686 "quic tp initial source_connection_id len:%uz %xV",
1687 tp->initial_scid.len, &tp->initial_scid);
1688 #endif
1689
1690 return NGX_OK;
1691 }
1692
1693
1694 static size_t
1695 ngx_quic_create_max_stream_data(u_char *p, ngx_quic_max_stream_data_frame_t *ms)
1696 {
1697 size_t len;
1698 u_char *start;
1699
1700 if (p == NULL) {
1701 len = ngx_quic_varint_len(NGX_QUIC_FT_MAX_STREAM_DATA);
1702 len += ngx_quic_varint_len(ms->id);
1703 len += ngx_quic_varint_len(ms->limit);
1704 return len;
1705 }
1706
1707 start = p;
1708
1709 ngx_quic_build_int(&p, NGX_QUIC_FT_MAX_STREAM_DATA);
1710 ngx_quic_build_int(&p, ms->id);
1711 ngx_quic_build_int(&p, ms->limit);
1712
1713 return p - start;
1714 }
1715
1716
1717 static size_t
1718 ngx_quic_create_max_data(u_char *p, ngx_quic_max_data_frame_t *md)
1719 {
1720 size_t len;
1721 u_char *start;
1722
1723 if (p == NULL) {
1724 len = ngx_quic_varint_len(NGX_QUIC_FT_MAX_DATA);
1725 len += ngx_quic_varint_len(md->max_data);
1726 return len;
1727 }
1728
1729 start = p;
1730
1731 ngx_quic_build_int(&p, NGX_QUIC_FT_MAX_DATA);
1732 ngx_quic_build_int(&p, md->max_data);
1733
1734 return p - start;
1735 }
1736
1737
1738 static size_t
1739 ngx_quic_create_path_response(u_char *p, ngx_quic_path_challenge_frame_t *pc)
1740 {
1741 size_t len;
1742 u_char *start;
1743
1744 if (p == NULL) {
1745 len = ngx_quic_varint_len(NGX_QUIC_FT_PATH_RESPONSE);
1746 len += sizeof(pc->data);
1747 return len;
1748 }
1749
1750 start = p;
1751
1752 ngx_quic_build_int(&p, NGX_QUIC_FT_PATH_RESPONSE);
1753 p = ngx_cpymem(p, &pc->data, sizeof(pc->data));
1754
1755 return p - start;
1756 }
1757
1758
1759 static size_t
1760 ngx_quic_create_new_connection_id(u_char *p, ngx_quic_new_conn_id_frame_t *ncid)
1761 {
1762 size_t len;
1763 u_char *start;
1764
1765 if (p == NULL) {
1766 len = ngx_quic_varint_len(NGX_QUIC_FT_NEW_CONNECTION_ID);
1767 len += ngx_quic_varint_len(ncid->seqnum);
1768 len += ngx_quic_varint_len(ncid->retire);
1769 len++;
1770 len += ncid->len;
1771 len += NGX_QUIC_SR_TOKEN_LEN;
1772 return len;
1773 }
1774
1775 start = p;
1776
1777 ngx_quic_build_int(&p, NGX_QUIC_FT_NEW_CONNECTION_ID);
1778 ngx_quic_build_int(&p, ncid->seqnum);
1779 ngx_quic_build_int(&p, ncid->retire);
1780 *p++ = ncid->len;
1781 p = ngx_cpymem(p, ncid->cid, ncid->len);
1782 p = ngx_cpymem(p, ncid->srt, NGX_QUIC_SR_TOKEN_LEN);
1783
1784 return p - start;
1785 }
1786
1787
1788 static size_t
1789 ngx_quic_create_retire_connection_id(u_char *p,
1790 ngx_quic_retire_cid_frame_t *rcid)
1791 {
1792 size_t len;
1793 u_char *start;
1794
1795 if (p == NULL) {
1796 len = ngx_quic_varint_len(NGX_QUIC_FT_RETIRE_CONNECTION_ID);
1797 len += ngx_quic_varint_len(rcid->sequence_number);
1798 return len;
1799 }
1800
1801 start = p;
1802
1803 ngx_quic_build_int(&p, NGX_QUIC_FT_RETIRE_CONNECTION_ID);
1804 ngx_quic_build_int(&p, rcid->sequence_number);
1805
1806 return p - start;
1807 }
1808
1809
1810 ssize_t
1811 ngx_quic_create_transport_params(u_char *pos, u_char *end, ngx_quic_tp_t *tp,
1812 size_t *clen)
1813 {
1814 u_char *p;
1815 size_t len;
1816
1817 #define ngx_quic_tp_len(id, value) \
1818 ngx_quic_varint_len(id) \
1819 + ngx_quic_varint_len(value) \
1820 + ngx_quic_varint_len(ngx_quic_varint_len(value))
1821
1822 #define ngx_quic_tp_vint(id, value) \
1823 do { \
1824 ngx_quic_build_int(&p, id); \
1825 ngx_quic_build_int(&p, ngx_quic_varint_len(value)); \
1826 ngx_quic_build_int(&p, value); \
1827 } while (0)
1828
1829 #define ngx_quic_tp_strlen(id, value) \
1830 ngx_quic_varint_len(id) \
1831 + ngx_quic_varint_len(value.len) \
1832 + value.len
1833
1834 #define ngx_quic_tp_str(id, value) \
1835 do { \
1836 ngx_quic_build_int(&p, id); \
1837 ngx_quic_build_int(&p, value.len); \
1838 p = ngx_cpymem(p, value.data, value.len); \
1839 } while (0)
1840
1841 p = pos;
1842
1843 len = ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_DATA, tp->initial_max_data);
1844
1845 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI,
1846 tp->initial_max_streams_uni);
1847
1848 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI,
1849 tp->initial_max_streams_bidi);
1850
1851 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
1852 tp->initial_max_stream_data_bidi_local);
1853
1854 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
1855 tp->initial_max_stream_data_bidi_remote);
1856
1857 len += ngx_quic_tp_len(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI,
1858 tp->initial_max_stream_data_uni);
1859
1860 len += ngx_quic_tp_len(NGX_QUIC_TP_MAX_IDLE_TIMEOUT,
1861 tp->max_idle_timeout);
1862
1863 if (clen) {
1864 *clen = len;
1865 }
1866
1867 if (tp->disable_active_migration) {
1868 len += ngx_quic_varint_len(NGX_QUIC_TP_DISABLE_ACTIVE_MIGRATION);
1869 len += ngx_quic_varint_len(0);
1870 }
1871
1872 len += ngx_quic_tp_len(NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT,
1873 tp->active_connection_id_limit);
1874
1875 #if (NGX_QUIC_DRAFT_VERSION >= 28)
1876 len += ngx_quic_tp_strlen(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid);
1877 len += ngx_quic_tp_strlen(NGX_QUIC_TP_INITIAL_SCID, tp->initial_scid);
1878
1879 if (tp->retry_scid.len) {
1880 len += ngx_quic_tp_strlen(NGX_QUIC_TP_RETRY_SCID, tp->retry_scid);
1881 }
1882 #else
1883 if (tp->original_dcid.len) {
1884 len += ngx_quic_tp_strlen(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid);
1885 }
1886 #endif
1887
1888 len += ngx_quic_varint_len(NGX_QUIC_TP_SR_TOKEN);
1889 len += ngx_quic_varint_len(NGX_QUIC_SR_TOKEN_LEN);
1890 len += NGX_QUIC_SR_TOKEN_LEN;
1891
1892 if (pos == NULL) {
1893 return len;
1894 }
1895
1896 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_DATA,
1897 tp->initial_max_data);
1898
1899 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAMS_UNI,
1900 tp->initial_max_streams_uni);
1901
1902 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAMS_BIDI,
1903 tp->initial_max_streams_bidi);
1904
1905 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
1906 tp->initial_max_stream_data_bidi_local);
1907
1908 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
1909 tp->initial_max_stream_data_bidi_remote);
1910
1911 ngx_quic_tp_vint(NGX_QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI,
1912 tp->initial_max_stream_data_uni);
1913
1914 ngx_quic_tp_vint(NGX_QUIC_TP_MAX_IDLE_TIMEOUT,
1915 tp->max_idle_timeout);
1916
1917 if (tp->disable_active_migration) {
1918 ngx_quic_build_int(&p, NGX_QUIC_TP_DISABLE_ACTIVE_MIGRATION);
1919 ngx_quic_build_int(&p, 0);
1920 }
1921
1922 ngx_quic_tp_vint(NGX_QUIC_TP_ACTIVE_CONNECTION_ID_LIMIT,
1923 tp->active_connection_id_limit);
1924
1925 #if (NGX_QUIC_DRAFT_VERSION >= 28)
1926 ngx_quic_tp_str(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid);
1927 ngx_quic_tp_str(NGX_QUIC_TP_INITIAL_SCID, tp->initial_scid);
1928
1929 if (tp->retry_scid.len) {
1930 ngx_quic_tp_str(NGX_QUIC_TP_RETRY_SCID, tp->retry_scid);
1931 }
1932 #else
1933 if (tp->original_dcid.len) {
1934 ngx_quic_tp_str(NGX_QUIC_TP_ORIGINAL_DCID, tp->original_dcid);
1935 }
1936 #endif
1937
1938 ngx_quic_build_int(&p, NGX_QUIC_TP_SR_TOKEN);
1939 ngx_quic_build_int(&p, NGX_QUIC_SR_TOKEN_LEN);
1940 p = ngx_cpymem(p, tp->sr_token, NGX_QUIC_SR_TOKEN_LEN);
1941
1942 return p - pos;
1943 }
1944
1945
1946 static size_t
1947 ngx_quic_create_close(u_char *p, ngx_quic_close_frame_t *cl)
1948 {
1949 size_t len;
1950 u_char *start;
1951 ngx_uint_t type;
1952
1953 type = cl->app ? NGX_QUIC_FT_CONNECTION_CLOSE_APP
1954 : NGX_QUIC_FT_CONNECTION_CLOSE;
1955
1956 if (p == NULL) {
1957 len = ngx_quic_varint_len(type);
1958 len += ngx_quic_varint_len(cl->error_code);
1959
1960 if (!cl->app) {
1961 len += ngx_quic_varint_len(cl->frame_type);
1962 }
1963
1964 len += ngx_quic_varint_len(cl->reason.len);
1965 len += cl->reason.len;
1966
1967 return len;
1968 }
1969
1970 start = p;
1971
1972 ngx_quic_build_int(&p, type);
1973 ngx_quic_build_int(&p, cl->error_code);
1974
1975 if (!cl->app) {
1976 ngx_quic_build_int(&p, cl->frame_type);
1977 }
1978
1979 ngx_quic_build_int(&p, cl->reason.len);
1980 p = ngx_cpymem(p, cl->reason.data, cl->reason.len);
1981
1982 return p - start;
1983 }