diff --git a/src/etcp_connections.c b/src/etcp_connections.c index a70cac94..1f3cdddb 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -112,41 +112,27 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) { dgram->link = link; dgram->noencrypt_len = SC_PUBKEY_ENC_SIZE; - size_t offset = 0; - - // reset=1: ETCP_INIT_REQUEST (0x02), reset=0: ETCP_INIT_REQUEST_NOINIT (0x04) - dgram->data[offset++] = reset ? ETCP_INIT_REQUEST : ETCP_INIT_REQUEST_NOINIT; - - uint64_t node_id = link->etcp->instance->node_id; - dgram->data[offset++] = (node_id >> 56) & 0xFF; - dgram->data[offset++] = (node_id >> 48) & 0xFF; - dgram->data[offset++] = (node_id >> 40) & 0xFF; - dgram->data[offset++] = (node_id >> 32) & 0xFF; - dgram->data[offset++] = (node_id >> 24) & 0xFF; - dgram->data[offset++] = (node_id >> 16) & 0xFF; - dgram->data[offset++] = (node_id >> 8) & 0xFF; - dgram->data[offset++] = node_id & 0xFF; - - // session_id (4 bytes) - для защиты от ложного reinit - uint32_t session_id = link->etcp->session_id; - dgram->data[offset++] = (session_id >> 24) & 0xFF; - dgram->data[offset++] = (session_id >> 16) & 0xFF; - dgram->data[offset++] = (session_id >> 8) & 0xFF; - dgram->data[offset++] = session_id & 0xFF; - - dgram->data[offset++] = (link->mtu_local >> 8) & 0xFF; - dgram->data[offset++] = link->mtu_local & 0xFF; - - dgram->data[offset++] = (link->keepalive_interval >> 8) & 0xFF; - dgram->data[offset++] = link->keepalive_interval & 0xFF; - - dgram->data[offset++] = ((link->recovery_interval/100) >> 8) & 0xFF; - dgram->data[offset++] = (link->recovery_interval/100) & 0xFF; - dgram->data[offset++] = link->local_link_id; - dgram->data[offset++] = link->conn ? link->conn->sock_id : 0; - dgram->data[offset++] = link->conn ? link->conn->only_local : 0; - dgram->data[offset++] = link->conn ? link->conn->type : CFG_SERVER_TYPE_UNKNOWN; + struct ETCP_INIT_REQUEST_PKT* req = (struct ETCP_INIT_REQUEST_PKT*)dgram->data; + req->code = reset ? ETCP_INIT_REQUEST : ETCP_INIT_REQUEST_NOINIT; + *(uint64_t*)req->node_id = htobe64(link->etcp->instance->node_id); + *(uint32_t*)req->session_id = htobe32(link->etcp->session_id); + *(uint16_t*)req->mtu = htobe16(link->mtu_local); + *(uint16_t*)req->keepalive = htobe16(link->keepalive_interval); + *(uint16_t*)req->recovery = htobe16(link->recovery_interval / 100); + req->link_id = link->local_link_id; + req->socket_id = link->conn ? link->conn->sock_id : 0; + req->only_local = link->conn ? link->conn->only_local : 0; + req->type = link->conn ? link->conn->type : CFG_SERVER_TYPE_UNKNOWN; + if (link->conn && link->conn->interface_addr.ss_family == AF_INET) { + struct sockaddr_in* sin = (struct sockaddr_in*)&link->conn->interface_addr; + memcpy(req->src_ipv4, &sin->sin_addr.s_addr, 4); + *(uint16_t*)req->src_port = sin->sin_port; + } else { + memset(req->src_ipv4, 0, 4); + memset(req->src_port, 0, 2); + } + size_t offset = ETCP_INIT_REQ_V2_SIZE; // padding int s = rand() % (link->handshake_maxsize - link->handshake_minsize) + link->handshake_minsize; @@ -179,7 +165,7 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) { dgram->data_len = offset; - DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Sending INIT request to link, node_id=%016llx, retry=%d", (unsigned long long)node_id, link->init_retry_count); + DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Sending INIT request to link, node_id=%016llx, retry=%d", (unsigned long long)link->etcp->instance->node_id, link->init_retry_count); // Debug: print remote address before sending if (link->remote_addr.ss_family == AF_INET) { @@ -1263,21 +1249,9 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { pkt->data_len=pkt_len-3; pkt->noencrypt_len=0; - struct { - uint8_t code; - uint8_t id[8]; - uint8_t session_id[4]; - uint8_t mtu[2]; - uint8_t keepalive[2]; - uint8_t recovery[2]; - uint8_t link_id; - uint8_t remote_socket_id; - uint8_t only_local; - uint8_t type; - uint8_t pubkey[SC_PUBKEY_SIZE]; - } *ack_hdr=(void*)&pkt->data[0]; - uint64_t peer_id = be64toh(*(uint64_t*)ack_hdr->id); - if (ack_hdr->code == ETCP_PING) { + uint8_t code = pkt->data[0]; + uint64_t peer_id = be64toh(*(uint64_t*)(pkt->data + 1)); + if (code == ETCP_PING) { if (pkt_len < 22) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PING too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str); errorcode=7; @@ -1319,7 +1293,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { memory_pool_free(e_sock->instance->pkt_pool, pkt); return; } - if (ack_hdr->code == ETCP_PONG) { + if (code == ETCP_PONG) { if (pkt_len < 20) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "PONG too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str); errorcode=7; @@ -1368,11 +1342,16 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { memory_pool_free(e_sock->instance->pkt_pool, pkt); return; } - if (ack_hdr->code!=ETCP_INIT_REQUEST && ack_hdr->code!=ETCP_INIT_REQUEST_NOINIT) { - DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "not an init packet, code=%02x", ack_hdr->code); + if (code!=ETCP_INIT_REQUEST && code!=ETCP_INIT_REQUEST_NOINIT) { + DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "not an init packet, code=%02x", code); errorcode=4; goto ec_fr; }// не init + if (pkt_len < ETCP_INIT_REQ_V1_SIZE) { + DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "INIT REQUEST too short: pkt_len=%zu from %s", pkt_len, sockaddr_storage_to_str(&addr).str); + errorcode=7; + goto ec_fr; + } // Check allowed keys for incoming connections struct global_config *global = &e_sock->instance->config->global; @@ -1398,7 +1377,8 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { } } - uint32_t session_id = be32toh(*(uint32_t*)ack_hdr->session_id); + struct ETCP_INIT_REQUEST_PKT* req = (struct ETCP_INIT_REQUEST_PKT*)pkt->data; + uint32_t session_id = be32toh(*(uint32_t*)req->session_id); DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "INIT request session_id=%08x", session_id); struct ETCP_CONN* conn=e_sock->instance->connections; @@ -1428,15 +1408,15 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { // Check if link already exists (for CHANNEL_INIT recovery) - struct ETCP_LINK* existing_link = etcp_link_find_by_remote_id(conn, ack_hdr->link_id); + struct ETCP_LINK* existing_link = etcp_link_find_by_remote_id(conn, req->link_id); uint8_t send_reset = 0; if (existing_link && existing_link->etcp == conn) {// существующий линк - DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] found existing link for id=%d, socket=[%s]", conn->log_name, ack_hdr->link_id, e_sock->name); + DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] found existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name); link = existing_link; if (!sockaddr_equal(&link->remote_addr, &addr)) { - DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] IP:port changed for remote_link_id=%d socket:[%s]", conn->log_name, ack_hdr->link_id, e_sock->name); + DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "[%s] IP:port changed for remote_link_id=%d socket:[%s]", conn->log_name, req->link_id, e_sock->name); if (link->conn) remove_link(link->conn, link->ip_port_hash); // remove old connection from old socket link->conn=e_sock; memcpy(&link->remote_addr, &addr, sizeof(addr)); @@ -1454,10 +1434,10 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { } // Link exists - reuse it for recovery - link->remote_link_id = ack_hdr->link_id; - link->remote_socket_id = ack_hdr->remote_socket_id; - link->remote_only_local = ack_hdr->only_local; - link->remote_type = ack_hdr->type; + link->remote_link_id = req->link_id; + link->remote_socket_id = req->socket_id; + link->remote_only_local = req->only_local; + link->remote_type = req->type; // For CHANNEL_INIT (0x04): if link already initialized - no reset, otherwise reset // For INIT_REQUEST (0x02): always reset @@ -1478,14 +1458,14 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { link->init_timer = NULL; } } else { - DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] NO existing link for id=%d, socket=[%s]", conn->log_name, ack_hdr->link_id, e_sock->name); + DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] NO existing link for id=%d, socket=[%s]", conn->log_name, req->link_id, e_sock->name); // Create new link link = etcp_link_new(conn, e_sock, &addr, 1); if (!link) { if (new_conn) etcp_connection_close(conn); errorcode=66; DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION, "etcp_connections_read_callback: failed to create link for connection"); goto ec_fr; }// облом - link->remote_link_id = ack_hdr->link_id; - link->remote_socket_id = ack_hdr->remote_socket_id; - link->remote_only_local = ack_hdr->only_local; - link->remote_type = ack_hdr->type; + link->remote_link_id = req->link_id; + link->remote_socket_id = req->socket_id; + link->remote_only_local = req->only_local; + link->remote_type = req->type; // For new links: check session_id to avoid false reinit if (conn->session_id != session_id) { @@ -1494,71 +1474,80 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) { conn->session_id = session_id; etcp_conn_reinit(conn); } - link->keepalive_interval=(ack_hdr->keepalive[0]<<8) | ack_hdr->keepalive[1]; - link->recovery_interval=((ack_hdr->recovery[0]<<8) | ack_hdr->recovery[1])*100;// timebase в link, timebase/100 в кодограмме + link->keepalive_interval=(req->keepalive[0]<<8) | req->keepalive[1]; + link->recovery_interval=((req->recovery[0]<<8) | req->recovery[1])*100;// timebase в link, timebase/100 в кодограмме if (link->keepalive_interval < 10) link->keepalive_interval = 10; DEBUG_DEBUG(DEBUG_CATEGORY_KEEPALIVE, "set keepalive for link=%d", link->keepalive_interval); } - link->mtu_remote = (ack_hdr->mtu[0] << 8) | ack_hdr->mtu[1]; + link->mtu_remote = (req->mtu[0] << 8) | req->mtu[1]; 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); - struct { - uint8_t code; - uint8_t id[8]; - uint8_t session_id[4]; - uint8_t mtu[2]; - uint8_t link_id; - uint8_t remote_socket_id; - uint8_t only_local; - uint8_t type; - uint8_t peer_ipv4[4]; - uint8_t peer_port[2]; - } *ack_repl_hdr=(void*)&pkt->data[0]; + struct ETCP_INIT_RESPONSE_PKT* resp = (struct ETCP_INIT_RESPONSE_PKT*)pkt->data; // Set response code: 0x03 (with reset) or 0x05 (without reset) // response with init (0x03) only if reinit was actually done on server side if (send_reset != 0) { DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "send init_response with reset"); - ack_repl_hdr->code = ETCP_INIT_RESPONSE; // 0x03 - with reset + resp->code = ETCP_INIT_RESPONSE; // 0x03 - with reset } else { DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "send init_response without reset"); - ack_repl_hdr->code = ETCP_INIT_RESPONSE_NOINIT; // 0x05 - without reset + resp->code = ETCP_INIT_RESPONSE_NOINIT; // 0x05 - without reset } - *(uint64_t*)ack_repl_hdr->id = htobe64(e_sock->instance->node_id); - *(uint32_t*)ack_repl_hdr->session_id = htobe32(conn->session_id); + *(uint64_t*)resp->node_id = htobe64(e_sock->instance->node_id); + *(uint32_t*)resp->session_id = htobe32(conn->session_id); - ack_repl_hdr->mtu[0]=link->mtu_local>>8; - ack_repl_hdr->mtu[1]=link->mtu_local; - ack_repl_hdr->link_id = link->local_link_id; - ack_repl_hdr->remote_socket_id = ack_hdr->remote_socket_id; - ack_repl_hdr->only_local = e_sock->only_local; - ack_repl_hdr->type = e_sock->type; + resp->mtu[0]=link->mtu_local>>8; + resp->mtu[1]=link->mtu_local; + resp->link_id = link->local_link_id; + resp->remote_socket_id = req->socket_id; + resp->only_local = e_sock->only_local; + resp->type = e_sock->type; // Add client's IP:port (so client behind NAT can know its external address) if (addr.ss_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in*)&addr; - memcpy(ack_repl_hdr->peer_ipv4, &sin->sin_addr.s_addr, 4); + memcpy(resp->peer_ipv4, &sin->sin_addr.s_addr, 4); uint16_t port = ntohs(sin->sin_port); - ack_repl_hdr->peer_port[0] = port >> 8; - ack_repl_hdr->peer_port[1] = port & 0xFF; + resp->peer_port[0] = port >> 8; + resp->peer_port[1] = port & 0xFF; link->nat_ip = sin->sin_addr.s_addr; link->nat_port = port; } else { // For IPv6, set to 0 (not supported for NAT traversal) - memset(ack_repl_hdr->peer_ipv4, 0, 4); - memset(ack_repl_hdr->peer_port, 0, 2); + memset(resp->peer_ipv4, 0, 4); + memset(resp->peer_port, 0, 2); link->nat_ip = 0; link->nat_port = 0; } + // DIRECT detection: if client reports its own address and it matches observed source → real public IP + if (pkt_len >= ETCP_INIT_REQ_V2_SIZE && addr.ss_family == AF_INET && link->nat_ip != 0) { + uint32_t reported_ip; + memcpy(&reported_ip, req->src_ipv4, 4); + uint16_t reported_port = be16toh(*(uint16_t*)req->src_port); + if (reported_ip != 0 && reported_ip == link->nat_ip + && reported_port == link->nat_port + && !is_local_subnet(link->nat_ip)) + { + link->nat_type = NAT_TYPE_DIRECT; + link->nat_check_status = NAT_CHECK_EIM; + if (link->etcp->instance->bgp) { + route_bgp_send_nat_info(link->etcp, link->remote_socket_id, + link->nat_ip, link->nat_port, NAT_TYPE_DIRECT); + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "DIRECT IP: %s:%u for %s", + ip_to_str(&link->nat_ip, AF_INET).str, link->nat_port, + link->etcp->log_name); + } + } pkt->noencrypt_len=0; pkt->link=link; link->recv_keepalive = 1; link->last_recv_local_time = get_time_tb(); link->last_recv_timestamp = pkt->timestamp; - int xoffset=sizeof(*ack_repl_hdr); + int xoffset=sizeof(struct ETCP_INIT_RESPONSE_PKT); // padding int s = rand() % (link->handshake_maxsize - link->handshake_minsize) + link->handshake_minsize; if (s > (int)(link->mtu)) s = (int)(link->mtu); @@ -1625,9 +1614,9 @@ process_decrypted: link->total_decrypted += pkt->data_len; size_t offset = 0; - uint8_t code = pkt->data[offset++]; + uint8_t pkt_code = pkt->data[offset++]; - if (code == ETCP_KEEPALIVE) { + if (pkt_code == ETCP_KEEPALIVE) { if (pkt->data_len >= 3) { uint16_t peer_period = pkt->data[1] | ((uint16_t)pkt->data[2] << 8); link->keepalive_timeout = (uint32_t)peer_period * KA_TIMEOUT_MULT; @@ -1637,16 +1626,13 @@ process_decrypted: return; // KA handled, nothing more to process } - if (code == ETCP_INIT_RESPONSE || code == ETCP_INIT_RESPONSE_NOINIT) { - if (pkt_len < 22) { errorcode = 46; DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "INIT_RESPONSE too short: pkt_len=%zu", pkt_len); goto ec_fr; } + if (pkt_code == ETCP_INIT_RESPONSE || pkt_code == ETCP_INIT_RESPONSE_NOINIT) { + if (pkt_len < ETCP_INIT_RESP_V1_SIZE) { errorcode = 46; DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "INIT_RESPONSE too short: pkt_len=%zu", pkt_len); goto ec_fr; } // ETCP_INIT_RESPONSE (0x03) - reset entire ETCP_CONN // ETCP_INIT_RESPONSE_NOINIT (0x05) - no reset - uint64_t server_node_id = 0; - for (int i = 0; i < 8; i++) { - server_node_id = (server_node_id << 8) | pkt->data[offset++]; - } - uint32_t resp_session_id = (pkt->data[offset] << 24) | (pkt->data[offset+1] << 16) | (pkt->data[offset+2] << 8) | pkt->data[offset+3]; - offset += 4; + struct ETCP_INIT_RESPONSE_PKT* resp = (struct ETCP_INIT_RESPONSE_PKT*)pkt->data; + uint64_t server_node_id = be64toh(*(uint64_t*)resp->node_id); + uint32_t resp_session_id = be32toh(*(uint32_t*)resp->session_id); DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "INIT_RESPONSE session_id=%08x", resp_session_id); // Check session_id: ignore response if it doesn't match our session if (resp_session_id != link->etcp->session_id) { @@ -1655,23 +1641,20 @@ process_decrypted: memory_pool_free(e_sock->instance->pkt_pool, pkt); return; } - link->mtu_remote = ((uint16_t)pkt->data[offset] << 8) | pkt->data[offset + 1]; - offset += 2; + link->mtu_remote = be16toh(*(uint16_t*)resp->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); - link->remote_link_id = pkt->data[offset++]; - link->remote_socket_id = pkt->data[offset++]; - link->remote_only_local = pkt->data[offset++]; - link->remote_type = pkt->data[offset++]; + link->remote_link_id = resp->link_id; + link->remote_socket_id = resp->remote_socket_id; + link->remote_only_local = resp->only_local; + link->remote_type = resp->type; // Parse NAT IP:port from response (new format includes 4+2 bytes) - if (pkt_len >= 24) { + if (pkt_len >= ETCP_INIT_RESP_V2_SIZE) { uint32_t new_nat_ip; - memcpy(&new_nat_ip, &pkt->data[offset], 4); - offset += 4; - uint16_t new_nat_port = (pkt->data[offset] << 8) | pkt->data[offset+1]; - offset += 2; + memcpy(&new_nat_ip, resp->peer_ipv4, 4); + uint16_t new_nat_port = be16toh(*(uint16_t*)resp->peer_port); // Check if NAT address changed if (link->nat_ip == 0 && link->nat_port == 0) { @@ -1710,7 +1693,6 @@ process_decrypted: link->etcp->log_name); } - if (offset > pkt_len) { errorcode=13; DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "etcp_connections_read_callback: packet parsing overflow, offset=%zu, pkt_len=%zu", offset, pkt_len); goto ec_fr; } // DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Received INIT_RESPONSE from server_node_id=%llu, mtu=%d", (unsigned long long)server_node_id, link->mtu); @@ -1724,7 +1706,7 @@ process_decrypted: link->init_timer = NULL; } - if (code == ETCP_INIT_RESPONSE) { + if (pkt_code == ETCP_INIT_RESPONSE) { DEBUG_TRACE(DEBUG_CATEGORY_CONNECTION, "do reinit 3 %p", link->etcp); etcp_conn_reinit(link->etcp); } diff --git a/src/etcp_connections.h b/src/etcp_connections.h index d0c8e710..deefd185 100644 --- a/src/etcp_connections.h +++ b/src/etcp_connections.h @@ -54,6 +54,45 @@ struct ETCP_DGRAM {// пакет (незашифрованный) /* Размер базового ACK: type(1) + count(1) + last_delivered_id(4) + rx_dup_count(2) */ #define ETCP_ACK_BASE_SIZE (2 + 4 + 2) +// --- INIT packet wire formats (inside encrypted payload, before padding) --- + +// INIT REQUEST: client → server +struct ETCP_INIT_REQUEST_PKT { + uint8_t code; // 0: ETCP_INIT_REQUEST (0x02) или ETCP_INIT_REQUEST_NOINIT (0x04) + uint8_t node_id[8]; // 1: sender node_id (big-endian) + uint8_t session_id[4]; // 9: session (big-endian) + uint8_t mtu[2]; // 13: client MTU (big-endian) + uint8_t keepalive[2]; // 15: keepalive interval (big-endian) + uint8_t recovery[2]; // 17: recovery interval/100 (big-endian) + uint8_t link_id; // 19: client's local link id + uint8_t socket_id; // 20: client's socket id + uint8_t only_local; // 21: client only_local flag + uint8_t type; // 22: client socket type (CFG_SERVER_TYPE_*) + // V2 fields (NAT_DIRECT detection): + uint8_t src_ipv4[4]; // 23: client interface_addr IPv4 (big-endian, 0 if N/A) + uint8_t src_port[2]; // 27: client interface_addr port (big-endian) +} __attribute__((packed)); +#define ETCP_INIT_REQ_V1_SIZE 23 // size without src_ipv4/src_port (backward compat) +#define ETCP_INIT_REQ_V2_SIZE 29 // size with src_ipv4/src_port + +// INIT RESPONSE: server → client +struct ETCP_INIT_RESPONSE_PKT { + uint8_t code; // 0: ETCP_INIT_RESPONSE (0x03) или ETCP_INIT_RESPONSE_NOINIT (0x05) + uint8_t node_id[8]; // 1: server node_id (big-endian) + uint8_t session_id[4]; // 9: session (big-endian) + uint8_t mtu[2]; // 13: server MTU (big-endian) + uint8_t link_id; // 15: server's local link id + uint8_t remote_socket_id; // 16: echo of client's socket_id + uint8_t only_local; // 17: server only_local flag + uint8_t type; // 18: server socket type (CFG_SERVER_TYPE_*) + // V2 fields: + uint8_t peer_ipv4[4]; // 19: client's external NAT address (big-endian) + uint8_t peer_port[2]; // 23: client's external NAT port (big-endian) +} __attribute__((packed)); +#define ETCP_INIT_RESP_V1_SIZE 19 // size without peer_ipv4/peer_port +#define ETCP_INIT_RESP_V2_SIZE 25 // size with peer_ipv4/peer_port +#define ETCP_INIT_RESP_MIN_SIZE ETCP_INIT_RESP_V1_SIZE + typedef void (*etcp_ping_callback_t)(int success, uint16_t rtt, void* arg, uint64_t nonce, const uint8_t* resp_data, size_t resp_data_len); struct PING_CONTEXT { @@ -106,6 +145,7 @@ struct ETCP_SOCKET { #define NAT_TYPE_UNKNOWN 0 #define NAT_TYPE_EIM 1 // Endpoint-Independent Mapping #define NAT_TYPE_STRICT 2 // Address/Restricted or Symmetric +#define NAT_TYPE_DIRECT 3 // real public IP, no NAT (detected during INIT handshake) // Verified NAT types (published in nodeinfo after server-side NAT detection) // Values above CFG_SERVER_TYPE_PRIVATE to avoid collision with config types diff --git a/src/route_bgp.c b/src/route_bgp.c index beec94d5..420ecf3b 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -663,6 +663,7 @@ static void route_bgp_extract_nat_addr(struct ETCP_CONN* conn, uint32_t* nat_ip, void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link) {// проверяем тип нат для линка link if (!bgp || !link || !link->conn || !link->etcp) return; + if (link->nat_type == NAT_TYPE_DIRECT) return; if (link->nat_check_status == NAT_CHECK_IN_PROGRESS) return; // Skip NAT check for private sockets - they are not reachable from outside if (link->conn->type == CFG_SERVER_TYPE_PRIVATE) { @@ -1012,6 +1013,7 @@ static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* f uint8_t verified_type; if (info->nat_type == NAT_TYPE_EIM) verified_type = NAT_VERIFIED_EIM; else if (info->nat_type == NAT_TYPE_STRICT) verified_type = NAT_VERIFIED_STRICT; + else if (info->nat_type == NAT_TYPE_DIRECT) verified_type = NAT_VERIFIED_DIRECT; else verified_type = NAT_VERIFIED_UNKNOWN; int data_changed = 0;