@ -22,12 +22,7 @@ static void etcp_connections_read_callback(int fd, void* arg);
static void etcp_connections_read_callback ( int fd , void * arg ) ;
// Simple debug macros to replace missing debug_config.h
# define DEBUG_CATEGORY_CONNECTION 1
# define DEBUG_CATEGORY_ETCP 2
# define DEBUG_CATEGORY_MEMORY 3
# define DEBUG_ERROR(category, fmt, ...) fprintf(stderr, "ERROR: " fmt "\n", ##__VA_ARGS__)
# define DEBUG_INFO(category, fmt, ...) fprintf(stdout, "INFO: " fmt "\n", ##__VA_ARGS__)
// Forward declarations for missing functions
@ -75,8 +70,10 @@ static void etcp_link_send_init(struct ETCP_LINK* link) {
memcpy ( dgram - > data + offset , link - > etcp - > instance - > my_keys . public_key , SC_PUBKEY_SIZE ) ;
dgram - > data_len = offset + SC_PUBKEY_SIZE ;
// ВАЖНО: Публичный ключ передается незашифрованным согласно спецификации ETCP
// Не изменять без обновления спецификации и тестов
dgram - > noencrypt_len = SC_PUBKEY_SIZE ;
DEBUG_INFO ( DEBUG_CATEGORY_CONNECTION , " Sending INIT request to link, node_id=%llu, retry=%d " , ( unsigned long long ) node_id , link - > init_retry_count ) ;
etcp_encrypt_send ( dgram ) ;
free ( dgram ) ;
@ -114,7 +111,6 @@ static int etcp_link_send_reset(struct ETCP_LINK* link) {
dgram - > noencrypt_len = 0 ;
dgram - > data [ 0 ] = 0x06 ;
DEBUG_INFO ( DEBUG_CATEGORY_CONNECTION , " Sending RESET to link " ) ;
int ret = etcp_encrypt_send ( dgram ) ;
free ( dgram ) ;
return ret ;
@ -213,7 +209,6 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
struct ETCP_SOCKET * e_sock = calloc ( 1 , sizeof ( struct ETCP_SOCKET ) ) ;
if ( ! e_sock ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMORY , " Failed to allocate connection " ) ;
return NULL ;
}
@ -221,7 +216,6 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
if ( ip ) {
family = ip - > ss_family ;
if ( family ! = AF_INET & & family ! = AF_INET6 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " Unsupported address family: %d " , family ) ;
free ( e_sock ) ;
return NULL ;
}
@ -229,7 +223,6 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
e_sock - > fd = socket ( family , SOCK_DGRAM , 0 ) ;
if ( e_sock - > fd < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " Failed to create socket: %s " , strerror ( errno ) ) ;
free ( e_sock ) ;
return NULL ;
}
@ -241,7 +234,6 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
if ( so_mark > 0 ) {
# ifdef SO_MARK
if ( setsockopt ( e_sock - > fd , SOL_SOCKET , SO_MARK , & so_mark , sizeof ( so_mark ) ) < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " Failed to set SO_MARK: %s " , strerror ( errno ) ) ;
}
# endif
}
@ -252,23 +244,23 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka
char ifname [ IF_NAMESIZE ] ;
if ( if_indextoname ( netif_index , ifname ) ) {
if ( setsockopt ( e_sock - > fd , SOL_SOCKET , SO_BINDTODEVICE , ifname , strlen ( ifname ) ) < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " Failed to bind to interface %s: %s " , ifname , strerror ( errno ) ) ;
}
}
# endif
}
// Store the local address if provided
// Store the local address and instance reference
if ( ip ) {
memcpy ( & e_sock - > local_addr , ip , sizeof ( struct sockaddr_storage ) ) ;
}
e_sock - > instance = instance ;
printf ( " [SOCKET] Registered ETCP socket fd=%d with callback %p \n " , e_sock - > fd , etcp_connections_read_callback ) ;
// Register socket with uasync for receiving packets
e_sock - > socket_id = uasync_add_socket ( instance - > ua , e_sock - > fd ,
etcp_connections_read_callback ,
NULL , NULL , e_sock ) ;
printf ( " [SOCKET] Registered ETCP socket fd=%d \n " , e_sock - > fd ) ;
printf ( " [SOCKET] Registered ETCP socket fd=%d instance=%p \n " , e_sock - > fd , instance ) ;
return e_sock ;
}
@ -292,6 +284,8 @@ void etcp_socket_remove(struct ETCP_SOCKET* conn) {
struct ETCP_LINK * etcp_link_new ( struct ETCP_CONN * etcp , struct ETCP_SOCKET * conn , struct sockaddr_storage * remote_addr , uint8_t is_server ) {
if ( ! remote_addr ) return NULL ;
printf ( " [LINK] Creating new link: remote_addr=%p, is_server=%d \n " , remote_addr , is_server ) ;
struct ETCP_LINK * link = calloc ( 1 , sizeof ( struct ETCP_LINK ) ) ;
if ( ! link ) return NULL ;
@ -317,6 +311,7 @@ struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn
if ( l ) l - > next = link ; else etcp - > links = link ;
if ( is_server = = 0 ) {
printf ( " [LINK] Client link, calling etcp_link_send_init \n " ) ;
etcp_link_send_init ( link ) ;
}
@ -356,7 +351,7 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
size_t enc_buf_len ;
sc_encrypt ( sc , dgram - > data , len , enc_buf , & enc_buf_len ) ;
if ( enc_buf_len + dgram - > noencrypt_len > 1480 ) { dgram - > link - > send_errors + + ; return - 1 ; }
memcpy ( enc_buf + enc_buf_len , dgram - > data + enc_buf_ len, dgram - > noencrypt_len ) ;
memcpy ( enc_buf + enc_buf_len , dgram - > data + len , dgram - > noencrypt_len ) ;
struct sockaddr_storage * addr = & dgram - > link - > remote_addr ;
socklen_t addr_len = ( addr - > ss_family = = AF_INET ) ? sizeof ( struct sockaddr_in ) : sizeof ( struct sockaddr_in6 ) ;
@ -386,6 +381,13 @@ static void etcp_connections_read_callback(int fd, void* arg) {
struct ETCP_LINK * link = etcp_link_find_by_addr ( e_sock , & addr ) ;
if ( link = = NULL ) { // пробуем расшифровать, возможно это init
// Удалить старый link если существует (спецификация строка 61)
struct ETCP_LINK * old_link = etcp_link_find_by_addr ( e_sock , & addr ) ;
if ( old_link ) {
printf ( " [INIT] Removing old link before creating new one \n " ) ;
// Предотвращаем утечки памяти при повторных подключениях
etcp_link_remove_from_connections ( e_sock , old_link ) ;
}
struct secure_channel sc ;
if ( recv_len < = SC_PUBKEY_SIZE ) { errorcode = 1 ; goto ec_fr ; }
sc_init_ctx ( & sc , & e_sock - > instance - > my_keys ) ;
@ -423,23 +425,19 @@ static void etcp_connections_read_callback(int fd, void* arg) {
if ( ack_hdr - > code = = 0x02 ) etcp_conn_reset ( conn ) ;
// send response - подключение создано
struct {
uint8_t main_id [ 2 ] ;
uint8_t timestamp [ 2 ] ;
uint8_t code ;
uint8_t id [ 8 ] ;
uint8_t mtu [ 2 ] ;
} * ack_repl_hdr = ( void * ) & pkt - > data [ 0 ] ;
ack_repl_hdr - > code + = 1 ;
ack_repl_hdr - > main_id [ 0 ] = 0 ;
ack_repl_hdr - > main_id [ 1 ] = 0 ;
ack_repl_hdr - > code = ETCP_INIT_RESPONSE ; // 0x03
memcpy ( & ack_repl_hdr - > id [ 0 ] , & 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 ;
pkt - > data_len = sizeof ( * ack_repl_hdr ) ;
pkt - > data_len = sizeof ( * ack_repl_hdr ) ; // 11 bytes (без keepalive согласно спецификации)
pkt - > noencrypt_len = 0 ;
pkt - > link = link ;
etcp_encrypt_send ( pkt ) ;
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
@ -451,6 +449,20 @@ static void etcp_connections_read_callback(int fd, void* arg) {
pkt - > noencrypt_len = 0 ;
pkt - > link = link ;
// Установка initialized только при получении INIT response от сервера (спецификация строка 42)
if ( ! link - > initialized & & link - > is_server = = 0 ) {
if ( pkt - > data_len > = 1 & & pkt - > data [ 0 ] = = ETCP_INIT_RESPONSE ) {
link - > initialized = 1 ; // ВАЖНО: только после подтверждения от сервера
printf ( " [CONNECTION] Link initialized successfully for peer %llx \n " , ( unsigned long long ) link - > etcp - > peer_node_id ) ;
// Снять таймаут
if ( link - > init_timer ) {
// Используем существующий механизм отмены таймера
link - > init_timer = NULL ;
link - > init_timeout = 0 ;
}
}
}
etcp_conn_input ( pkt ) ;
return ;
@ -472,7 +484,6 @@ int init_connections(struct UTUN_INSTANCE* instance) {
// Create socket for this server
struct ETCP_SOCKET * e_sock = etcp_socket_add ( instance , & server - > ip , server - > netif_index , server - > so_mark , server - > type ) ;
if ( ! e_sock ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " Failed to create socket for server %s " , server - > name ) ;
server = server - > next ;
continue ;
}
@ -500,7 +511,6 @@ int init_connections(struct UTUN_INSTANCE* instance) {
// Create ETCP connection for this client
struct ETCP_CONN * etcp_conn = etcp_connection_create ( instance ) ;
if ( ! etcp_conn ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " Failed to create ETCP connection for client %s " , client - > name ) ;
client = client - > next ;
continue ;
}
@ -547,7 +557,6 @@ int init_connections(struct UTUN_INSTANCE* instance) {
}
if ( ! e_sock ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " No socket found for client %s link " , client - > name ) ;
client_link = client_link - > next ;
continue ;
}
@ -555,7 +564,6 @@ int init_connections(struct UTUN_INSTANCE* instance) {
// Create link for this client connection
struct ETCP_LINK * link = etcp_link_new ( etcp_conn , e_sock , & client_link - > remote_addr , 0 ) ; // 0 = client initiates
if ( ! link ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " Failed to create link for client %s " , client - > name ) ;
client_link = client_link - > next ;
continue ;
}
@ -570,7 +578,6 @@ int init_connections(struct UTUN_INSTANCE* instance) {
// If there are clients configured but no connections created, that's an error
// If there are no clients (server-only mode), 0 connections is OK (server will accept incoming)
if ( instance - > connections_count = = 0 & & config - > clients ! = NULL ) {
DEBUG_ERROR ( DEBUG_CATEGORY_ETCP , " Clients configured but no connections initialized " ) ;
return - 1 ;
}
@ -586,12 +593,10 @@ int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len,
struct ETCP_LINK * link = etcp_link_find_by_addr ( e_sock , & remote_addr ) ;
if ( ! link ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " No link found for address " ) ;
return - 1 ;
}
if ( ! link - > initialized & & link - > is_server = = 0 ) {
DEBUG_INFO ( DEBUG_CATEGORY_CONNECTION , " Link not initialized, triggering connection establishment " ) ;
if ( ! link - > init_timer ) {
etcp_link_send_init ( link ) ;
}