comparison src/event/ngx_event_quic_transport.c @ 7847:262396242352 quic

Reworked macros for parsing/assembling packet types. Previously, macros checking a packet type with the long header also checked whether this is a long header. Now it requires a separate preceding check.
author Vladimir Homutov <vl@nginx.com>
date Thu, 30 Apr 2020 12:38:38 +0300
parents 336d527ca031
children 7ea34e13937f
comparison
equal deleted inserted replaced
7846:bddf704d62c1 7847:262396242352
64 static u_char *ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len, 64 static u_char *ngx_quic_read_bytes(u_char *pos, u_char *end, size_t len,
65 u_char **out); 65 u_char **out);
66 static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, 66 static u_char *ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len,
67 u_char *dst); 67 u_char *dst);
68 68
69 static ngx_int_t ngx_quic_frame_allowed(ngx_quic_header_t *pkt,
70 ngx_uint_t frame_type);
69 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack); 71 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack);
70 static size_t ngx_quic_create_crypto(u_char *p, 72 static size_t ngx_quic_create_crypto(u_char *p,
71 ngx_quic_crypto_frame_t *crypto); 73 ngx_quic_crypto_frame_t *crypto);
72 static size_t ngx_quic_create_hs_done(u_char *p); 74 static size_t ngx_quic_create_hs_done(u_char *p);
73 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf); 75 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf);
526 ssize_t 528 ssize_t
527 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end, 529 ngx_quic_parse_frame(ngx_quic_header_t *pkt, u_char *start, u_char *end,
528 ngx_quic_frame_t *f) 530 ngx_quic_frame_t *f)
529 { 531 {
530 u_char *p; 532 u_char *p;
531 uint8_t flags;
532 uint64_t varint; 533 uint64_t varint;
533 ngx_uint_t i; 534 ngx_uint_t i;
534 535
535 flags = pkt->flags;
536 p = start; 536 p = start;
537 537
538 p = ngx_quic_parse_int(p, end, &varint); 538 p = ngx_quic_parse_int(p, end, &varint);
539 if (p == NULL) { 539 if (p == NULL) {
540 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, 540 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
542 return NGX_ERROR; 542 return NGX_ERROR;
543 } 543 }
544 544
545 f->type = varint; 545 f->type = varint;
546 546
547 if (ngx_quic_frame_allowed(pkt, f->type) != NGX_OK) {
548 return NGX_DECLINED;
549 }
550
547 switch (f->type) { 551 switch (f->type) {
548 552
549 case NGX_QUIC_FT_CRYPTO: 553 case NGX_QUIC_FT_CRYPTO:
550
551 if (ngx_quic_pkt_zrtt(flags)) {
552 goto not_allowed;
553 }
554 554
555 p = ngx_quic_parse_int(p, end, &f->u.crypto.offset); 555 p = ngx_quic_parse_int(p, end, &f->u.crypto.offset);
556 if (p == NULL) { 556 if (p == NULL) {
557 goto error; 557 goto error;
558 } 558 }
578 #endif 578 #endif
579 break; 579 break;
580 580
581 case NGX_QUIC_FT_PADDING: 581 case NGX_QUIC_FT_PADDING:
582 582
583 /* allowed in any packet type */
584
585 while (p < end && *p == NGX_QUIC_FT_PADDING) { 583 while (p < end && *p == NGX_QUIC_FT_PADDING) {
586 p++; 584 p++;
587 } 585 }
588 586
589 break; 587 break;
590 588
591 case NGX_QUIC_FT_ACK: 589 case NGX_QUIC_FT_ACK:
592 case NGX_QUIC_FT_ACK_ECN: 590 case NGX_QUIC_FT_ACK_ECN:
593
594 if (ngx_quic_pkt_zrtt(flags)) {
595 goto not_allowed;
596 }
597 591
598 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.largest)) 592 if (!((p = ngx_quic_parse_int(p, end, &f->u.ack.largest))
599 && (p = ngx_quic_parse_int(p, end, &f->u.ack.delay)) 593 && (p = ngx_quic_parse_int(p, end, &f->u.ack.delay))
600 && (p = ngx_quic_parse_int(p, end, &f->u.ack.range_count)) 594 && (p = ngx_quic_parse_int(p, end, &f->u.ack.range_count))
601 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range)))) 595 && (p = ngx_quic_parse_int(p, end, &f->u.ack.first_range))))
642 } 636 }
643 637
644 break; 638 break;
645 639
646 case NGX_QUIC_FT_PING: 640 case NGX_QUIC_FT_PING:
647
648 /* allowed in any packet type */
649
650 break; 641 break;
651 642
652 case NGX_QUIC_FT_NEW_CONNECTION_ID: 643 case NGX_QUIC_FT_NEW_CONNECTION_ID:
653
654 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
655 goto not_allowed;
656 }
657 644
658 p = ngx_quic_parse_int(p, end, &f->u.ncid.seqnum); 645 p = ngx_quic_parse_int(p, end, &f->u.ncid.seqnum);
659 if (p == NULL) { 646 if (p == NULL) {
660 goto error; 647 goto error;
661 } 648 }
684 "quic frame in: NCID seq:%ui retire:%ui len:%ui", 671 "quic frame in: NCID seq:%ui retire:%ui len:%ui",
685 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len); 672 f->u.ncid.seqnum, f->u.ncid.retire, f->u.ncid.len);
686 break; 673 break;
687 674
688 case NGX_QUIC_FT_CONNECTION_CLOSE2: 675 case NGX_QUIC_FT_CONNECTION_CLOSE2:
689
690 if (!ngx_quic_short_pkt(flags)) {
691 goto not_allowed;
692 }
693
694 /* fall through */ 676 /* fall through */
695 677
696 case NGX_QUIC_FT_CONNECTION_CLOSE: 678 case NGX_QUIC_FT_CONNECTION_CLOSE:
697
698 if (ngx_quic_pkt_zrtt(flags)) {
699 goto not_allowed;
700 }
701 679
702 p = ngx_quic_parse_int(p, end, &f->u.close.error_code); 680 p = ngx_quic_parse_int(p, end, &f->u.close.error_code);
703 if (p == NULL) { 681 if (p == NULL) {
704 goto error; 682 goto error;
705 } 683 }
749 case NGX_QUIC_FT_STREAM4: 727 case NGX_QUIC_FT_STREAM4:
750 case NGX_QUIC_FT_STREAM5: 728 case NGX_QUIC_FT_STREAM5:
751 case NGX_QUIC_FT_STREAM6: 729 case NGX_QUIC_FT_STREAM6:
752 case NGX_QUIC_FT_STREAM7: 730 case NGX_QUIC_FT_STREAM7:
753 731
754 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
755 goto not_allowed;
756 }
757
758 f->u.stream.type = f->type; 732 f->u.stream.type = f->type;
759 733
760 f->u.stream.off = ngx_quic_stream_bit_off(f->type); 734 f->u.stream.off = ngx_quic_stream_bit_off(f->type);
761 f->u.stream.len = ngx_quic_stream_bit_len(f->type); 735 f->u.stream.len = ngx_quic_stream_bit_len(f->type);
762 f->u.stream.fin = ngx_quic_stream_bit_fin(f->type); 736 f->u.stream.fin = ngx_quic_stream_bit_fin(f->type);
805 #endif 779 #endif
806 break; 780 break;
807 781
808 case NGX_QUIC_FT_MAX_DATA: 782 case NGX_QUIC_FT_MAX_DATA:
809 783
810 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
811 goto not_allowed;
812 }
813
814 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data); 784 p = ngx_quic_parse_int(p, end, &f->u.max_data.max_data);
815 if (p == NULL) { 785 if (p == NULL) {
816 goto error; 786 goto error;
817 } 787 }
818 788
820 "quic frame in: MAX_DATA max_data:%ui", 790 "quic frame in: MAX_DATA max_data:%ui",
821 f->u.max_data.max_data); 791 f->u.max_data.max_data);
822 break; 792 break;
823 793
824 case NGX_QUIC_FT_RESET_STREAM: 794 case NGX_QUIC_FT_RESET_STREAM:
825
826 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
827 goto not_allowed;
828 }
829 795
830 if (!((p = ngx_quic_parse_int(p, end, &f->u.reset_stream.id)) 796 if (!((p = ngx_quic_parse_int(p, end, &f->u.reset_stream.id))
831 && (p = ngx_quic_parse_int(p, end, &f->u.reset_stream.error_code)) 797 && (p = ngx_quic_parse_int(p, end, &f->u.reset_stream.error_code))
832 && (p = ngx_quic_parse_int(p, end, 798 && (p = ngx_quic_parse_int(p, end,
833 &f->u.reset_stream.final_size)))) 799 &f->u.reset_stream.final_size))))
842 f->u.reset_stream.final_size); 808 f->u.reset_stream.final_size);
843 break; 809 break;
844 810
845 case NGX_QUIC_FT_STOP_SENDING: 811 case NGX_QUIC_FT_STOP_SENDING:
846 812
847 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
848 goto not_allowed;
849 }
850
851 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.id); 813 p = ngx_quic_parse_int(p, end, &f->u.stop_sending.id);
852 if (p == NULL) { 814 if (p == NULL) {
853 goto error; 815 goto error;
854 } 816 }
855 817
864 826
865 break; 827 break;
866 828
867 case NGX_QUIC_FT_STREAMS_BLOCKED: 829 case NGX_QUIC_FT_STREAMS_BLOCKED:
868 case NGX_QUIC_FT_STREAMS_BLOCKED2: 830 case NGX_QUIC_FT_STREAMS_BLOCKED2:
869
870 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
871 goto not_allowed;
872 }
873 831
874 p = ngx_quic_parse_int(p, end, &f->u.streams_blocked.limit); 832 p = ngx_quic_parse_int(p, end, &f->u.streams_blocked.limit);
875 if (p == NULL) { 833 if (p == NULL) {
876 goto error; 834 goto error;
877 } 835 }
884 f->u.streams_blocked.limit, 842 f->u.streams_blocked.limit,
885 f->u.streams_blocked.bidi); 843 f->u.streams_blocked.bidi);
886 844
887 break; 845 break;
888 846
889 case NGX_QUIC_FT_HANDSHAKE_DONE:
890 /* only sent by server, not by client */
891 goto not_allowed;
892
893 case NGX_QUIC_FT_NEW_TOKEN: 847 case NGX_QUIC_FT_NEW_TOKEN:
894
895 if (!ngx_quic_short_pkt(flags)) {
896 goto not_allowed;
897 }
898
899 /* TODO: implement */ 848 /* TODO: implement */
900 849
901 ngx_log_error(NGX_LOG_ALERT, pkt->log, 0, 850 ngx_log_error(NGX_LOG_ALERT, pkt->log, 0,
902 "quic unimplemented frame type 0x%xi in packet", f->type); 851 "quic unimplemented frame type 0x%xi in packet", f->type);
903 852
904 break; 853 break;
905 854
906 case NGX_QUIC_FT_MAX_STREAMS: 855 case NGX_QUIC_FT_MAX_STREAMS:
907 case NGX_QUIC_FT_MAX_STREAMS2: 856 case NGX_QUIC_FT_MAX_STREAMS2:
908
909 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
910 goto not_allowed;
911 }
912 857
913 p = ngx_quic_parse_int(p, end, &f->u.max_streams.limit); 858 p = ngx_quic_parse_int(p, end, &f->u.max_streams.limit);
914 if (p == NULL) { 859 if (p == NULL) {
915 goto error; 860 goto error;
916 } 861 }
923 f->u.max_streams.bidi); 868 f->u.max_streams.bidi);
924 break; 869 break;
925 870
926 case NGX_QUIC_FT_MAX_STREAM_DATA: 871 case NGX_QUIC_FT_MAX_STREAM_DATA:
927 872
928 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
929 goto not_allowed;
930 }
931
932 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.id); 873 p = ngx_quic_parse_int(p, end, &f->u.max_stream_data.id);
933 if (p == NULL) { 874 if (p == NULL) {
934 goto error; 875 goto error;
935 } 876 }
936 877
945 f->u.max_stream_data.limit); 886 f->u.max_stream_data.limit);
946 break; 887 break;
947 888
948 case NGX_QUIC_FT_DATA_BLOCKED: 889 case NGX_QUIC_FT_DATA_BLOCKED:
949 890
950 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
951 goto not_allowed;
952 }
953
954 p = ngx_quic_parse_int(p, end, &f->u.data_blocked.limit); 891 p = ngx_quic_parse_int(p, end, &f->u.data_blocked.limit);
955 if (p == NULL) { 892 if (p == NULL) {
956 goto error; 893 goto error;
957 } 894 }
958 895
960 "quic frame in: DATA_BLOCKED limit:%ui", 897 "quic frame in: DATA_BLOCKED limit:%ui",
961 f->u.data_blocked.limit); 898 f->u.data_blocked.limit);
962 break; 899 break;
963 900
964 case NGX_QUIC_FT_STREAM_DATA_BLOCKED: 901 case NGX_QUIC_FT_STREAM_DATA_BLOCKED:
965
966 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
967 goto not_allowed;
968 }
969 902
970 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.id); 903 p = ngx_quic_parse_int(p, end, &f->u.stream_data_blocked.id);
971 if (p == NULL) { 904 if (p == NULL) {
972 goto error; 905 goto error;
973 } 906 }
984 f->u.stream_data_blocked.limit); 917 f->u.stream_data_blocked.limit);
985 break; 918 break;
986 919
987 case NGX_QUIC_FT_RETIRE_CONNECTION_ID: 920 case NGX_QUIC_FT_RETIRE_CONNECTION_ID:
988 921
989 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
990 goto not_allowed;
991 }
992
993 p = ngx_quic_parse_int(p, end, &f->u.retire_cid.sequence_number); 922 p = ngx_quic_parse_int(p, end, &f->u.retire_cid.sequence_number);
994 if (p == NULL) { 923 if (p == NULL) {
995 goto error; 924 goto error;
996 } 925 }
997 926
1001 f->u.retire_cid.sequence_number); 930 f->u.retire_cid.sequence_number);
1002 break; 931 break;
1003 932
1004 case NGX_QUIC_FT_PATH_CHALLENGE: 933 case NGX_QUIC_FT_PATH_CHALLENGE:
1005 934
1006 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
1007 goto not_allowed;
1008 }
1009
1010 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_challenge.data); 935 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_challenge.data);
1011 if (p == NULL) { 936 if (p == NULL) {
1012 goto error; 937 goto error;
1013 } 938 }
1014 939
1021 #endif 946 #endif
1022 break; 947 break;
1023 948
1024 case NGX_QUIC_FT_PATH_RESPONSE: 949 case NGX_QUIC_FT_PATH_RESPONSE:
1025 950
1026 if (!(ngx_quic_short_pkt(flags) || ngx_quic_pkt_zrtt(flags))) {
1027 goto not_allowed;
1028 }
1029
1030 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_response.data); 951 p = ngx_quic_copy_bytes(p, end, 8, f->u.path_response.data);
1031 if (p == NULL) { 952 if (p == NULL) {
1032 goto error; 953 goto error;
1033 } 954 }
1034 955
1047 return NGX_ERROR; 968 return NGX_ERROR;
1048 } 969 }
1049 970
1050 return p - start; 971 return p - start;
1051 972
1052 not_allowed: 973 error:
974
975 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
976 "quic failed to parse frame type 0x%xi", f->type);
977
978 return NGX_ERROR;
979 }
980
981
982 static ngx_int_t
983 ngx_quic_frame_allowed(ngx_quic_header_t *pkt, ngx_uint_t frame_type)
984 {
985 uint8_t ptype;
986
987 /* frame permissions per packet: 4 bits: IH01: 12.4, Table 3 */
988 static uint8_t ngx_quic_frame_masks[] = {
989 /* PADDING */ 0xF,
990 /* PING */ 0xF,
991 /* ACK */ 0xD,
992 /* ACK_ECN */ 0xD,
993 /* RESET_STREAM */ 0x3,
994 /* STOP_SENDING */ 0x3,
995 /* CRYPTO */ 0xD,
996 /* NEW_TOKEN */ 0x1,
997 /* STREAM0 */ 0x3,
998 /* STREAM1 */ 0x3,
999 /* STREAM2 */ 0x3,
1000 /* STREAM3 */ 0x3,
1001 /* STREAM4 */ 0x3,
1002 /* STREAM5 */ 0x3,
1003 /* STREAM6 */ 0x3,
1004 /* STREAM7 */ 0x3,
1005 /* MAX_DATA */ 0x3,
1006 /* MAX_STREAM_DATA */ 0x3,
1007 /* MAX_STREAMS */ 0x3,
1008 /* MAX_STREAMS2 */ 0x3,
1009 /* DATA_BLOCKED */ 0x3,
1010 /* STREAM_DATA_BLOCKED */ 0x3,
1011 /* STREAMS_BLOCKED */ 0x3,
1012 /* STREAMS_BLOCKED2 */ 0x3,
1013 /* NEW_CONNECTION_ID */ 0x3,
1014 /* RETIRE_CONNECTION_ID */ 0x3,
1015 /* PATH_CHALLENGE */ 0x3,
1016 /* PATH_RESPONSE */ 0x3,
1017 /* CONNECTION_CLOSE */ 0xD,
1018 /* CONNECTION_CLOSE2 */ 0x1,
1019 /* HANDSHAKE_DONE */ 0x0, /* only sent by server */
1020 };
1021
1022 if (ngx_quic_long_pkt(pkt->flags)) {
1023
1024 if (ngx_quic_pkt_in(pkt->flags)) {
1025 ptype = 8; /* initial */
1026
1027 } else if (ngx_quic_pkt_hs(pkt->flags)) {
1028 ptype = 4; /* handshake */
1029
1030 } else {
1031 ptype = 2; /* zero-rtt */
1032 }
1033
1034 } else {
1035 ptype = 1; /* application data */
1036 }
1037
1038 if (ptype & ngx_quic_frame_masks[frame_type]) {
1039 return NGX_OK;
1040 }
1053 1041
1054 ngx_log_error(NGX_LOG_INFO, pkt->log, 0, 1042 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
1055 "quic frame type 0x%xi is not " 1043 "quic frame type 0x%xi is not "
1056 "allowed in packet with flags 0x%xi", 1044 "allowed in packet with flags 0x%xi",
1057 f->type, pkt->flags); 1045 frame_type, pkt->flags);
1058 1046
1059 return NGX_DECLINED; 1047 return NGX_DECLINED;
1060
1061 error:
1062
1063 ngx_log_error(NGX_LOG_INFO, pkt->log, 0,
1064 "quic failed to parse frame type 0x%xi", f->type);
1065
1066 return NGX_ERROR;
1067 } 1048 }
1068 1049
1069 1050
1070 ssize_t 1051 ssize_t
1071 ngx_quic_parse_ack_range(ngx_quic_header_t *pkt, u_char *start, u_char *end, 1052 ngx_quic_parse_ack_range(ngx_quic_header_t *pkt, u_char *start, u_char *end,