Check accepted and rejected MTU boundaries in both UDP handshake directions

This commit is contained in:
evgeny committed 2026-10-23 23:42:49 +02:00
1 parent b8021efed8
commit 942736d604
1 file changed
+35 -4
+35 -4
View File
@@ -252,12 +252,12 @@ static void request_boundaries(unsigned established) {
request.code = variant ? ETCP_INIT_REQUEST_NOINIT : ETCP_INIT_REQUEST;
for (unsigned invalid = 0; invalid < sizeof(request) + sizeof(request.node_id) + 5; invalid++) {
unsigned length = invalid < sizeof(request) ? invalid : sizeof(request);
unsigned fault = invalid - sizeof(request);
unsigned fault = invalid < sizeof(request) ? 0 : invalid - sizeof(request);
uint8_t saved_mtu[2]; memcpy(saved_mtu, request.mtu, 2);
uint8_t saved_id = request.link_id;
if (invalid >= sizeof(request) && fault < 8) request.node_id[fault] ^= 1;
if (invalid >= sizeof(request) && fault >= 8 && fault < 12) {
const uint16_t values[] = {0, 1, 100, WIRE_OVERHEAD(AF_INET) + ETCP_PAYLOAD_HEADER_SIZE + ACK_REZERV + 2};
const uint16_t values[] = {0, 1, 100, ETCP_MIN_UDP_MTU(AF_INET) - 1};
request.mtu[0] = values[fault - 8] >> 8; request.mtu[1] = values[fault - 8];
}
if (invalid >= sizeof(request) && fault == 12) request.link_id = 0;
@@ -294,6 +294,16 @@ static void request_boundaries(unsigned established) {
CHECK(link->initialized && link->remote_keepalive == flag && link->recv_keepalive);
accepted++;
}
const uint16_t mtus[] = {ETCP_MIN_UDP_MTU(AF_INET), PACKET_DATA_MAX_MTU, UINT16_MAX};
for (unsigned i = 0; i < 3; i++) {
request.mtu[0] = mtus[i] >> 8; request.mtu[1] = mtus[i];
size_t errors = ep[1].socket->pkt_format_errors;
send_init_request_body(&request, sizeof(request), 1);
CHECK(ep[1].socket->pkt_format_errors == errors);
CHECK(first_link(1)->mtu_remote == (mtus[i] > PACKET_DATA_MAX_MTU ? PACKET_DATA_MAX_MTU : mtus[i]));
CHECK(ep[1].conn->normalizer->frag_size >= 3 && ep[1].conn->normalizer->frag_size < PACKET_DATA_SIZE);
accepted++;
}
}
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "INIT_REQUEST boundaries established=%u: rejected=%u accepted=%u", established, rejected, accepted);
teardown();
@@ -318,10 +328,20 @@ static void response_boundaries(void) {
unsigned rejected = 0, accepted = 0;
for (unsigned variant = 0; variant < 2; variant++) {
response.code = variant ? ETCP_INIT_RESPONSE_NOINIT : ETCP_INIT_RESPONSE;
for (unsigned len = 1; len <= sizeof(response) + 1; len++) {
for (unsigned invalid = 1; invalid <= sizeof(response) + 1 + 5; invalid++) {
unsigned len = invalid <= sizeof(response) + 1 ? invalid : sizeof(response);
struct ETCP_DGRAM* pkt = memory_pool_alloc(ep[0].inst->pkt_pool); CHECK(pkt);
memcpy(pkt->data, &response, sizeof(response)); pkt->data[sizeof(response)] = 0;
if (len >= sizeof(response)) pkt->data[1] ^= 1; /* Полное тело с чужим node_id тоже недопустимо. */
if (invalid <= sizeof(response) + 1 && len >= sizeof(response)) pkt->data[1] ^= 1;
if (invalid > sizeof(response) + 1) {
unsigned fault = invalid - sizeof(response) - 2;
struct ETCP_INIT_RESPONSE_PKT *bad = (struct ETCP_INIT_RESPONSE_PKT*)pkt->data;
if (fault == 4) bad->link_id = 0;
else {
const uint16_t values[] = {0, 1, 100, ETCP_MIN_UDP_MTU(AF_INET) - 1};
bad->mtu[0] = values[fault] >> 8; bad->mtu[1] = values[fault];
}
}
pkt->timestamp = 123; pkt->flag_up = 0;
struct ETCP_LINK before_link;
struct ETCP_CONN before_conn;
@@ -346,6 +366,17 @@ static void response_boundaries(void) {
CHECK(link->last_recv_timestamp == 456 && !ep[0].conn->callbacks_running);
CHECK(ep[0].conn->reset_id == epoch && !ep[0].reinit); accepted++;
}
const uint16_t mtus[] = {ETCP_MIN_UDP_MTU(AF_INET), PACKET_DATA_MAX_MTU, UINT16_MAX};
for (unsigned i = 0; i < 3; i++) {
struct ETCP_DGRAM *pkt = memory_pool_alloc(ep[0].inst->pkt_pool); CHECK(pkt);
memcpy(pkt->data, &response, sizeof(response)); pkt->timestamp = 456; pkt->flag_up = 1;
struct ETCP_INIT_RESPONSE_PKT *valid = (struct ETCP_INIT_RESPONSE_PKT*)pkt->data;
valid->mtu[0] = mtus[i] >> 8; valid->mtu[1] = mtus[i];
CHECK(etcp_packet_decrypted(ep[0].socket, pkt, link, sizeof(response) + ETCP_ENCRYPTED_HDR_SIZE) == 0);
CHECK(link->mtu_remote == (mtus[i] > PACKET_DATA_MAX_MTU ? PACKET_DATA_MAX_MTU : mtus[i]));
CHECK(ep[0].conn->normalizer->frag_size >= 3 && ep[0].conn->normalizer->frag_size < PACKET_DATA_SIZE);
accepted++;
}
}
CHECK(ep[0].down == 6 && ep[0].up == 7);
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "INIT_RESPONSE boundaries: rejected=%u accepted=%u (both codes, padding, flag_up=0/1)",