Validate UDP handshake MTU and nonzero path IDs before state updates

This commit is contained in:
evgeny committed 2026-10-23 23:41:58 +02:00
1 parent 1260884485
commit b8021efed8
2 files changed
+16 -3

No files matched your search

+12 -1
View File
@@ -2191,12 +2191,18 @@ static int handle_init_response_client(struct ETCP_SOCKET* e_sock, struct ETCP_D
if (server_node_id != sc_derive_node_id_from_pubkey(link->etcp->crypto_ctx.peer_public_key)) {
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "INIT_RESPONSE node ID does not match authenticated peer key"); return 46;
}
uint16_t remote_mtu = wire_read16(resp->mtu);
if (!resp->link_id || remote_mtu < ETCP_MIN_UDP_MTU(link->remote_addr.ss_family)) {
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "INIT_RESPONSE invalid path: link_id=%u MTU=%u minimum=%u",
resp->link_id, remote_mtu, (unsigned)ETCP_MIN_UDP_MTU(link->remote_addr.ss_family));
return 46;
}
struct ETCP_CONN* conn = link->etcp;
int old_state = link->link_state, old_status = etcp_link_record_rx(link, pkt);
uint64_t resp_reset_id = wire_read64(resp->reset_id);
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "INIT_RESPONSE rid=%016llx", (unsigned long long)resp_reset_id);
etcp_conn_apply_peer_reset_id(link->etcp, resp_reset_id);
link->mtu_remote = wire_read16(resp->mtu);
link->mtu_remote = remote_mtu;
if (link->mtu_remote > PACKET_DATA_MAX_MTU) link->mtu_remote = PACKET_DATA_MAX_MTU;
link->mtu = link->mtu_local < link->mtu_remote ? link->mtu_local : link->mtu_remote;
etcp_update_mtu(link->etcp);
@@ -2472,6 +2478,11 @@ static void etcp_process_packet(struct ETCP_SOCKET* e_sock, uint8_t* data,
}
uint64_t reset_id = wire_read64(req->reset_id);
uint16_t mtu = wire_read16(req->mtu);
if (!req->link_id || mtu < ETCP_MIN_UDP_MTU(addr.ss_family)) {
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "INIT_REQUEST invalid path: link_id=%u MTU=%u minimum=%u from=%s",
req->link_id, mtu, (unsigned)ETCP_MIN_UDP_MTU(addr.ss_family), sockaddr_storage_to_str(&addr).str);
errorcode = 7; goto ec_fr;
}
uint16_t src_port = wire_read16(req->src_port);
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "INIT received: peer=0x%016llx mtu=%u link=%u sock=%u rid=%016llx src=%s",
(unsigned long long)peer_id, mtu, req->link_id, req->socket_id,
+4 -2
View File
@@ -38,6 +38,8 @@ extern "C" {
// PACKET_DATA_SIZE (2048) — это внутренний буфер аллокации/приёма, а не wire-MTU.
#define PACKET_DATA_MAX_MTU 1500
#define ETCP_PAYLOAD_HEADER_SIZE 7 // type + seq:u32 + attempt_no:u16 (LE, 1..65535, общий номер для всех линков seq)
// Запас normalizer: длина u16 + хотя бы 1 байт кодограммы; меньший MTU даёт нулевой/переполненный frag_size.
#define ETCP_MIN_UDP_MTU(fam) (WIRE_OVERHEAD(fam) + ETCP_PAYLOAD_HEADER_SIZE + ACK_REZERV + 3)
#define ETCP_ACK_ENTRY_SIZE 10 // seq:u32 + attempt_no:u16 + receiver_delay_us:u32; все числа LE
#define ETCP_MAX_PAYLOAD_SIZE (PACKET_DATA_SIZE - ETCP_ACK_BASE_SIZE - ETCP_PAYLOAD_HEADER_SIZE)
#define ETCP_RFC791_MIN_MTU 576
@@ -102,7 +104,7 @@ struct ETCP_INIT_REQUEST_PKT {
uint8_t mtu[2]; // 17: client MTU (big-endian)
uint8_t keepalive[2]; // 19: keepalive interval (big-endian)
uint8_t recovery[2]; // 21: recovery interval/100 (big-endian)
uint8_t link_id; // 23: client's local link id
uint8_t link_id; // 23: client's local link id, 1..255
uint8_t socket_id; // 24: client's socket id
uint8_t only_local; // 25: client only_local flag
uint8_t type; // 26: client socket type (CFG_SERVER_TYPE_*)
@@ -124,7 +126,7 @@ struct ETCP_INIT_RESPONSE_PKT {
uint8_t node_id[8]; // 1: server node_id (big-endian)
uint8_t reset_id[8]; // 9: локальная эпоха потока сервера (big-endian), не эхо запроса
uint8_t mtu[2]; // 17: server MTU (big-endian)
uint8_t link_id; // 19: server's local link id
uint8_t link_id; // 19: server's local link id, 1..255
uint8_t remote_socket_id; // 20: ID серверного сокета, отправляющего ответ
uint8_t only_local; // 21: server only_local flag
uint8_t type; // 22: server socket type (CFG_SERVER_TYPE_*)