comparison src/event/ngx_event_quic_transport.c @ 8641:fe53def49945 quic

QUIC: refactored long header parsing. The largely duplicate type-specific functions ngx_quic_parse_initial_header(), ngx_quic_parse_handshake_header(), and a missing one for 0-RTT, were merged. The new order of functions listed in ngx_event_quic_transport.c reflects this. |_ ngx_quic_parse_long_header - version-invariant long header fields \_ ngx_quic_supported_version - a helper to decide we can go further \_ ngx_quic_parse_long_header_v1 - QUICv1-specific long header fields 0-RTT packets previously appeared as Handshake are now logged as appropriate: *1 quic packet rx long flags:db version:ff00001d *1 quic packet rx early len:870 Logging SCID/DCID is no longer duplicated as were seen with Initial packets.
author Sergey Kandaurov <pluknet@nginx.com>
date Tue, 17 Nov 2020 21:32:04 +0000
parents 46374c3fee3f
children 05b1ee464350
comparison
equal deleted inserted replaced
8640:46374c3fee3f 8641:fe53def49945
76 76
77 static ngx_int_t ngx_quic_parse_short_header(ngx_quic_header_t *pkt, 77 static ngx_int_t ngx_quic_parse_short_header(ngx_quic_header_t *pkt,
78 size_t dcid_len); 78 size_t dcid_len);
79 static ngx_int_t ngx_quic_parse_long_header(ngx_quic_header_t *pkt); 79 static ngx_int_t ngx_quic_parse_long_header(ngx_quic_header_t *pkt);
80 static ngx_int_t ngx_quic_supported_version(uint32_t version); 80 static ngx_int_t ngx_quic_supported_version(uint32_t version);
81 static ngx_int_t ngx_quic_parse_initial_header(ngx_quic_header_t *pkt); 81 static ngx_int_t ngx_quic_parse_long_header_v1(ngx_quic_header_t *pkt);
82 static ngx_int_t ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt);
83 82
84 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt, 83 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt,
85 ngx_uint_t frame_type); 84 ngx_uint_t frame_type);
86 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack); 85 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack);
87 static size_t ngx_quic_create_stop_sending(u_char *p, 86 static size_t ngx_quic_create_stop_sending(u_char *p,
289 288
290 if (!ngx_quic_supported_version(pkt->version)) { 289 if (!ngx_quic_supported_version(pkt->version)) {
291 return NGX_ABORT; 290 return NGX_ABORT;
292 } 291 }
293 292
293 if (ngx_quic_parse_long_header_v1(pkt) != NGX_OK) {
294 return NGX_DECLINED;
295 }
296
297 return NGX_OK;
298 }
299
300
301 static ngx_int_t
302 ngx_quic_parse_short_header(ngx_quic_header_t *pkt, size_t dcid_len)
303 {
304 u_char *p, *end;
305
306 p = pkt->raw->pos;
307 end = pkt->data + pkt->len;
308
309 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
310 "quic packet rx short flags:%xd", pkt->flags);
311
312 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
313 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
314 return NGX_ERROR;
315 }
316
317 pkt->dcid.len = dcid_len;
318
319 p = ngx_quic_read_bytes(p, end, dcid_len, &pkt->dcid.data);
320 if (p == NULL) {
321 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
322 "quic packet is too small to read dcid");
323 return NGX_ERROR;
324 }
325
326 pkt->raw->pos = p;
327
328 return NGX_OK;
329 }
330
331
332 static ngx_int_t
333 ngx_quic_parse_long_header(ngx_quic_header_t *pkt)
334 {
335 u_char *p, *end;
336 uint8_t idlen;
337
338 p = pkt->raw->pos;
339 end = pkt->data + pkt->len;
340
341 p = ngx_quic_read_uint32(p, end, &pkt->version);
342 if (p == NULL) {
343 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
344 "quic packet is too small to read version");
345 return NGX_ERROR;
346 }
347
348 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
349 "quic packet rx long flags:%xd version:%xD",
350 pkt->flags, pkt->version);
351
352 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
353 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
354 return NGX_ERROR;
355 }
356
357 p = ngx_quic_read_uint8(p, end, &idlen);
358 if (p == NULL) {
359 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
360 "quic packet is too small to read dcid len");
361 return NGX_ERROR;
362 }
363
364 if (idlen > NGX_QUIC_CID_LEN_MAX) {
365 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
366 "quic packet dcid is too long");
367 return NGX_ERROR;
368 }
369
370 pkt->dcid.len = idlen;
371
372 p = ngx_quic_read_bytes(p, end, idlen, &pkt->dcid.data);
373 if (p == NULL) {
374 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
375 "quic packet is too small to read dcid");
376 return NGX_ERROR;
377 }
378
379 p = ngx_quic_read_uint8(p, end, &idlen);
380 if (p == NULL) {
381 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
382 "quic packet is too small to read scid len");
383 return NGX_ERROR;
384 }
385
386 if (idlen > NGX_QUIC_CID_LEN_MAX) {
387 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
388 "quic packet scid is too long");
389 return NGX_ERROR;
390 }
391
392 pkt->scid.len = idlen;
393
394 p = ngx_quic_read_bytes(p, end, idlen, &pkt->scid.data);
395 if (p == NULL) {
396 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
397 "quic packet is too small to read scid");
398 return NGX_ERROR;
399 }
400
401 pkt->raw->pos = p;
402
403 return NGX_OK;
404 }
405
406
407 static ngx_int_t
408 ngx_quic_supported_version(uint32_t version)
409 {
410 ngx_uint_t i;
411
412 for (i = 0; i < NGX_QUIC_NVERSIONS; i++) {
413 if (ngx_quic_versions[i] == version) {
414 return 1;
415 }
416 }
417
418 return 0;
419 }
420
421
422 static ngx_int_t
423 ngx_quic_parse_long_header_v1(ngx_quic_header_t *pkt)
424 {
425 u_char *p, *end;
426 uint64_t varint;
427
428 p = pkt->raw->pos;
429 end = pkt->raw->last;
430
431 pkt->log->action = "parsing quic long header";
432
294 if (ngx_quic_pkt_in(pkt->flags)) { 433 if (ngx_quic_pkt_in(pkt->flags)) {
295 434
296 if (pkt->len < NGX_QUIC_MIN_INITIAL_SIZE) { 435 if (pkt->len < NGX_QUIC_MIN_INITIAL_SIZE) {
297 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, 436 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
298 "quic UDP datagram is too small for initial packet"); 437 "quic UDP datagram is too small for initial packet");
299 return NGX_DECLINED; 438 return NGX_DECLINED;
300 } 439 }
301 440
441 p = ngx_quic_parse_int(p, end, &varint);
442 if (p == NULL) {
443 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
444 "quic failed to parse token length");
445 return NGX_ERROR;
446 }
447
448 pkt->token.len = varint;
449
450 p = ngx_quic_read_bytes(p, end, pkt->token.len, &pkt->token.data);
451 if (p == NULL) {
452 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
453 "quic packet too small to read token data");
454 return NGX_ERROR;
455 }
456
302 pkt->level = ssl_encryption_initial; 457 pkt->level = ssl_encryption_initial;
303
304 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) {
305 return NGX_DECLINED;
306 }
307
308 return NGX_OK;
309 }
310
311 if (ngx_quic_pkt_hs(pkt->flags)) {
312 pkt->level = ssl_encryption_handshake;
313 458
314 } else if (ngx_quic_pkt_zrtt(pkt->flags)) { 459 } else if (ngx_quic_pkt_zrtt(pkt->flags)) {
315 pkt->level = ssl_encryption_early_data; 460 pkt->level = ssl_encryption_early_data;
316 461
462 } else if (ngx_quic_pkt_hs(pkt->flags)) {
463 pkt->level = ssl_encryption_handshake;
464
317 } else { 465 } else {
318 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, 466 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
319 "quic unknown long packet type"); 467 "quic bad packet type");
320 return NGX_DECLINED; 468 return NGX_DECLINED;
321 }
322
323 if (ngx_quic_parse_handshake_header(pkt) != NGX_OK) {
324 return NGX_DECLINED;
325 }
326
327 return NGX_OK;
328 }
329
330
331 static ngx_int_t
332 ngx_quic_parse_short_header(ngx_quic_header_t *pkt, size_t dcid_len)
333 {
334 u_char *p, *end;
335
336 p = pkt->raw->pos;
337 end = pkt->data + pkt->len;
338
339 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
340 "quic packet rx short flags:%xd", pkt->flags);
341
342 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
343 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
344 return NGX_ERROR;
345 }
346
347 pkt->dcid.len = dcid_len;
348
349 p = ngx_quic_read_bytes(p, end, dcid_len, &pkt->dcid.data);
350 if (p == NULL) {
351 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
352 "quic packet is too small to read dcid");
353 return NGX_ERROR;
354 }
355
356 pkt->raw->pos = p;
357
358 return NGX_OK;
359 }
360
361
362 static ngx_int_t
363 ngx_quic_parse_long_header(ngx_quic_header_t *pkt)
364 {
365 u_char *p, *end;
366 uint8_t idlen;
367
368 p = pkt->raw->pos;
369 end = pkt->data + pkt->len;
370
371 p = ngx_quic_read_uint32(p, end, &pkt->version);
372 if (p == NULL) {
373 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
374 "quic packet is too small to read version");
375 return NGX_ERROR;
376 }
377
378 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
379 "quic packet rx long flags:%xd version:%xD",
380 pkt->flags, pkt->version);
381
382 if (!(pkt->flags & NGX_QUIC_PKT_FIXED_BIT)) {
383 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic fixed bit is not set");
384 return NGX_ERROR;
385 }
386
387 p = ngx_quic_read_uint8(p, end, &idlen);
388 if (p == NULL) {
389 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
390 "quic packet is too small to read dcid len");
391 return NGX_ERROR;
392 }
393
394 if (idlen > NGX_QUIC_CID_LEN_MAX) {
395 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
396 "quic packet dcid is too long");
397 return NGX_ERROR;
398 }
399
400 pkt->dcid.len = idlen;
401
402 p = ngx_quic_read_bytes(p, end, idlen, &pkt->dcid.data);
403 if (p == NULL) {
404 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
405 "quic packet is too small to read dcid");
406 return NGX_ERROR;
407 }
408
409 p = ngx_quic_read_uint8(p, end, &idlen);
410 if (p == NULL) {
411 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
412 "quic packet is too small to read scid len");
413 return NGX_ERROR;
414 }
415
416 if (idlen > NGX_QUIC_CID_LEN_MAX) {
417 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
418 "quic packet scid is too long");
419 return NGX_ERROR;
420 }
421
422 pkt->scid.len = idlen;
423
424 p = ngx_quic_read_bytes(p, end, idlen, &pkt->scid.data);
425 if (p == NULL) {
426 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
427 "quic packet is too small to read scid");
428 return NGX_ERROR;
429 }
430
431 pkt->raw->pos = p;
432
433 return NGX_OK;
434 }
435
436
437 static ngx_int_t
438 ngx_quic_supported_version(uint32_t version)
439 {
440 ngx_uint_t i;
441
442 for (i = 0; i < NGX_QUIC_NVERSIONS; i++) {
443 if (ngx_quic_versions[i] == version) {
444 return 1;
445 }
446 }
447
448 return 0;
449 }
450
451
452 static ngx_int_t
453 ngx_quic_parse_initial_header(ngx_quic_header_t *pkt)
454 {
455 u_char *p, *end;
456 uint64_t varint;
457
458 p = pkt->raw->pos;
459
460 end = pkt->raw->last;
461
462 pkt->log->action = "parsing quic initial header";
463
464 p = ngx_quic_parse_int(p, end, &varint);
465 if (p == NULL) {
466 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
467 "quic failed to parse token length");
468 return NGX_ERROR;
469 }
470
471 pkt->token.len = varint;
472
473 p = ngx_quic_read_bytes(p, end, pkt->token.len, &pkt->token.data);
474 if (p == NULL) {
475 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
476 "quic packet too small to read token data");
477 return NGX_ERROR;
478 } 469 }
479 470
480 p = ngx_quic_parse_int(p, end, &varint); 471 p = ngx_quic_parse_int(p, end, &varint);
481 if (p == NULL) { 472 if (p == NULL) {
482 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic bad packet length"); 473 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic bad packet length");
483 return NGX_ERROR; 474 return NGX_ERROR;
484 } 475 }
485 476
486 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0, 477 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
487 "quic packet rx initial len:%uL", varint); 478 "quic packet rx %s len:%uL",
479 ngx_quic_level_name(pkt->level), varint);
488 480
489 if (varint > (uint64_t) ((pkt->data + pkt->len) - p)) { 481 if (varint > (uint64_t) ((pkt->data + pkt->len) - p)) {
490 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, 482 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic truncated %s packet",
491 "quic truncated initial packet"); 483 ngx_quic_level_name(pkt->level));
492 return NGX_ERROR; 484 return NGX_ERROR;
493 } 485 }
494 486
495 pkt->raw->pos = p; 487 pkt->raw->pos = p;
496 pkt->len = p + varint - pkt->data; 488 pkt->len = p + varint - pkt->data;
497
498 #ifdef NGX_QUIC_DEBUG_PACKETS
499 ngx_quic_hexdump(pkt->log, "quic DCID", pkt->dcid.data, pkt->dcid.len);
500 ngx_quic_hexdump(pkt->log, "quic SCID", pkt->scid.data, pkt->scid.len);
501 ngx_quic_hexdump(pkt->log, "quic token", pkt->token.data, pkt->token.len);
502 #endif
503
504 return NGX_OK;
505 }
506
507
508 static ngx_int_t
509 ngx_quic_parse_handshake_header(ngx_quic_header_t *pkt)
510 {
511 u_char *p, *end;
512 uint64_t plen;
513
514 p = pkt->raw->pos;
515 end = pkt->raw->last;
516
517 pkt->log->action = "parsing quic handshake header";
518
519 p = ngx_quic_parse_int(p, end, &plen);
520 if (p == NULL) {
521 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, "quic bad packet length");
522 return NGX_ERROR;
523 }
524
525 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, pkt->log, 0,
526 "quic packet rx handshake len:%uL", plen);
527
528 if (plen > (uint64_t)((pkt->data + pkt->len) - p)) {
529 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
530 "quic truncated handshake packet");
531 return NGX_ERROR;
532 }
533
534 pkt->raw->pos = p;
535 pkt->len = p + plen - pkt->data;
536 489
537 return NGX_OK; 490 return NGX_OK;
538 } 491 }
539 492
540 493