@ -572,160 +572,140 @@ static void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
struct ETCP_LINK * link = etcp_link_find_by_addr ( e_sock , & addr ) ;
// printf("[ETCP DEBUG] Received packet, link=%p, recv_len=%zd\n", link, recv_len);
// If no link found OR found link is a client link (not server), treat as potential INIT
// Client links shouldn't receive incoming INIT packets - only server links should
if ( link = = NULL | | link - > is_server = = 0 ) { // пробуем расшифровать, возможно это init
// printf("[ETCP DEBUG] No existing link found, trying to decrypt as INIT packet\n");
struct secure_channel sc ;
if ( recv_len < = SC_PUBKEY_SIZE ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " etcp_connections_read_callback: packet too small for init, size=%zd " , recv_len ) ;
// If we have an existing link (client link), try normal decryption instead
if ( link ! = NULL ) {
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " INIT packet too small, trying normal decryption with existing link " ) ;
goto normal_decrypt ;
}
errorcode = 1 ;
goto ec_fr ;
}
sc_init_ctx ( & sc , & e_sock - > instance - > my_keys ) ;
// printf("[ETCP DEBUG] Extracting peer public key from position %ld, total packet size=%zd\n", recv_len-SC_PUBKEY_SIZE, recv_len);
// printf("[ETCP DEBUG] Last 64 bytes of packet (PUBKEY): ");
// for (int i=0; i<SC_PUBKEY_SIZE; i++) DEBUG_INFO(DEBUG_CATEGORY_CRYPTO, "%02x ", data[recv_len-SC_PUBKEY_SIZE+i]);
// Расшифровываем public_key inplace используя собственный ключ
sc_sha_transcode ( e_sock - > instance - > my_keys . public_key , SC_PUBKEY_SIZE , data + recv_len - SC_PUBKEY_SIZE , SC_PUBKEY_SIZE ) ;
if ( sc_set_peer_public_key ( & sc , & data [ recv_len - SC_PUBKEY_SIZE ] , SC_PEER_PUBKEY_BIN ) ! = SC_OK ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: failed to set peer public key during init " ) ;
// If we have an existing link (client link), try normal decryption instead
if ( link ! = NULL ) {
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " INIT peer key setup failed, trying normal decryption with existing link " ) ;
goto normal_decrypt ;
}
errorcode = 2 ;
goto ec_fr ;
}
if ( sc_decrypt ( & sc , data , recv_len - SC_PUBKEY_SIZE , ( uint8_t * ) & pkt - > timestamp , & pkt_len ) ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: failed to decrypt init packet " ) ;
// If we have an existing link (client link), try normal decryption instead
if ( link ! = NULL ) {
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " INIT decryption failed, trying normal decryption with existing link " ) ;
goto normal_decrypt ;
}
errorcode = 3 ;
goto ec_fr ;
// Try normal decryption first if we have an established link with session keys
// This is the common case for data packets and responses
if ( link ! = NULL & & link - > etcp ! = NULL & & link - > etcp - > crypto_ctx . session_ready ) {
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " Decrypt start (normal) " ) ;
if ( ! sc_decrypt ( & link - > etcp - > crypto_ctx , data , recv_len , ( uint8_t * ) & pkt - > timestamp , & pkt_len ) ) {
// Normal decryption succeeded - process packet normally
goto process_decrypted ;
}
// printf("[ETCP DEBUG] Decrypt OK\n");
pkt - > data_len = pkt_len - 2 ;
pkt - > noencrypt_len = 0 ;
struct {
uint8_t code ;
uint8_t id [ 8 ] ;
uint8_t mtu [ 2 ] ;
uint8_t keepalive [ 2 ] ;
uint8_t link_id ;
uint8_t pubkey [ SC_PUBKEY_SIZE ] ;
} * ack_hdr = ( void * ) & pkt - > data [ 0 ] ;
uint64_t peer_id ;
memcpy ( & peer_id , & ack_hdr - > id [ 0 ] , 8 ) ;
if ( ack_hdr - > code ! = ETCP_INIT_REQUEST & & ack_hdr - > code ! = ETCP_CHANNEL_INIT ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " etcp_connections_read_callback: not an init packet, code=%02x " , ack_hdr - > code ) ;
// If we have an existing link (client link), try normal decryption instead
if ( link ! = NULL ) {
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " Packet is not INIT (code=%02x), trying normal decryption with existing link " , ack_hdr - > code ) ;
goto normal_decrypt ;
}
errorcode = 4 ;
goto ec_fr ;
} // не init
struct ETCP_CONN * conn = e_sock - > instance - > connections ;
while ( conn ) { // ищем есть ли подключение к этому пиру
if ( conn - > peer_node_id = = peer_id ) break ;
conn = conn - > next ;
}
int new_conn = 0 ;
if ( ! conn | | conn - > peer_node_id ! = peer_id ) { // создаём новое
new_conn = 1 ;
conn = etcp_connection_create ( e_sock - > instance ) ;
if ( ! conn ) { errorcode = 55 ; DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " etcp_connections_read_callback: failed to create connection " ) ; goto ec_fr ; } // облом
memcpy ( & conn - > crypto_ctx , & sc , sizeof ( sc ) ) ; // добавляем ключ
conn - > peer_node_id = peer_id ;
etcp_update_log_name ( conn ) ; // Update log_name with peer_node_id
char buf [ 128 ] ;
addr_to_string ( & addr , buf , sizeof ( buf ) ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " New connection from %s peer_id=%ld etcp=%p " , buf , peer_id , conn ) ;
// Add connection to instance list
conn - > next = e_sock - > instance - > connections ;
e_sock - > instance - > connections = conn ;
e_sock - > instance - > connections_count + + ;
DEBUG_INFO ( DEBUG_CATEGORY_CONNECTION , " Added incoming connection %p to instance, total count: %d " , conn , e_sock - > instance - > connections_count ) ;
}
else { // check keys если существующее подключение
if ( memcmp ( conn - > crypto_ctx . peer_public_key , sc . peer_public_key , SC_PUBKEY_SIZE ) ) { errorcode = 5 ; DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: peer key mismatch for node %llu " , ( unsigned long long ) peer_id ) ; goto ec_fr ; } // коллизия - peer id совпал а ключи разные.
}
struct ETCP_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 ;
if ( ack_hdr - > code = = 0x02 ) etcp_conn_reset ( conn ) ;
struct {
uint8_t code ;
uint8_t id [ 8 ] ;
uint8_t mtu [ 2 ] ;
uint8_t link_id ;
uint8_t peer_ipv4 [ 4 ] ;
uint8_t peer_port [ 2 ] ;
} * ack_repl_hdr = ( void * ) & pkt - > data [ 0 ] ;
ack_repl_hdr - > code + = 1 ;
memcpy ( ack_repl_hdr - > id , & e_sock - > instance - > node_id , 8 ) ;
int mtu = e_sock - > instance - > config - > global . mtu ;
ack_repl_hdr - > mtu [ 0 ] = mtu > > 8 ;
ack_repl_hdr - > mtu [ 1 ] = mtu ;
ack_repl_hdr - > link_id = link - > local_link_id ;
// 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 ) ;
uint16_t port = ntohs ( sin - > sin_port ) ;
ack_repl_hdr - > peer_port [ 0 ] = port > > 8 ;
ack_repl_hdr - > peer_port [ 1 ] = port & 0xFF ;
} 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 ) ;
// Normal decryption failed - might be INIT packet, fall through to INIT handling
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " Normal decryption failed, trying INIT decryption " ) ;
}
// Try INIT decryption (for incoming connection requests)
// This handles: no link found, or link without session, or normal decrypt failed
if ( recv_len < = SC_PUBKEY_SIZE ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " etcp_connections_read_callback: packet too small for init, size=%zd " , recv_len ) ;
errorcode = 1 ;
goto ec_fr ;
}
struct secure_channel sc ;
sc_init_ctx ( & sc , & e_sock - > instance - > my_keys ) ;
// Расшифровываем public_key inplace используя собственный ключ
sc_sha_transcode ( e_sock - > instance - > my_keys . public_key , SC_PUBKEY_SIZE , data + recv_len - SC_PUBKEY_SIZE , SC_PUBKEY_SIZE ) ;
if ( sc_set_peer_public_key ( & sc , & data [ recv_len - SC_PUBKEY_SIZE ] , SC_PEER_PUBKEY_BIN ) ! = SC_OK ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: failed to set peer public key during init " ) ;
errorcode = 2 ;
goto ec_fr ;
}
if ( sc_decrypt ( & sc , data , recv_len - SC_PUBKEY_SIZE , ( uint8_t * ) & pkt - > timestamp , & pkt_len ) ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: failed to decrypt init packet " ) ;
errorcode = 3 ;
goto ec_fr ;
}
// INIT decryption succeeded - process as new incoming connection
pkt - > data_len = pkt_len - 2 ;
pkt - > noencrypt_len = 0 ;
struct {
uint8_t code ;
uint8_t id [ 8 ] ;
uint8_t mtu [ 2 ] ;
uint8_t keepalive [ 2 ] ;
uint8_t link_id ;
uint8_t pubkey [ SC_PUBKEY_SIZE ] ;
} * ack_hdr = ( void * ) & pkt - > data [ 0 ] ;
uint64_t peer_id ;
memcpy ( & peer_id , & ack_hdr - > id [ 0 ] , 8 ) ;
if ( ack_hdr - > code ! = ETCP_INIT_REQUEST & & ack_hdr - > code ! = ETCP_CHANNEL_INIT ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " etcp_connections_read_callback: not an init packet, code=%02x " , ack_hdr - > code ) ;
errorcode = 4 ;
goto ec_fr ;
} // не init
struct ETCP_CONN * conn = e_sock - > instance - > connections ;
while ( conn ) { // ищем есть ли подключение к этому пиру
if ( conn - > peer_node_id = = peer_id ) break ;
conn = conn - > next ;
}
pkt - > data_len = sizeof ( * ack_repl_hdr ) ;
pkt - > noencrypt_len = 0 ;
pkt - > link = link ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " Sending INIT RESPONSE, link=%p, local_link_id=%d, remote_link_id=%d " , link , link - > local_link_id , link - > remote_link_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " [ETCP DEBUG] Send INIT RESPONSE " ) ;
etcp_encrypt_send ( pkt ) ;
// printf("[ETCP DEBUG] Send INIT RESPONSE ok\n");
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
link - > initialized = 1 ; // получен init request (server), считаем линк уже готовым к работе
loadbalancer_link_ready ( link ) ;
// Notify BGP about new connection to send routing table
if ( link - > etcp & & link - > etcp - > instance & & link - > etcp - > instance - > bgp ) {
route_bgp_new_conn ( link - > etcp ) ;
int new_conn = 0 ;
if ( ! conn | | conn - > peer_node_id ! = peer_id ) { // создаём новое
new_conn = 1 ;
conn = etcp_connection_create ( e_sock - > instance ) ;
if ( ! conn ) { errorcode = 55 ; DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " etcp_connections_read_callback: failed to create connection " ) ; goto ec_fr ; } // облом
memcpy ( & conn - > crypto_ctx , & sc , sizeof ( sc ) ) ; // добавляем ключ
conn - > peer_node_id = peer_id ;
etcp_update_log_name ( conn ) ; // Update log_name with peer_node_id
char buf [ 128 ] ;
addr_to_string ( & addr , buf , sizeof ( buf ) ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " New connection from %s peer_id=%ld etcp=%p " , buf , peer_id , conn ) ;
// Add connection to instance list
conn - > next = e_sock - > instance - > connections ;
e_sock - > instance - > connections = conn ;
e_sock - > instance - > connections_count + + ;
DEBUG_INFO ( DEBUG_CATEGORY_CONNECTION , " Added incoming connection %p to instance, total count: %d " , conn , e_sock - > instance - > connections_count ) ;
}
return ;
else { // check keys если существующее подключение
if ( memcmp ( conn - > crypto_ctx . peer_public_key , sc . peer_public_key , SC_PUBKEY_SIZE ) ) { errorcode = 5 ; DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: peer key mismatch for node %llu " , ( unsigned long long ) peer_id ) ; goto ec_fr ; } // коллизия - peer id совпал а ключи разные.
}
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 ;
if ( ack_hdr - > code = = 0x02 ) etcp_conn_reset ( conn ) ;
struct {
uint8_t code ;
uint8_t id [ 8 ] ;
uint8_t mtu [ 2 ] ;
uint8_t link_id ;
uint8_t peer_ipv4 [ 4 ] ;
uint8_t peer_port [ 2 ] ;
} * ack_repl_hdr = ( void * ) & pkt - > data [ 0 ] ;
ack_repl_hdr - > code + = 1 ;
memcpy ( ack_repl_hdr - > id , & e_sock - > instance - > node_id , 8 ) ;
int mtu = e_sock - > instance - > config - > global . mtu ;
ack_repl_hdr - > mtu [ 0 ] = mtu > > 8 ;
ack_repl_hdr - > mtu [ 1 ] = mtu ;
ack_repl_hdr - > link_id = link - > local_link_id ;
// 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 ) ;
uint16_t port = ntohs ( sin - > sin_port ) ;
ack_repl_hdr - > peer_port [ 0 ] = port > > 8 ;
ack_repl_hdr - > peer_port [ 1 ] = port & 0xFF ;
} 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 ) ;
}
pkt - > data_len = sizeof ( * ack_repl_hdr ) ;
pkt - > noencrypt_len = 0 ;
pkt - > link = link ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " Sending INIT RESPONSE, link=%p, local_link_id=%d, remote_link_id=%d " , link , link - > local_link_id , link - > remote_link_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " [ETCP DEBUG] Send INIT RESPONSE " ) ;
etcp_encrypt_send ( pkt ) ;
// printf("[ETCP DEBUG] Send INIT RESPONSE ok\n");
normal_decrypt :
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " Decrypt start " ) ;
if ( sc_decrypt ( & link - > etcp - > crypto_ctx , data , recv_len , ( uint8_t * ) & pkt - > timestamp , & pkt_len ) ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CRYPTO , " etcp_connections_read_callback: failed to decrypt packet from node %llu len=%d " , ( unsigned long long ) link - > etcp - > instance - > node_id , recv_len ) ;
// log_dump("my_privkey",&link->etcp->crypto_ctx.pk->private_key, SC_PRIVKEY_SIZE);
// log_dump("my_pubkey",&link->etcp->crypto_ctx.pk->public_key, SC_PUBKEY_SIZE);
// log_dump("peer_pubkey",&link->etcp->crypto_ctx.peer_public_key, SC_PUBKEY_SIZE);
errorcode = 6 ;
goto ec_fr ;
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
link - > initialized = 1 ; // получен init request (server), считаем линк уже готовым к работе
loadbalancer_link_ready ( link ) ;
// Notify BGP about new connection to send routing table
if ( link - > etcp & & link - > etcp - > instance & & link - > etcp - > instance - > bgp ) {
route_bgp_new_conn ( link - > etcp ) ;
}
return ;
process_decrypted :
DEBUG_INFO ( DEBUG_CATEGORY_ETCP , " Decrypt end " ) ;
if ( pkt_len < 3 ) { errorcode = 46 ; DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " etcp_connections_read_callback: decrypted packet too small, size=%zu " , pkt_len ) ; goto ec_fr ; }
pkt - > data_len = pkt_len - 2 ;