@ -112,41 +112,27 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) {
dgram - > link = link ;
dgram - > link = link ;
dgram - > noencrypt_len = SC_PUBKEY_ENC_SIZE ;
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 ;
struct ETCP_INIT_REQUEST_PKT * req = ( struct ETCP_INIT_REQUEST_PKT * ) dgram - > data ;
dgram - > data [ offset + + ] = link - > mtu_local & 0xFF ;
req - > code = reset ? ETCP_INIT_REQUEST : ETCP_INIT_REQUEST_NOINIT ;
* ( uint64_t * ) req - > node_id = htobe64 ( link - > etcp - > instance - > node_id ) ;
dgram - > data [ offset + + ] = ( link - > keepalive_interval > > 8 ) & 0xFF ;
* ( uint32_t * ) req - > session_id = htobe32 ( link - > etcp - > session_id ) ;
dgram - > data [ offset + + ] = link - > keepalive_interval & 0xFF ;
* ( uint16_t * ) req - > mtu = htobe16 ( link - > mtu_local ) ;
* ( uint16_t * ) req - > keepalive = htobe16 ( link - > keepalive_interval ) ;
dgram - > data [ offset + + ] = ( ( link - > recovery_interval / 100 ) > > 8 ) & 0xFF ;
* ( uint16_t * ) req - > recovery = htobe16 ( link - > recovery_interval / 100 ) ;
dgram - > data [ offset + + ] = ( link - > recovery_interval / 100 ) & 0xFF ;
req - > link_id = link - > local_link_id ;
req - > socket_id = link - > conn ? link - > conn - > sock_id : 0 ;
dgram - > data [ offset + + ] = link - > local_link_id ;
req - > only_local = link - > conn ? link - > conn - > only_local : 0 ;
dgram - > data [ offset + + ] = link - > conn ? link - > conn - > sock_id : 0 ;
req - > type = link - > conn ? link - > conn - > type : CFG_SERVER_TYPE_UNKNOWN ;
dgram - > data [ offset + + ] = link - > conn ? link - > conn - > only_local : 0 ;
if ( link - > conn & & link - > conn - > interface_addr . ss_family = = AF_INET ) {
dgram - > data [ offset + + ] = link - > conn ? link - > conn - > type : CFG_SERVER_TYPE_UNKNOWN ;
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
// padding
int s = rand ( ) % ( link - > handshake_maxsize - link - > handshake_minsize ) + link - > handshake_minsize ;
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 ;
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
// Debug: print remote address before sending
if ( link - > remote_addr . ss_family = = AF_INET ) {
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 - > data_len = pkt_len - 3 ;
pkt - > noencrypt_len = 0 ;
pkt - > noencrypt_len = 0 ;
struct {
uint8_t code = pkt - > data [ 0 ] ;
uint8_t code ;
uint64_t peer_id = be64toh ( * ( uint64_t * ) ( pkt - > data + 1 ) ) ;
uint8_t id [ 8 ] ;
if ( code = = ETCP_PING ) {
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 ) {
if ( pkt_len < 22 ) {
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 ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " PING too short: pkt_len=%zu from %s " , pkt_len , sockaddr_storage_to_str ( & addr ) . str ) ;
errorcode = 7 ;
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 ) ;
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
return ;
return ;
}
}
if ( ack_hdr - > code = = ETCP_PONG ) {
if ( code = = ETCP_PONG ) {
if ( pkt_len < 20 ) {
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 ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " PONG too short: pkt_len=%zu from %s " , pkt_len , sockaddr_storage_to_str ( & addr ) . str ) ;
errorcode = 7 ;
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 ) ;
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
return ;
return ;
}
}
if ( ack_hdr - > code ! = ETCP_INIT_REQUEST & & ack_hdr - > code ! = ETCP_INIT_REQUEST_NOINIT ) {
if ( code ! = ETCP_INIT_REQUEST & & code ! = ETCP_INIT_REQUEST_NOINIT ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " not an init packet, code=%02x " , ack_hdr - > code ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_CONNECTION , " not an init packet, code=%02x " , code ) ;
errorcode = 4 ;
errorcode = 4 ;
goto ec_fr ;
goto ec_fr ;
} // не init
} // не 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
// Check allowed keys for incoming connections
struct global_config * global = & e_sock - > instance - > config - > global ;
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 ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " INIT request session_id=%08x " , session_id ) ;
struct ETCP_CONN * conn = e_sock - > instance - > connections ;
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)
// Check if link already exists (for CHANNEL_INIT recovery)
struct ETCP_LINK * existing_link = etcp_link_find_by_remote_id ( conn , ack_hd r- > link_id ) ;
struct ETCP_LINK * existing_link = etcp_link_find_by_remote_id ( conn , req - > link_id ) ;
uint8_t send_reset = 0 ;
uint8_t send_reset = 0 ;
if ( existing_link & & existing_link - > etcp = = conn ) { // существующий линк
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_hd r- > 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 ;
link = existing_link ;
if ( ! sockaddr_equal ( & link - > remote_addr , & addr ) ) {
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_hd r- > 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
if ( link - > conn ) remove_link ( link - > conn , link - > ip_port_hash ) ; // remove old connection from old socket
link - > conn = e_sock ;
link - > conn = e_sock ;
memcpy ( & link - > remote_addr , & addr , sizeof ( addr ) ) ;
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 exists - reuse it for recovery
link - > remote_link_id = ack_hd r- > link_id ;
link - > remote_link_id = req - > link_id ;
link - > remote_socket_id = ack_hd r- > remote_ socket_id;
link - > remote_socket_id = req - > socket_id ;
link - > remote_only_local = ack_hd r- > only_local ;
link - > remote_only_local = req - > only_local ;
link - > remote_type = ack_hd r- > type ;
link - > remote_type = req - > type ;
// For CHANNEL_INIT (0x04): if link already initialized - no reset, otherwise reset
// For CHANNEL_INIT (0x04): if link already initialized - no reset, otherwise reset
// For INIT_REQUEST (0x02): always 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 ;
link - > init_timer = NULL ;
}
}
} else {
} else {
DEBUG_DEBUG ( DEBUG_CATEGORY_CONNECTION , " [%s] NO existing link for id=%d, socket=[%s] " , conn - > log_name , ack_hd r- > 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
// Create new link
link = etcp_link_new ( conn , e_sock , & addr , 1 ) ;
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 ; } // облом
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_hd r- > link_id ;
link - > remote_link_id = req - > link_id ;
link - > remote_socket_id = ack_hd r- > remote_ socket_id;
link - > remote_socket_id = req - > socket_id ;
link - > remote_only_local = ack_hd r- > only_local ;
link - > remote_only_local = req - > only_local ;
link - > remote_type = ack_hd r- > type ;
link - > remote_type = req - > type ;
// For new links: check session_id to avoid false reinit
// For new links: check session_id to avoid false reinit
if ( conn - > session_id ! = session_id ) {
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 ;
conn - > session_id = session_id ;
etcp_conn_reinit ( conn ) ;
etcp_conn_reinit ( conn ) ;
}
}
link - > keepalive_interval = ( ack_hd r- > keepalive [ 0 ] < < 8 ) | ack_hd r- > keepalive [ 1 ] ;
link - > keepalive_interval = ( req - > keepalive [ 0 ] < < 8 ) | req - > keepalive [ 1 ] ;
link - > recovery_interval = ( ( ack_hd r- > recovery [ 0 ] < < 8 ) | ack_hd r- > recovery [ 1 ] ) * 100 ; // timebase в link, timebase/100 в кодограмме
link - > recovery_interval = ( ( req - > recovery [ 0 ] < < 8 ) | req - > recovery [ 1 ] ) * 100 ; // timebase в link, timebase/100 в кодограмме
if ( link - > keepalive_interval < 10 ) link - > keepalive_interval = 10 ;
if ( link - > keepalive_interval < 10 ) link - > keepalive_interval = 10 ;
DEBUG_DEBUG ( DEBUG_CATEGORY_KEEPALIVE , " set keepalive for link=%d " , link - > keepalive_interval ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_KEEPALIVE , " set keepalive for link=%d " , link - > keepalive_interval ) ;
}
}
link - > mtu_remote = ( ack_hd r- > mtu [ 0 ] < < 8 ) | ack_hd r- > 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 ;
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 ;
link - > mtu = link - > mtu_local < link - > mtu_remote ? link - > mtu_local : link - > mtu_remote ;
etcp_update_mtu ( link - > etcp ) ;
etcp_update_mtu ( link - > etcp ) ;
struct {
struct ETCP_INIT_RESPONSE_PKT * resp = ( struct ETCP_INIT_RESPONSE_PKT * ) pkt - > data ;
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 ] ;
// Set response code: 0x03 (with reset) or 0x05 (without reset)
// Set response code: 0x03 (with reset) or 0x05 (without reset)
// response with init (0x03) only if reinit was actually done on server side
// response with init (0x03) only if reinit was actually done on server side
if ( send_reset ! = 0 ) {
if ( send_reset ! = 0 ) {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " send init_response with reset " ) ;
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 {
} else {
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " send init_response without reset " ) ;
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 ) ;
* ( uint64_t * ) resp - > node_id = htobe64 ( e_sock - > instance - > node_id ) ;
* ( uint32_t * ) ack_ repl_hdr - > session_id = htobe32 ( conn - > session_id ) ;
* ( uint32_t * ) res p - > session_id = htobe32 ( conn - > session_id ) ;
ack_ repl_hdr - > mtu [ 0 ] = link - > mtu_local > > 8 ;
res p - > mtu [ 0 ] = link - > mtu_local > > 8 ;
ack_ repl_hdr - > mtu [ 1 ] = link - > mtu_local ;
res p - > mtu [ 1 ] = link - > mtu_local ;
ack_ repl_hdr - > link_id = link - > local_link_id ;
res p - > link_id = link - > local_link_id ;
ack_ repl_hdr - > remote_socket_id = ack_hd r- > remote_ socket_id;
res p - > remote_socket_id = req - > socket_id ;
ack_ repl_hdr - > only_local = e_sock - > only_local ;
res p - > only_local = e_sock - > only_local ;
ack_ repl_hdr - > type = e_sock - > type ;
res p - > type = e_sock - > type ;
// Add client's IP:port (so client behind NAT can know its external address)
// Add client's IP:port (so client behind NAT can know its external address)
if ( addr . ss_family = = AF_INET ) {
if ( addr . ss_family = = AF_INET ) {
struct sockaddr_in * sin = ( struct sockaddr_in * ) & addr ;
struct sockaddr_in * sin = ( struct sockaddr_in * ) & addr ;
memcpy ( ack_ repl_hdr - > peer_ipv4 , & sin - > sin_addr . s_addr , 4 ) ;
memcpy ( res p - > peer_ipv4 , & sin - > sin_addr . s_addr , 4 ) ;
uint16_t port = ntohs ( sin - > sin_port ) ;
uint16_t port = ntohs ( sin - > sin_port ) ;
ack_ repl_hdr - > peer_port [ 0 ] = port > > 8 ;
res p - > peer_port [ 0 ] = port > > 8 ;
ack_ repl_hdr - > peer_port [ 1 ] = port & 0xFF ;
res p - > peer_port [ 1 ] = port & 0xFF ;
link - > nat_ip = sin - > sin_addr . s_addr ;
link - > nat_ip = sin - > sin_addr . s_addr ;
link - > nat_port = port ;
link - > nat_port = port ;
} else {
} else {
// For IPv6, set to 0 (not supported for NAT traversal)
// For IPv6, set to 0 (not supported for NAT traversal)
memset ( ack_ repl_hdr - > peer_ipv4 , 0 , 4 ) ;
memset ( res p - > peer_ipv4 , 0 , 4 ) ;
memset ( ack_ repl_hdr - > peer_port , 0 , 2 ) ;
memset ( res p - > peer_port , 0 , 2 ) ;
link - > nat_ip = 0 ;
link - > nat_ip = 0 ;
link - > nat_port = 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 - > noencrypt_len = 0 ;
pkt - > link = link ;
pkt - > link = link ;
link - > recv_keepalive = 1 ;
link - > recv_keepalive = 1 ;
link - > last_recv_local_time = get_time_tb ( ) ;
link - > last_recv_local_time = get_time_tb ( ) ;
link - > last_recv_timestamp = pkt - > timestamp ;
link - > last_recv_timestamp = pkt - > timestamp ;
int xoffset = sizeof ( * ack_repl_hdr ) ;
int xoffset = sizeof ( struct ETCP_INIT_RESPONSE_PKT ) ;
// padding
// padding
int s = rand ( ) % ( link - > handshake_maxsize - link - > handshake_minsize ) + link - > handshake_minsize ;
int s = rand ( ) % ( link - > handshake_maxsize - link - > handshake_minsize ) + link - > handshake_minsize ;
if ( s > ( int ) ( link - > mtu ) ) s = ( int ) ( link - > mtu ) ;
if ( s > ( int ) ( link - > mtu ) ) s = ( int ) ( link - > mtu ) ;
@ -1625,9 +1614,9 @@ process_decrypted:
link - > total_decrypted + = pkt - > data_len ;
link - > total_decrypted + = pkt - > data_len ;
size_t offset = 0 ;
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 ) {
if ( pkt - > data_len > = 3 ) {
uint16_t peer_period = pkt - > data [ 1 ] | ( ( uint16_t ) pkt - > data [ 2 ] < < 8 ) ;
uint16_t peer_period = pkt - > data [ 1 ] | ( ( uint16_t ) pkt - > data [ 2 ] < < 8 ) ;
link - > keepalive_timeout = ( uint32_t ) peer_period * KA_TIMEOUT_MULT ;
link - > keepalive_timeout = ( uint32_t ) peer_period * KA_TIMEOUT_MULT ;
@ -1637,16 +1626,13 @@ process_decrypted:
return ; // KA handled, nothing more to process
return ; // KA handled, nothing more to process
}
}
if ( code = = ETCP_INIT_RESPONSE | | code = = ETCP_INIT_RESPONSE_NOINIT ) {
if ( pkt_ code = = ETCP_INIT_RESPONSE | | pkt_ 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_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 (0x03) - reset entire ETCP_CONN
// ETCP_INIT_RESPONSE_NOINIT (0x05) - no reset
// ETCP_INIT_RESPONSE_NOINIT (0x05) - no reset
uint64_t server_node_id = 0 ;
struct ETCP_INIT_RESPONSE_PKT * resp = ( struct ETCP_INIT_RESPONSE_PKT * ) pkt - > data ;
for ( int i = 0 ; i < 8 ; i + + ) {
uint64_t server_node_id = be64toh ( * ( uint64_t * ) resp - > node_id ) ;
server_node_id = ( server_node_id < < 8 ) | pkt - > data [ offset + + ] ;
uint32_t resp_session_id = be32toh ( * ( uint32_t * ) resp - > session_id ) ;
}
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 ;
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " INIT_RESPONSE session_id=%08x " , 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
// Check session_id: ignore response if it doesn't match our session
if ( resp_session_id ! = link - > etcp - > session_id ) {
if ( resp_session_id ! = link - > etcp - > session_id ) {
@ -1655,23 +1641,20 @@ process_decrypted:
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
memory_pool_free ( e_sock - > instance - > pkt_pool , pkt ) ;
return ;
return ;
}
}
link - > mtu_remote = ( ( uint16_t ) pkt - > data [ offset ] < < 8 ) | pkt - > data [ offset + 1 ] ;
link - > mtu_remote = be16toh ( * ( uint16_t * ) resp - > mtu ) ;
offset + = 2 ;
if ( link - > mtu_remote > PACKET_DATA_MAX_MTU ) link - > mtu_remote = PACKET_DATA_MAX_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 ;
link - > mtu = link - > mtu_local < link - > mtu_remote ? link - > mtu_local : link - > mtu_remote ;
etcp_update_mtu ( link - > etcp ) ;
etcp_update_mtu ( link - > etcp ) ;
link - > remote_link_id = pkt - > data [ offset + + ] ;
link - > remote_link_id = res p- > link_id ;
link - > remote_socket_id = pkt - > data [ offset + + ] ;
link - > remote_socket_id = res p- > remote_socket_id ;
link - > remote_only_local = pkt - > data [ offset + + ] ;
link - > remote_only_local = res p- > only_local ;
link - > remote_type = pkt - > data [ offset + + ] ;
link - > remote_type = res p- > type ;
// Parse NAT IP:port from response (new format includes 4+2 bytes)
// 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 ;
uint32_t new_nat_ip ;
memcpy ( & new_nat_ip , & pkt - > data [ offset ] , 4 ) ;
memcpy ( & new_nat_ip , resp - > peer_ipv4 , 4 ) ;
offset + = 4 ;
uint16_t new_nat_port = be16toh ( * ( uint16_t * ) resp - > peer_port ) ;
uint16_t new_nat_port = ( pkt - > data [ offset ] < < 8 ) | pkt - > data [ offset + 1 ] ;
offset + = 2 ;
// Check if NAT address changed
// Check if NAT address changed
if ( link - > nat_ip = = 0 & & link - > nat_port = = 0 ) {
if ( link - > nat_ip = = 0 & & link - > nat_port = = 0 ) {
@ -1710,7 +1693,6 @@ process_decrypted:
link - > etcp - > log_name ) ;
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);
// 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 ;
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 ) ;
DEBUG_TRACE ( DEBUG_CATEGORY_CONNECTION , " do reinit 3 %p " , link - > etcp ) ;
etcp_conn_reinit ( link - > etcp ) ;
etcp_conn_reinit ( link - > etcp ) ;
}
}