@ -33,7 +33,7 @@ static void router_schedule_ack(struct ETCP_ROUTER_CONN* rconn);
static void router_try_assembly ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn ) ;
static void router_try_assembly ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn ) ;
static void router_deliver ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn , const uint8_t * wire , size_t wire_len ) ;
static void router_deliver ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn , const uint8_t * wire , size_t wire_len ) ;
static void router_send_ctrl ( struct ETCP_ROUTER_CONN * rconn , uint8_t flag_bits ) ;
static void router_send_ctrl ( struct ETCP_ROUTER_CONN * rconn , uint8_t flag_bits ) ;
static void router_send_rst ( struct ETCP_ROUTER_CONN * rconn ) ;
static void router_send_rst ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn ) ;
static void router_restart_send ( struct ETCP_ROUTER_CONN * rconn ) ;
static void router_restart_send ( struct ETCP_ROUTER_CONN * rconn ) ;
static struct ETCP_CONN * router_send_conn ( struct ETCP_ROUTER_CONN * rconn ) ;
static struct ETCP_CONN * router_send_conn ( struct ETCP_ROUTER_CONN * rconn ) ;
static void router_send_kick ( struct ETCP_ROUTER_CONN * rconn ) ;
static void router_send_kick ( struct ETCP_ROUTER_CONN * rconn ) ;
@ -50,7 +50,7 @@ static void router_conn_reset(struct ETCP_ROUTER_CONN* rconn);
static void free_entry ( struct ll_entry * e ) { queue_dgram_free ( e ) ; queue_entry_free ( e ) ; }
static void free_entry ( struct ll_entry * e ) { queue_dgram_free ( e ) ; queue_entry_free ( e ) ; }
static void router_handle_ack ( struct UTUN_INSTANCE * inst , struct ETCP_ROUTER_CONN * rconn , uint32_t seq , uint64_t src_node_id , uint16_t ack_ts ) ;
static void router_handle_ack ( struct UTUN_INSTANCE * inst , struct ETCP_ROUTER_CONN * rconn , uint32_t seq , uint64_t src_node_id , uint16_t ack_ts ) ;
static void router_forward_transit ( struct UTUN_INSTANCE * inst , struct ll_entry * entry , struct SVC_ROUTE_HDR * hdr ) ;
static void router_forward_transit ( struct UTUN_INSTANCE * inst , struct ll_entry * entry , struct SVC_ROUTE_HDR * hdr ) ;
static int router_check_peer_restart ( struct UTUN_INSTANCE * inst , struct ETCP_ROUTER_CONN * * prconn , struct SVC_ROUTE_HDR * hdr , size_t wire_len ) ;
static int router_check_peer_restart ( struct UTUN_INSTANCE * inst , struct ETCP_ROUTER_CONN * * prconn , struct SVC_ROUTE_HDR * hdr , size_t wire_len , struct ETCP_CONN * conn ) ;
static void router_handle_data_packet ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn , uint32_t seq , const uint8_t * wire , size_t wire_len ) ;
static void router_handle_data_packet ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn , uint32_t seq , const uint8_t * wire , size_t wire_len ) ;
static void router_retransmit_one ( struct ETCP_ROUTER_CONN * rconn , struct ROUTER_INFLIGHT * inf ) ;
static void router_retransmit_one ( struct ETCP_ROUTER_CONN * rconn , struct ROUTER_INFLIGHT * inf ) ;
static void router_retrans_schedule ( struct ETCP_ROUTER_CONN * rconn ) ;
static void router_retrans_schedule ( struct ETCP_ROUTER_CONN * rconn ) ;
@ -153,6 +153,27 @@ void etcp_router_transit_queues_destroy(struct ETCP_CONN* conn) {
conn - > transit_queues = NULL ;
conn - > transit_queues = NULL ;
}
}
// Сбросить recv_conn у всех ROUTER_CONN, ссылающихся на уничтожаемый ETCP_CONN.
// recv_conn — заимствованный указатель; без очистки он висит после u_free(conn) (UAF).
void etcp_router_conn_destroyed ( struct ETCP_CONN * conn ) {
if ( ! conn | | ! conn - > instance | | ! conn - > instance - > router_conns ) return ;
struct ll_queue * q = conn - > instance - > router_conns ;
for ( uint32_t slot = 0 ; slot < q - > hash_size ; slot + + ) {
struct ll_entry * entry = q - > hash_table [ slot ] ;
while ( entry ) {
struct ll_entry * next = entry - > hash_next ;
struct ETCP_ROUTER_CONN * rconn = ( struct ETCP_ROUTER_CONN * ) entry ;
if ( rconn - > recv_conn = = conn ) {
DEBUG_DEBUG ( DEBUG_CATEGORY_ETCPROUTE ,
" router: clear recv_conn remote=%016llx svc_id=%u (conn destroyed) " ,
( unsigned long long ) rconn - > remote_node_id , rconn - > svc_id ) ;
rconn - > recv_conn = NULL ;
}
entry = next ;
}
}
}
// ====================================================================
// ====================================================================
// Управление ROUTER_CONN
// Управление ROUTER_CONN
// ====================================================================
// ====================================================================
@ -251,10 +272,9 @@ static void router_send_ctrl(struct ETCP_ROUTER_CONN* rconn, uint8_t flag_bits)
}
}
// Отправка RST удалённой стороне — сброс чужой «старой» сессии.
// Отправка RST удалённой стороне — сброс чужой «старой» сессии.
// Идёт через recv_conn: в асимметричной топологии route-lookup до remote вернёт NULL .
// conn — живой физический conn, доставивший пакет (recv_conn может быть уже устаревшим) .
static void router_send_rst ( struct ETCP_ROUTER_CONN * rconn ) {
static void router_send_rst ( struct ETCP_ROUTER_CONN * rconn , struct ETCP_CONN * conn ) {
struct UTUN_INSTANCE * inst = rconn - > inst ;
struct UTUN_INSTANCE * inst = rconn - > inst ;
struct ETCP_CONN * conn = rconn - > recv_conn ;
if ( ! conn ) conn = topo_group_find_conn_for_node ( topo_groups_find ( inst - > topo_groups , rconn - > group_id ) , rconn - > remote_node_id ) ;
if ( ! conn ) conn = topo_group_find_conn_for_node ( topo_groups_find ( inst - > topo_groups , rconn - > group_id ) , rconn - > remote_node_id ) ;
if ( ! conn ) {
if ( ! conn ) {
DEBUG_WARN ( DEBUG_CATEGORY_ETCPROUTE , " router_rst: no route to %016llx svc_id=%u " ,
DEBUG_WARN ( DEBUG_CATEGORY_ETCPROUTE , " router_rst: no route to %016llx svc_id=%u " ,
@ -1069,7 +1089,7 @@ static void router_forward_transit(struct UTUN_INSTANCE* inst, struct ll_entry*
}
}
static int router_check_peer_restart ( struct UTUN_INSTANCE * inst , struct ETCP_ROUTER_CONN * * prconn ,
static int router_check_peer_restart ( struct UTUN_INSTANCE * inst , struct ETCP_ROUTER_CONN * * prconn ,
struct SVC_ROUTE_HDR * hdr , size_t wire_len ) {
struct SVC_ROUTE_HDR * hdr , size_t wire_len , struct ETCP_CONN * conn ) {
( void ) wire_len ;
( void ) wire_len ;
struct ETCP_ROUTER_CONN * rconn = * prconn ;
struct ETCP_ROUTER_CONN * rconn = * prconn ;
if ( ! ( hdr - > flags & ROUTER_FLAG_START ) ) return 0 ; // не START — не рестарт
if ( ! ( hdr - > flags & ROUTER_FLAG_START ) ) return 0 ; // не START — не рестарт
@ -1091,7 +1111,7 @@ static int router_check_peer_restart(struct UTUN_INSTANCE* inst, struct ETCP_ROU
" router: peer reset_id=%016llx != mine=%016llx — master keeps epoch, RST to %016llx svc_id=%u " ,
" router: peer reset_id=%016llx != mine=%016llx — master keeps epoch, RST to %016llx svc_id=%u " ,
( unsigned long long ) peer_rid , ( unsigned long long ) rconn - > reset_id ,
( unsigned long long ) peer_rid , ( unsigned long long ) rconn - > reset_id ,
( unsigned long long ) hdr - > src_node_id , hdr - > svc_id ) ;
( unsigned long long ) hdr - > src_node_id , hdr - > svc_id ) ;
router_send_rst ( rconn ) ;
router_send_rst ( rconn , conn ) ;
return 0 ;
return 0 ;
} else {
} else {
// slave принимает эпоху мастера и ресетится.
// slave принимает эпоху мастера и ресетится.
@ -1207,11 +1227,11 @@ static void etcp_router_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry)
rconn = etcp_router_conn_get ( inst , hdr - > group_id , hdr - > src_node_id , hdr - > svc_id ) ;
rconn = etcp_router_conn_get ( inst , hdr - > group_id , hdr - > src_node_id , hdr - > svc_id ) ;
if ( ! rconn ) { free_entry ( entry ) ; return ; }
if ( ! rconn ) { free_entry ( entry ) ; return ; }
}
}
if ( router_check_peer_restart ( inst , & rconn , hdr , entry - > len ) ! = 0 ) { free_entry ( entry ) ; return ; }
if ( router_check_peer_restart ( inst , & rconn , hdr , entry - > len , conn ) ! = 0 ) { free_entry ( entry ) ; return ; }
// Сервер после рестарта «ждёт START»: пришёл не-START пакет от старой сессии → RST.
// Сервер после рестарта «ждёт START»: пришёл не-START пакет от старой сессии → RST.
if ( ! rconn - > peer_sync_done & & ! ( hdr - > flags & ROUTER_FLAG_START ) ) {
if ( ! rconn - > peer_sync_done & & ! ( hdr - > flags & ROUTER_FLAG_START ) ) {
router_send_rst ( rconn ) ;
router_send_rst ( rconn , conn ) ;
free_entry ( entry ) ; return ;
free_entry ( entry ) ; return ;
}
}