comparison src/event/ngx_event_quic.c @ 8060:fc89d02bdca2 quic

QUIC: added version negotiation support. If a client attemtps to start a new connection with unsupported version, a version negotiation packet is sent that contains a list of supported versions (currently this is a single version, selected at compile time).
author Vladimir Homutov <vl@nginx.com>
date Thu, 20 Aug 2020 17:11:04 +0300
parents de7d6d943f68
children 0609ea17ca23
comparison
equal deleted inserted replaced
8059:a748095bf94e 8060:fc89d02bdca2
167 enum ssl_encryption_level_t level, uint8_t alert); 167 enum ssl_encryption_level_t level, uint8_t alert);
168 168
169 169
170 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, 170 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl,
171 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt); 171 ngx_quic_conf_t *conf, ngx_quic_header_t *pkt);
172 static ngx_int_t ngx_quic_negotiate_version(ngx_connection_t *c,
173 ngx_quic_header_t *inpkt);
172 static ngx_int_t ngx_quic_new_dcid(ngx_connection_t *c, ngx_str_t *odcid); 174 static ngx_int_t ngx_quic_new_dcid(ngx_connection_t *c, ngx_str_t *odcid);
173 static ngx_int_t ngx_quic_retry(ngx_connection_t *c); 175 static ngx_int_t ngx_quic_retry(ngx_connection_t *c);
174 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, ngx_str_t *token); 176 static ngx_int_t ngx_quic_new_token(ngx_connection_t *c, ngx_str_t *token);
175 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c, 177 static ngx_int_t ngx_quic_validate_token(ngx_connection_t *c,
176 ngx_quic_header_t *pkt); 178 ngx_quic_header_t *pkt);
657 rc = ngx_quic_parse_long_header(pkt); 659 rc = ngx_quic_parse_long_header(pkt);
658 if (rc != NGX_OK) { 660 if (rc != NGX_OK) {
659 return rc; 661 return rc;
660 } 662 }
661 663
664 if (pkt->version != NGX_QUIC_VERSION) {
665 return ngx_quic_negotiate_version(c, pkt);
666 }
667
662 if (!ngx_quic_pkt_in(pkt->flags)) { 668 if (!ngx_quic_pkt_in(pkt->flags)) {
663 ngx_log_error(NGX_LOG_INFO, c->log, 0, 669 ngx_log_error(NGX_LOG_INFO, c->log, 0,
664 "quic invalid initial packet: 0x%xd", pkt->flags); 670 "quic invalid initial packet: 0x%xd", pkt->flags);
665 return NGX_ERROR; 671 return NGX_ERROR;
666 } 672 }
818 pkt->raw->pos += pkt->len; 824 pkt->raw->pos += pkt->len;
819 825
820 (void) ngx_quic_skip_zero_padding(pkt->raw); 826 (void) ngx_quic_skip_zero_padding(pkt->raw);
821 827
822 return ngx_quic_input(c, pkt->raw); 828 return ngx_quic_input(c, pkt->raw);
829 }
830
831
832 static ngx_int_t
833 ngx_quic_negotiate_version(ngx_connection_t *c, ngx_quic_header_t *inpkt)
834 {
835 size_t len;
836 ngx_quic_header_t pkt;
837
838 /* buffer size is calculated assuming a single supported version */
839 static u_char buf[NGX_QUIC_MAX_LONG_HEADER + sizeof(uint32_t)];
840
841 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
842 "sending version negotiation packet");
843
844 pkt.log = c->log;
845 pkt.flags = NGX_QUIC_PKT_LONG | NGX_QUIC_PKT_FIXED_BIT;
846 pkt.dcid = inpkt->scid;
847 pkt.scid = inpkt->dcid;
848
849 len = ngx_quic_create_version_negotiation(&pkt, buf);
850
851 #ifdef NGX_QUIC_DEBUG_PACKETS
852 ngx_quic_hexdump(c->log, "quic vnego packet to send", buf, len);
853 #endif
854
855 (void) c->send(c, buf, len);
856
857 return NGX_ERROR;
823 } 858 }
824 859
825 860
826 static ngx_int_t 861 static ngx_int_t
827 ngx_quic_new_dcid(ngx_connection_t *c, ngx_str_t *odcid) 862 ngx_quic_new_dcid(ngx_connection_t *c, ngx_str_t *odcid)
1626 rc = ngx_quic_parse_long_header(pkt); 1661 rc = ngx_quic_parse_long_header(pkt);
1627 if (rc != NGX_OK) { 1662 if (rc != NGX_OK) {
1628 return rc; 1663 return rc;
1629 } 1664 }
1630 1665
1666 if (pkt->version != NGX_QUIC_VERSION) {
1667 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1668 "quic unsupported version: 0x%xD", pkt->version);
1669 return NGX_ERROR;
1670 }
1671
1631 if (ngx_quic_pkt_zrtt(pkt->flags)) { 1672 if (ngx_quic_pkt_zrtt(pkt->flags)) {
1632 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1673 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1633 "quic discard inflight 0-RTT packet"); 1674 "quic discard inflight 0-RTT packet");
1634 return NGX_OK; 1675 return NGX_OK;
1635 } 1676 }
1711 ssl_conn = c->ssl->connection; 1752 ssl_conn = c->ssl->connection;
1712 1753
1713 rc = ngx_quic_parse_long_header(pkt); 1754 rc = ngx_quic_parse_long_header(pkt);
1714 if (rc != NGX_OK) { 1755 if (rc != NGX_OK) {
1715 return rc; 1756 return rc;
1757 }
1758
1759 if (pkt->version != NGX_QUIC_VERSION) {
1760 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1761 "quic unsupported version: 0x%xD", pkt->version);
1762 return NGX_ERROR;
1716 } 1763 }
1717 1764
1718 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) { 1765 if (ngx_quic_parse_initial_header(pkt) != NGX_OK) {
1719 return NGX_ERROR; 1766 return NGX_ERROR;
1720 } 1767 }
1763 rc = ngx_quic_parse_long_header(pkt); 1810 rc = ngx_quic_parse_long_header(pkt);
1764 if (rc != NGX_OK) { 1811 if (rc != NGX_OK) {
1765 return rc; 1812 return rc;
1766 } 1813 }
1767 1814
1815 if (pkt->version != NGX_QUIC_VERSION) {
1816 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1817 "quic unsupported version: 0x%xD", pkt->version);
1818 return NGX_ERROR;
1819 }
1820
1768 if (ngx_quic_check_peer(qc, pkt) != NGX_OK) { 1821 if (ngx_quic_check_peer(qc, pkt) != NGX_OK) {
1769 return NGX_ERROR; 1822 return NGX_ERROR;
1770 } 1823 }
1771 1824
1772 if (ngx_quic_parse_handshake_header(pkt) != NGX_OK) { 1825 if (ngx_quic_parse_handshake_header(pkt) != NGX_OK) {
1821 1874
1822 /* extract cleartext data into pkt */ 1875 /* extract cleartext data into pkt */
1823 rc = ngx_quic_parse_long_header(pkt); 1876 rc = ngx_quic_parse_long_header(pkt);
1824 if (rc != NGX_OK) { 1877 if (rc != NGX_OK) {
1825 return rc; 1878 return rc;
1879 }
1880
1881 if (pkt->version != NGX_QUIC_VERSION) {
1882 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1883 "quic unsupported version: 0x%xD", pkt->version);
1884 return NGX_ERROR;
1826 } 1885 }
1827 1886
1828 if (ngx_quic_check_peer(qc, pkt) != NGX_OK) { 1887 if (ngx_quic_check_peer(qc, pkt) != NGX_OK) {
1829 return NGX_ERROR; 1888 return NGX_ERROR;
1830 } 1889 }