@ -54,6 +54,7 @@ struct NODE_CONN_DIRECT {
ncd_callback cb ;
void * cb_arg ;
struct NODE_CONN_DIRECT * next ;
void * deliver_up_token ; /* handle uasync_call_soon отложенной доставки UP (для отмены при close) */
} ;
/* ─── forward declarations ─── */
@ -379,9 +380,21 @@ static void ncd_connect_timeout_cb(void* arg) {
static void ncd_deliver_up_cb ( void * arg ) {
struct NODE_CONN_DIRECT * h = ( struct NODE_CONN_DIRECT * ) arg ;
h - > deliver_up_token = NULL ; /* токен consumed — close больше не отменит освобождённый узел */
if ( h - > cb ) h - > cb ( h , NCD_EVENT_UP , h - > cb_arg ) ;
}
/* Планирует отложенную доставку UP и сохраняет токен для возможной отмены при close. */
static void ncd_schedule_deliver_up ( struct UASYNC * ua , struct NODE_CONN_DIRECT * h ) {
h - > deliver_up_token = uasync_call_soon ( ua , h , ncd_deliver_up_cb ) ;
}
/* Отменяет pending-доставку UP (если ещё не сработала). Без этого h освобождается,
* а о т л о ж е н н ы й ncd_deliver_up_cb ч и т а е т freed - п а м я т ь — UAF . */
static void ncd_cancel_deliver_up ( struct NODE_CONN_DIRECT * h , struct UASYNC * ua ) {
if ( h - > deliver_up_token ) { uasync_call_soon_cancel ( ua , h - > deliver_up_token ) ; h - > deliver_up_token = NULL ; }
}
/* ═══════════ FIN_WAIT ═══════════ */
/*
* fin_wait — с о с т о я н и е о ж и д а н и я п о д т в е р ж д е н и я з а к р ы т и я о т п и р а .
@ -573,7 +586,7 @@ int node_conn_direct_open(struct UTUN_INSTANCE* inst, uint64_t node_id,
entry - > handle_count + + ;
* out_handle = h ;
if ( entry - > conn & & entry - > conn - > state = = 1 & & entry - > up ) {
uasync_call_soon ( inst - > ua , h , ncd_deliver_up_cb ) ;
ncd_schedule_deliver_up ( inst - > ua , h ) ;
DEBUG_INFO ( DEBUG_CATEGORY_NCD , " [ncd] open REUSED (ready) node=0x%016llx handles=%d " , ( unsigned long long ) node_id , entry - > handle_count ) ;
} else if ( entry - > timed_out ) {
struct TOPO_NODE * ni = ncd_lookup_node ( inst , node_id ) ;
@ -613,7 +626,7 @@ int node_conn_direct_open(struct UTUN_INSTANCE* inst, uint64_t node_id,
etcp_conn_add_cbk ( conn , ncd_down_cb , entry , ETCP_CBK_EVENT_DOWN ) ;
if ( conn - > state = = 1 & & entry - > up ) {
uasync_call_soon ( inst - > ua , h , ncd_deliver_up_cb ) ;
ncd_schedule_deliver_up ( inst - > ua , h ) ;
DEBUG_INFO ( DEBUG_CATEGORY_NCD , " [ncd] open REUSED new-entry (ready) node=0x%016llx conn=%p " , ( unsigned long long ) node_id , ( void * ) conn ) ;
} else {
{ struct TOPO_NODE * ni = ncd_lookup_node ( inst , node_id ) ;
@ -732,7 +745,7 @@ int node_conn_direct_open_node(struct UTUN_INSTANCE* inst, uint64_t node_id,
entry - > handle_count + + ;
* out_handle = h ;
if ( entry - > conn & & entry - > conn - > state = = 1 & & entry - > up ) {
uasync_call_soon ( inst - > ua , h , ncd_deliver_up_cb ) ;
ncd_schedule_deliver_up ( inst - > ua , h ) ;
DEBUG_INFO ( DEBUG_CATEGORY_NCD , " [ncd] open_node REUSED (ready) node=0x%016llx handles=%d " , ( unsigned long long ) node_id , entry - > handle_count ) ;
} else if ( entry - > timed_out ) {
ncd_revive_entry ( entry , inst , ni , specific_sock ) ;
@ -769,7 +782,7 @@ int node_conn_direct_open_node(struct UTUN_INSTANCE* inst, uint64_t node_id,
etcp_conn_add_cbk ( conn , ncd_down_cb , entry , ETCP_CBK_EVENT_DOWN ) ;
if ( conn - > state = = 1 & & entry - > up ) {
uasync_call_soon ( inst - > ua , h , ncd_deliver_up_cb ) ;
ncd_schedule_deliver_up ( inst - > ua , h ) ;
DEBUG_INFO ( DEBUG_CATEGORY_NCD , " [ncd] open_node REUSED new-entry (ready) node=0x%016llx conn=%p " , ( unsigned long long ) node_id , ( void * ) conn ) ;
} else {
ncd_create_links ( entry , ni , specific_sock ) ;
@ -863,6 +876,7 @@ void node_conn_direct_close(struct NODE_CONN_DIRECT* h) {
if ( ! h ) return ;
struct ncd_entry * entry = h - > entry ;
if ( ! entry ) { u_free ( h ) ; return ; }
ncd_cancel_deliver_up ( h , entry - > ua ) ;
uint64_t node_id = entry - > node_id ;
struct ETCP_CONN * conn = entry - > conn ;
@ -953,6 +967,7 @@ void node_conn_direct_force_close(struct NODE_CONN_DIRECT* h) {
if ( ! h ) return ;
if ( ! h - > entry ) { DEBUG_ERROR ( DEBUG_CATEGORY_NCD , " [ncd] force_close: h=%p h->entry=NULL " , h ) ; u_free ( h ) ; return ; }
struct ncd_entry * entry = h - > entry ;
ncd_cancel_deliver_up ( h , entry - > ua ) ;
DEBUG_INFO ( DEBUG_CATEGORY_NCD , " [ncd] force_close h=%p entry=%p node=0x%016llx handles=%d " ,
h , entry , ( unsigned long long ) entry - > node_id , entry - > handle_count ) ;