Mercurial > hg > nginx-quic
comparison src/event/ngx_event_quic.c @ 7672:8d6ac639feac quic
Added support of multiple QUIC packets in single datagram.
- now NEW_CONNECTION_ID frames can be received and parsed
The packet structure is created in ngx_quic_input() and passed
to all handlers (initial, handshake and application data).
The UDP datagram buffer is saved as pkt->raw;
The QUIC packet is stored as pkt->data and pkt->len (instead of pkt->buf)
(pkt->len is adjusted after parsing headers to actual length)
The pkt->pos is removed, pkt->raw->pos is used instead.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Thu, 12 Mar 2020 14:43:24 +0300 |
parents | a5423632d67b |
children | cc8d211cb45c |
comparison
equal
deleted
inserted
replaced
7671:a5423632d67b | 7672:8d6ac639feac |
---|---|
164 size_t len; | 164 size_t len; |
165 u_char *data; | 165 u_char *data; |
166 } ngx_quic_crypto_frame_t; | 166 } ngx_quic_crypto_frame_t; |
167 | 167 |
168 | 168 |
169 typedef struct { | |
170 uint64_t seqnum; | |
171 uint64_t retire; | |
172 uint64_t len; | |
173 u_char cid[20]; | |
174 u_char srt[16]; | |
175 } ngx_quic_ncid_t; | |
176 | |
177 | |
169 struct ngx_quic_frame_s { | 178 struct ngx_quic_frame_s { |
170 ngx_uint_t type; | 179 ngx_uint_t type; |
171 ngx_quic_level_t level; | 180 ngx_quic_level_t level; |
172 ngx_quic_frame_t *next; | 181 ngx_quic_frame_t *next; |
173 union { | 182 union { |
174 ngx_quic_crypto_frame_t crypto; | 183 ngx_quic_crypto_frame_t crypto; |
175 ngx_quic_ack_frame_t ack; | 184 ngx_quic_ack_frame_t ack; |
185 ngx_quic_ncid_t ncid; | |
176 // more frames | 186 // more frames |
177 } u; | 187 } u; |
178 | 188 |
179 u_char info[128]; // for debug purposes | 189 u_char info[128]; // for debug purposes |
180 }; | 190 }; |
213 uint32_t version; | 223 uint32_t version; |
214 ngx_str_t token; | 224 ngx_str_t token; |
215 ngx_quic_level_t level; | 225 ngx_quic_level_t level; |
216 | 226 |
217 /* filled in by parser */ | 227 /* filled in by parser */ |
218 ngx_str_t buf; /* quic packet from wire */ | 228 ngx_buf_t *raw; /* udp datagram from wire */ |
219 u_char *pos; /* current parser position */ | 229 |
230 u_char *data; /* quic packet */ | |
231 size_t len; | |
220 | 232 |
221 /* cleartext fields */ | 233 /* cleartext fields */ |
222 ngx_str_t dcid; | 234 ngx_str_t dcid; |
223 ngx_str_t scid; | 235 ngx_str_t scid; |
224 | 236 |
228 | 240 |
229 } ngx_quic_header_t; | 241 } ngx_quic_header_t; |
230 | 242 |
231 | 243 |
232 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, | 244 static ngx_int_t ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, |
233 ngx_buf_t *b); | 245 ngx_quic_header_t *pkt); |
234 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *b); | 246 |
235 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, ngx_buf_t *b); | 247 static ngx_int_t ngx_quic_handshake_input(ngx_connection_t *c, |
248 ngx_quic_header_t *pkt); | |
249 static ngx_int_t ngx_quic_app_input(ngx_connection_t *c, | |
250 ngx_quic_header_t *pkt); | |
251 | |
236 | 252 |
237 #if BORINGSSL_API_VERSION >= 10 | 253 #if BORINGSSL_API_VERSION >= 10 |
238 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, | 254 static int ngx_quic_set_read_secret(ngx_ssl_conn_t *ssl_conn, |
239 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, | 255 enum ssl_encryption_level_t level, const SSL_CIPHER *cipher, |
240 const uint8_t *secret, size_t secret_len); | 256 const uint8_t *secret, size_t secret_len); |
317 | 333 |
318 | 334 |
319 ngx_int_t | 335 ngx_int_t |
320 ngx_quic_input(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b) | 336 ngx_quic_input(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b) |
321 { | 337 { |
338 u_char *p; | |
339 ngx_quic_header_t pkt; | |
340 | |
341 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); | |
342 | |
343 pkt.raw = b; | |
344 pkt.data = b->start; | |
345 pkt.len = b->last - b->start; | |
346 | |
322 if (c->quic == NULL) { | 347 if (c->quic == NULL) { |
323 return ngx_quic_new_connection(c, ssl, b); | 348 return ngx_quic_new_connection(c, ssl, &pkt); |
324 } | 349 } |
325 | 350 |
326 if (b->start[0] & NGX_QUIC_PKT_LONG) { | 351 p = b->start; |
327 // TODO: check current state | 352 |
328 return ngx_quic_handshake_input(c, b); | 353 do { |
329 } | 354 ngx_memzero(&pkt, sizeof(ngx_quic_header_t)); |
330 | 355 pkt.raw = b; |
331 return ngx_quic_app_input(c, b); | 356 pkt.data = p; |
357 pkt.len = b->last - p; | |
358 | |
359 if (p[0] & NGX_QUIC_PKT_LONG) { | |
360 // TODO: check current state | |
361 if (ngx_quic_handshake_input(c, &pkt) != NGX_OK) { | |
362 return NGX_ERROR; | |
363 } | |
364 } else { | |
365 | |
366 if (ngx_quic_app_input(c, &pkt) != NGX_OK) { | |
367 return NGX_ERROR; | |
368 } | |
369 } | |
370 | |
371 /* b->pos is at header end, adjust by actual packet length */ | |
372 p = b->pos + pkt.len; | |
373 b->pos = p; /* reset b->pos to the next packet start */ | |
374 | |
375 } while (p < b->last); | |
376 | |
377 return NGX_OK; | |
332 } | 378 } |
333 | 379 |
334 static ngx_int_t | 380 static ngx_int_t |
335 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc, | 381 ngx_quic_send_packet(ngx_connection_t *c, ngx_quic_connection_t *qc, |
336 ngx_quic_level_t level, ngx_str_t *payload) | 382 ngx_quic_level_t level, ngx_str_t *payload) |
1016 | 1062 |
1017 return 1; | 1063 return 1; |
1018 } | 1064 } |
1019 | 1065 |
1020 | 1066 |
1021 /* TODO: stub for short packet header processing */ | |
1022 static ngx_int_t | 1067 static ngx_int_t |
1023 ngx_quic_process_short_header(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1068 ngx_quic_process_short_header(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1024 { | 1069 { |
1025 u_char *p; | 1070 u_char *p; |
1026 | 1071 |
1027 p = pkt->buf.data; | 1072 p = pkt->data; |
1028 | 1073 |
1029 ngx_quic_hexdump0(c->log, "input", pkt->buf.data, pkt->buf.len); | 1074 ngx_quic_hexdump0(c->log, "short input", pkt->data, pkt->len); |
1030 | 1075 |
1031 if ((p[0] & NGX_QUIC_PKT_LONG)) { | 1076 if ((p[0] & NGX_QUIC_PKT_LONG)) { |
1032 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a short packet"); | 1077 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a short packet"); |
1033 return NGX_ERROR; | 1078 return NGX_ERROR; |
1034 } | 1079 } |
1041 if (ngx_memcmp(p, c->quic->dcid.data, c->quic->dcid.len) != 0) { | 1086 if (ngx_memcmp(p, c->quic->dcid.data, c->quic->dcid.len) != 0) { |
1042 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); | 1087 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); |
1043 return NGX_ERROR; | 1088 return NGX_ERROR; |
1044 } | 1089 } |
1045 | 1090 |
1091 pkt->dcid.len = c->quic->dcid.len; | |
1046 pkt->dcid.data = p; | 1092 pkt->dcid.data = p; |
1047 p += c->quic->dcid.len; | 1093 p += pkt->dcid.len; |
1048 | 1094 |
1049 pkt->pos = p; | 1095 pkt->raw->pos = p; |
1050 | 1096 |
1051 return NGX_OK; | 1097 return NGX_OK; |
1052 } | 1098 } |
1053 | 1099 |
1054 | 1100 |
1055 static ngx_int_t | 1101 static ngx_int_t |
1056 ngx_quic_process_long_header(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1102 ngx_quic_process_long_header(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1057 { | 1103 { |
1058 u_char *p; | 1104 u_char *p; |
1059 | 1105 |
1060 p = pkt->buf.data; | 1106 p = pkt->data; |
1061 | 1107 |
1062 ngx_quic_hexdump0(c->log, "input", pkt->buf.data, pkt->buf.len); | 1108 ngx_quic_hexdump0(c->log, "long input", pkt->data, pkt->len); |
1063 | 1109 |
1064 if (!(p[0] & NGX_QUIC_PKT_LONG)) { | 1110 if (!(p[0] & NGX_QUIC_PKT_LONG)) { |
1065 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a long packet"); | 1111 ngx_log_error(NGX_LOG_INFO, c->log, 0, "not a long packet"); |
1066 return NGX_ERROR; | 1112 return NGX_ERROR; |
1067 } | 1113 } |
1085 | 1131 |
1086 pkt->scid.len = *p++; | 1132 pkt->scid.len = *p++; |
1087 pkt->scid.data = p; | 1133 pkt->scid.data = p; |
1088 p += pkt->scid.len; | 1134 p += pkt->scid.len; |
1089 | 1135 |
1090 pkt->pos = p; | 1136 pkt->raw->pos = p; |
1091 | 1137 |
1092 return NGX_OK; | 1138 return NGX_OK; |
1093 } | 1139 } |
1094 | 1140 |
1095 | 1141 |
1097 ngx_quic_process_initial_header(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1143 ngx_quic_process_initial_header(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1098 { | 1144 { |
1099 u_char *p; | 1145 u_char *p; |
1100 ngx_int_t plen; | 1146 ngx_int_t plen; |
1101 | 1147 |
1102 p = pkt->pos; | 1148 p = pkt->raw->pos; |
1103 | 1149 |
1104 pkt->token.len = ngx_quic_parse_int(&p); | 1150 pkt->token.len = ngx_quic_parse_int(&p); |
1105 pkt->token.data = p; | 1151 pkt->token.data = p; |
1106 | 1152 |
1107 p += pkt->token.len; | 1153 p += pkt->token.len; |
1109 plen = ngx_quic_parse_int(&p); | 1155 plen = ngx_quic_parse_int(&p); |
1110 | 1156 |
1111 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1157 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1112 "quic packet length: %d", plen); | 1158 "quic packet length: %d", plen); |
1113 | 1159 |
1114 if (plen > pkt->buf.data + pkt->buf.len - p) { | 1160 if (plen > pkt->data + pkt->len - p) { |
1115 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet"); | 1161 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated initial packet"); |
1116 return NGX_ERROR; | 1162 return NGX_ERROR; |
1117 } | 1163 } |
1118 | 1164 |
1119 pkt->pos = p; | 1165 pkt->raw->pos = p; |
1120 pkt->buf.len = plen; | 1166 pkt->len = plen; |
1121 | 1167 |
1122 ngx_quic_hexdump0(c->log, "DCID", pkt->dcid.data, pkt->dcid.len); | 1168 ngx_quic_hexdump0(c->log, "DCID", pkt->dcid.data, pkt->dcid.len); |
1123 ngx_quic_hexdump0(c->log, "SCID", pkt->scid.data, pkt->scid.len); | 1169 ngx_quic_hexdump0(c->log, "SCID", pkt->scid.data, pkt->scid.len); |
1124 ngx_quic_hexdump0(c->log, "token", pkt->token.data, pkt->token.len); | 1170 ngx_quic_hexdump0(c->log, "token", pkt->token.data, pkt->token.len); |
1125 | 1171 |
1133 ngx_quic_process_handshake_header(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1179 ngx_quic_process_handshake_header(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1134 { | 1180 { |
1135 u_char *p; | 1181 u_char *p; |
1136 ngx_int_t plen; | 1182 ngx_int_t plen; |
1137 | 1183 |
1138 p = pkt->pos; | 1184 p = pkt->raw->pos; |
1139 | 1185 |
1140 plen = ngx_quic_parse_int(&p); | 1186 plen = ngx_quic_parse_int(&p); |
1141 | 1187 |
1142 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1188 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1143 "quic packet length: %d", plen); | 1189 "quic packet length: %d", plen); |
1144 | 1190 |
1145 if (plen > pkt->buf.data + pkt->buf.len - p) { | 1191 if (plen > pkt->data + pkt->len - p) { |
1146 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet"); | 1192 ngx_log_error(NGX_LOG_INFO, c->log, 0, "truncated handshake packet"); |
1147 return NGX_ERROR; | 1193 return NGX_ERROR; |
1148 } | 1194 } |
1149 | 1195 |
1150 pkt->pos = p; | 1196 pkt->raw->pos = p; |
1151 pkt->buf.len = plen; | 1197 pkt->len = plen; |
1152 | 1198 |
1153 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1199 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1154 "quic packet length: %d", plen); | 1200 "quic packet length: %d", plen); |
1155 | 1201 |
1156 return NGX_OK; | 1202 return NGX_OK; |
1278 | 1324 |
1279 if (ngx_quic_ciphers(c, &ciphers, pkt->level) == NGX_ERROR) { | 1325 if (ngx_quic_ciphers(c, &ciphers, pkt->level) == NGX_ERROR) { |
1280 return NGX_ERROR; | 1326 return NGX_ERROR; |
1281 } | 1327 } |
1282 | 1328 |
1283 p = pkt->pos; | 1329 p = pkt->raw->pos; |
1284 | 1330 |
1285 /* draft-ietf-quic-tls-23#section-5.4.2: | 1331 /* draft-ietf-quic-tls-23#section-5.4.2: |
1286 * the Packet Number field is assumed to be 4 bytes long | 1332 * the Packet Number field is assumed to be 4 bytes long |
1287 * draft-ietf-quic-tls-23#section-5.4.[34]: | 1333 * draft-ietf-quic-tls-23#section-5.4.[34]: |
1288 * AES-Based and ChaCha20-Based header protections sample 16 bytes | 1334 * AES-Based and ChaCha20-Based header protections sample 16 bytes |
1319 /* packet protection */ | 1365 /* packet protection */ |
1320 | 1366 |
1321 in.data = p; | 1367 in.data = p; |
1322 | 1368 |
1323 if (pkt->flags & NGX_QUIC_PKT_LONG) { | 1369 if (pkt->flags & NGX_QUIC_PKT_LONG) { |
1324 in.len = pkt->buf.len - pnl; | 1370 in.len = pkt->len - pnl; |
1325 | 1371 |
1326 } else { | 1372 } else { |
1327 in.len = pkt->buf.data + pkt->buf.len - p; | 1373 in.len = pkt->data + pkt->len - p; |
1328 } | 1374 } |
1329 | 1375 |
1330 ad.len = p - pkt->buf.data; | 1376 ad.len = p - pkt->data; |
1331 ad.data = ngx_pnalloc(c->pool, ad.len); | 1377 ad.data = ngx_pnalloc(c->pool, ad.len); |
1332 if (ad.data == NULL) { | 1378 if (ad.data == NULL) { |
1333 return NGX_ERROR; | 1379 return NGX_ERROR; |
1334 } | 1380 } |
1335 | 1381 |
1336 ngx_memcpy(ad.data, pkt->buf.data, ad.len); | 1382 ngx_memcpy(ad.data, pkt->data, ad.len); |
1337 ad.data[0] = clearflags; | 1383 ad.data[0] = clearflags; |
1338 ad.data[ad.len - pnl] = (u_char) pn; | 1384 ad.data[ad.len - pnl] = (u_char) pn; |
1339 | 1385 |
1340 nonce = ngx_pstrdup(c->pool, &pkt->secret->iv); | 1386 nonce = ngx_pstrdup(c->pool, &pkt->secret->iv); |
1341 nonce[11] ^= pn; | 1387 nonce[11] ^= pn; |
1347 nonce, &in, &ad); | 1393 nonce, &in, &ad); |
1348 | 1394 |
1349 ngx_quic_hexdump0(c->log, "packet payload", | 1395 ngx_quic_hexdump0(c->log, "packet payload", |
1350 pkt->payload.data, pkt->payload.len); | 1396 pkt->payload.data, pkt->payload.len); |
1351 | 1397 |
1352 pkt->pos = pkt->payload.data; | |
1353 | |
1354 return rc; | 1398 return rc; |
1355 } | 1399 } |
1356 | 1400 |
1357 | 1401 |
1358 ngx_int_t | 1402 ssize_t |
1359 ngx_quic_read_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, | 1403 ngx_quic_read_frame(ngx_connection_t *c, u_char *start, u_char *end, |
1360 ngx_quic_frame_t *frame) | 1404 ngx_quic_frame_t *frame) |
1361 { | 1405 { |
1362 u_char *p, *end; | 1406 u_char *p; |
1363 | 1407 |
1364 size_t npad; | 1408 size_t npad; |
1365 | 1409 |
1366 p = pkt->pos; | 1410 p = start; |
1367 end = pkt->payload.data + pkt->payload.len; | 1411 |
1368 | 1412 frame->type = *p++; // TODO: check overflow (p < end) |
1369 frame->type = *p++; | |
1370 | 1413 |
1371 switch (frame->type) { | 1414 switch (frame->type) { |
1372 | 1415 |
1373 case NGX_QUIC_FT_CRYPTO: | 1416 case NGX_QUIC_FT_CRYPTO: |
1374 frame->u.crypto.offset = *p++; | 1417 frame->u.crypto.offset = *p++; |
1418 | 1461 |
1419 case NGX_QUIC_FT_PING: | 1462 case NGX_QUIC_FT_PING: |
1420 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame"); | 1463 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "PING frame"); |
1421 p++; | 1464 p++; |
1422 break; | 1465 break; |
1466 | |
1467 case NGX_QUIC_FT_NEW_CONNECTION_ID: | |
1468 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "NCID frame"); | |
1469 | |
1470 frame->u.ncid.seqnum = ngx_quic_parse_int(&p); | |
1471 frame->u.ncid.retire = ngx_quic_parse_int(&p); | |
1472 frame->u.ncid.len = *p++; | |
1473 ngx_memcpy(frame->u.ncid.cid, p, frame->u.ncid.len); | |
1474 p += frame->u.ncid.len; | |
1475 | |
1476 ngx_memcpy(frame->u.ncid.srt, p, 16); | |
1477 p += 16; | |
1478 | |
1479 break; | |
1480 | |
1481 case NGX_QUIC_FT_CONNECTION_CLOSE: | |
1482 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "connection close frame => NGX_ERROR"); | |
1483 | |
1484 // TODO: parse connection close here | |
1485 return NGX_ERROR; | |
1486 break; | |
1487 | |
1423 default: | 1488 default: |
1424 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, | 1489 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, |
1425 "unknown frame type %xi", frame->type); | 1490 "unknown frame type %xi", frame->type); |
1426 return NGX_ERROR; | 1491 return NGX_ERROR; |
1427 } | 1492 } |
1428 | 1493 |
1429 pkt->pos = p; | 1494 return p - start; |
1430 | |
1431 return NGX_OK; | |
1432 } | 1495 } |
1433 | 1496 |
1434 | 1497 |
1435 static ngx_int_t | 1498 static ngx_int_t |
1436 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, | 1499 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt, |
1537 | 1600 |
1538 /* process all payload from the current packet and generate ack if required */ | 1601 /* process all payload from the current packet and generate ack if required */ |
1539 static ngx_int_t | 1602 static ngx_int_t |
1540 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) | 1603 ngx_quic_payload_handler(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1541 { | 1604 { |
1542 u_char *end; | 1605 u_char *end, *p; |
1606 ssize_t len; | |
1543 ngx_uint_t ack_this; | 1607 ngx_uint_t ack_this; |
1544 ngx_quic_frame_t frame, *ack_frame; | 1608 ngx_quic_frame_t frame, *ack_frame; |
1545 ngx_quic_connection_t *qc; | 1609 ngx_quic_connection_t *qc; |
1546 | 1610 |
1547 qc = c->quic; | 1611 qc = c->quic; |
1548 end = pkt->payload.data + pkt->payload.len; | 1612 |
1613 p = pkt->payload.data; | |
1614 end = p + pkt->payload.len; | |
1549 | 1615 |
1550 ack_this = 0; | 1616 ack_this = 0; |
1551 | 1617 |
1552 while (pkt->pos < end) { | 1618 while (p < end) { |
1553 | 1619 |
1554 if (ngx_quic_read_frame(c, pkt, &frame) != NGX_OK) { | 1620 len = ngx_quic_read_frame(c, p, end, &frame); |
1621 if (len < 0) { | |
1555 return NGX_ERROR; | 1622 return NGX_ERROR; |
1556 } | 1623 } |
1624 | |
1625 p += len; | |
1557 | 1626 |
1558 switch (frame.type) { | 1627 switch (frame.type) { |
1559 | 1628 |
1560 case NGX_QUIC_FT_ACK: | 1629 case NGX_QUIC_FT_ACK: |
1561 | 1630 |
1592 | 1661 |
1593 case NGX_QUIC_FT_PING: | 1662 case NGX_QUIC_FT_PING: |
1594 ack_this = 1; | 1663 ack_this = 1; |
1595 continue; | 1664 continue; |
1596 | 1665 |
1666 case NGX_QUIC_FT_NEW_CONNECTION_ID: | |
1667 ack_this = 1; | |
1668 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
1669 "NCID: { seq=%ui retire=%ui len=%ui}", | |
1670 frame.u.ncid.seqnum, | |
1671 frame.u.ncid.retire, | |
1672 frame.u.ncid.len); | |
1673 continue; | |
1674 | |
1597 default: | 1675 default: |
1598 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 1676 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
1599 "unexpected frame type 0x%xd in packet", frame.type); | 1677 "unexpected frame type 0x%xd in packet", frame.type); |
1600 return NGX_ERROR; | 1678 return NGX_ERROR; |
1601 } | 1679 } |
1602 } | 1680 } |
1603 | 1681 |
1682 if (p != end) { | |
1683 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1684 "trailing garbage in payload: %ui bytes", end - p); | |
1685 return NGX_ERROR; | |
1686 } | |
1687 | |
1688 | |
1604 if (ack_this == 0) { | 1689 if (ack_this == 0) { |
1605 /* do not ack packets with ACKs and PADDING */ | 1690 /* do not ack packets with ACKs and PADDING */ |
1606 return NGX_OK; | 1691 return NGX_OK; |
1607 } | 1692 } |
1608 | 1693 |
1624 return ngx_quic_output(c); | 1709 return ngx_quic_output(c); |
1625 } | 1710 } |
1626 | 1711 |
1627 | 1712 |
1628 static ngx_int_t | 1713 static ngx_int_t |
1629 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, ngx_buf_t *b) | 1714 ngx_quic_new_connection(ngx_connection_t *c, ngx_ssl_t *ssl, |
1715 ngx_quic_header_t *pkt) | |
1630 { | 1716 { |
1631 ngx_quic_connection_t *qc; | 1717 ngx_quic_connection_t *qc; |
1632 | 1718 |
1633 ngx_quic_header_t pkt = { 0 }; | 1719 if (ngx_buf_size(pkt->raw) < 1200) { |
1634 | |
1635 pkt.buf.data = b->start; | |
1636 pkt.buf.len = b->last - b->pos; | |
1637 | |
1638 if (ngx_buf_size(b) < 1200) { | |
1639 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram"); | 1720 ngx_log_error(NGX_LOG_INFO, c->log, 0, "too small UDP datagram"); |
1640 return NGX_ERROR; | 1721 return NGX_ERROR; |
1641 } | 1722 } |
1642 | 1723 |
1643 if (ngx_quic_process_long_header(c, &pkt) != NGX_OK) { | 1724 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) { |
1644 return NGX_ERROR; | 1725 return NGX_ERROR; |
1645 } | 1726 } |
1646 | 1727 |
1647 if ((pkt.flags & 0xf0) != NGX_QUIC_PKT_INITIAL) { | 1728 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_INITIAL) { |
1648 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 1729 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
1649 "invalid initial packet: 0x%xi", pkt.flags); | 1730 "invalid initial packet: 0x%xi", pkt->flags); |
1650 return NGX_ERROR; | 1731 return NGX_ERROR; |
1651 } | 1732 } |
1652 | 1733 |
1653 if (ngx_quic_process_initial_header(c, &pkt) != NGX_OK) { | 1734 if (ngx_quic_process_initial_header(c, pkt) != NGX_OK) { |
1654 return NGX_ERROR; | 1735 return NGX_ERROR; |
1655 } | 1736 } |
1656 | 1737 |
1657 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); | 1738 qc = ngx_pcalloc(c->pool, sizeof(ngx_quic_connection_t)); |
1658 if (qc == NULL) { | 1739 if (qc == NULL) { |
1660 } | 1741 } |
1661 | 1742 |
1662 c->quic = qc; | 1743 c->quic = qc; |
1663 qc->ssl = ssl; | 1744 qc->ssl = ssl; |
1664 | 1745 |
1665 qc->dcid.len = pkt.dcid.len; | 1746 qc->dcid.len = pkt->dcid.len; |
1666 qc->dcid.data = ngx_pnalloc(c->pool, pkt.dcid.len); | 1747 qc->dcid.data = ngx_pnalloc(c->pool, pkt->dcid.len); |
1667 if (qc->dcid.data == NULL) { | 1748 if (qc->dcid.data == NULL) { |
1668 return NGX_ERROR; | 1749 return NGX_ERROR; |
1669 } | 1750 } |
1670 ngx_memcpy(qc->dcid.data, pkt.dcid.data, qc->dcid.len); | 1751 ngx_memcpy(qc->dcid.data, pkt->dcid.data, qc->dcid.len); |
1671 | 1752 |
1672 qc->scid.len = pkt.scid.len; | 1753 qc->scid.len = pkt->scid.len; |
1673 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len); | 1754 qc->scid.data = ngx_pnalloc(c->pool, qc->scid.len); |
1674 if (qc->scid.data == NULL) { | 1755 if (qc->scid.data == NULL) { |
1675 return NGX_ERROR; | 1756 return NGX_ERROR; |
1676 } | 1757 } |
1677 ngx_memcpy(qc->scid.data, pkt.scid.data, qc->scid.len); | 1758 ngx_memcpy(qc->scid.data, pkt->scid.data, qc->scid.len); |
1678 | 1759 |
1679 qc->token.len = pkt.token.len; | 1760 qc->token.len = pkt->token.len; |
1680 qc->token.data = ngx_pnalloc(c->pool, qc->token.len); | 1761 qc->token.data = ngx_pnalloc(c->pool, qc->token.len); |
1681 if (qc->token.data == NULL) { | 1762 if (qc->token.data == NULL) { |
1682 return NGX_ERROR; | 1763 return NGX_ERROR; |
1683 } | 1764 } |
1684 ngx_memcpy(qc->token.data, pkt.token.data, qc->token.len); | 1765 ngx_memcpy(qc->token.data, pkt->token.data, qc->token.len); |
1685 | 1766 |
1686 | 1767 |
1687 if (ngx_quic_initial_secret(c) != NGX_OK) { | 1768 if (ngx_quic_initial_secret(c) != NGX_OK) { |
1688 return NGX_ERROR; | 1769 return NGX_ERROR; |
1689 } | 1770 } |
1690 | 1771 |
1691 pkt.secret = &qc->client_in; | 1772 pkt->secret = &qc->client_in; |
1692 pkt.level = ssl_encryption_initial; | 1773 pkt->level = ssl_encryption_initial; |
1693 | 1774 |
1694 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) { | 1775 if (ngx_quic_decrypt(c, pkt) != NGX_OK) { |
1695 return NGX_ERROR; | 1776 return NGX_ERROR; |
1696 } | 1777 } |
1697 | 1778 |
1698 if (ngx_quic_init_connection(c, &pkt) != NGX_OK) { | 1779 if (ngx_quic_init_connection(c, pkt) != NGX_OK) { |
1699 return NGX_ERROR; | 1780 return NGX_ERROR; |
1700 } | 1781 } |
1701 | 1782 |
1702 return ngx_quic_payload_handler(c, &pkt); | 1783 return ngx_quic_payload_handler(c, pkt); |
1703 } | 1784 } |
1704 | 1785 |
1705 | 1786 |
1706 static ngx_int_t | 1787 static ngx_int_t |
1707 ngx_quic_handshake_input(ngx_connection_t *c, ngx_buf_t *b) | 1788 ngx_quic_handshake_input(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1708 { | 1789 { |
1709 ngx_ssl_conn_t *ssl_conn; | 1790 ngx_ssl_conn_t *ssl_conn; |
1710 ngx_quic_connection_t *qc; | 1791 ngx_quic_connection_t *qc; |
1711 | 1792 |
1712 ngx_quic_header_t pkt = { 0 }; | |
1713 | |
1714 qc = c->quic; | 1793 qc = c->quic; |
1715 ssl_conn = c->ssl->connection; | 1794 ssl_conn = c->ssl->connection; |
1716 | 1795 |
1717 pkt.buf.data = b->start; | |
1718 pkt.buf.len = b->last - b->pos; | |
1719 | |
1720 /* extract cleartext data into pkt */ | 1796 /* extract cleartext data into pkt */ |
1721 if (ngx_quic_process_long_header(c, &pkt) != NGX_OK) { | 1797 if (ngx_quic_process_long_header(c, pkt) != NGX_OK) { |
1722 return NGX_ERROR; | 1798 return NGX_ERROR; |
1723 } | 1799 } |
1724 | 1800 |
1725 if (pkt.dcid.len != qc->dcid.len) { | 1801 if (pkt->dcid.len != qc->dcid.len) { |
1726 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl"); | 1802 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcidl"); |
1727 return NGX_ERROR; | 1803 return NGX_ERROR; |
1728 } | 1804 } |
1729 | 1805 |
1730 if (ngx_memcmp(pkt.dcid.data, qc->dcid.data, qc->dcid.len) != 0) { | 1806 if (ngx_memcmp(pkt->dcid.data, qc->dcid.data, qc->dcid.len) != 0) { |
1731 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); | 1807 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic dcid"); |
1732 return NGX_ERROR; | 1808 return NGX_ERROR; |
1733 } | 1809 } |
1734 | 1810 |
1735 if (pkt.scid.len != qc->scid.len) { | 1811 if (pkt->scid.len != qc->scid.len) { |
1736 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl"); | 1812 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scidl"); |
1737 return NGX_ERROR; | 1813 return NGX_ERROR; |
1738 } | 1814 } |
1739 | 1815 |
1740 if (ngx_memcmp(pkt.scid.data, qc->scid.data, qc->scid.len) != 0) { | 1816 if (ngx_memcmp(pkt->scid.data, qc->scid.data, qc->scid.len) != 0) { |
1741 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid"); | 1817 ngx_log_error(NGX_LOG_INFO, c->log, 0, "unexpected quic scid"); |
1742 return NGX_ERROR; | 1818 return NGX_ERROR; |
1743 } | 1819 } |
1744 | 1820 |
1745 if ((pkt.flags & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) { | 1821 if ((pkt->flags & 0xf0) != NGX_QUIC_PKT_HANDSHAKE) { |
1746 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 1822 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
1747 "invalid packet type: 0x%xi", pkt.flags); | 1823 "invalid packet type: 0x%xi", pkt->flags); |
1748 return NGX_ERROR; | 1824 return NGX_ERROR; |
1749 } | 1825 } |
1750 | 1826 |
1751 if (ngx_quic_process_handshake_header(c, &pkt) != NGX_OK) { | 1827 if (ngx_quic_process_handshake_header(c, pkt) != NGX_OK) { |
1752 return NGX_ERROR; | 1828 return NGX_ERROR; |
1753 } | 1829 } |
1754 | 1830 |
1755 pkt.secret = &qc->client_hs; | 1831 pkt->secret = &qc->client_hs; |
1756 pkt.level = ssl_encryption_handshake; | 1832 pkt->level = ssl_encryption_handshake; |
1757 | 1833 |
1758 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) { | 1834 if (ngx_quic_decrypt(c, pkt) != NGX_OK) { |
1759 return NGX_ERROR; | 1835 return NGX_ERROR; |
1760 } | 1836 } |
1761 | 1837 |
1762 return ngx_quic_payload_handler(c, &pkt); | 1838 return ngx_quic_payload_handler(c, pkt); |
1763 } | 1839 } |
1764 | 1840 |
1765 | 1841 |
1766 static ngx_int_t | 1842 static ngx_int_t |
1767 ngx_quic_app_input(ngx_connection_t *c, ngx_buf_t *b) | 1843 ngx_quic_app_input(ngx_connection_t *c, ngx_quic_header_t *pkt) |
1768 { | 1844 { |
1769 ngx_quic_connection_t *qc; | 1845 ngx_quic_connection_t *qc; |
1770 | 1846 |
1771 qc = c->quic; | 1847 qc = c->quic; |
1772 | 1848 |
1773 /* TODO: this is a stub, untested */ | 1849 /* TODO: this is a stub, untested */ |
1774 | 1850 |
1775 ngx_quic_header_t pkt = { 0 }; | 1851 if (ngx_quic_process_short_header(c, pkt) != NGX_OK) { |
1776 | 1852 return NGX_ERROR; |
1777 pkt.buf.data = b->start; | 1853 } |
1778 pkt.buf.len = b->last - b->pos; | 1854 |
1779 | 1855 pkt->secret = &qc->client_ad; |
1780 if (ngx_quic_process_short_header(c, &pkt) != NGX_OK) { | 1856 pkt->level = ssl_encryption_application; |
1781 return NGX_ERROR; | 1857 |
1782 } | 1858 if (ngx_quic_decrypt(c, pkt) != NGX_OK) { |
1783 | 1859 return NGX_ERROR; |
1784 pkt.secret = &qc->client_ad; | 1860 } |
1785 pkt.level = ssl_encryption_application; | 1861 |
1786 | 1862 return ngx_quic_payload_handler(c, pkt); |
1787 if (ngx_quic_decrypt(c, &pkt) != NGX_OK) { | |
1788 return NGX_ERROR; | |
1789 } | |
1790 | |
1791 return ngx_quic_payload_handler(c, &pkt); | |
1792 } | 1863 } |
1793 | 1864 |
1794 | 1865 |
1795 uint64_t | 1866 uint64_t |
1796 ngx_quic_parse_int(u_char **pos) | 1867 ngx_quic_parse_int(u_char **pos) |