From fc3295ce12e838b928eaca2ec0ec90d6e5fd002c Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 14 Sep 2026 14:37:34 +0300 Subject: [PATCH] =?UTF-8?q?nat=5Fdetection:=20=D0=B3=D0=B0=D1=81=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20NAT-=D1=87=D0=B5=D0=BA=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=BA=D1=80=D1=8B=D1=82=D0=B8=D0=B8=20=D0=BB=D0=B8?= =?UTF-8?q?=D0=BD=D0=BA=D0=B0=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20link-stat?= =?UTF-8?q?us=20=D0=BA=D0=BE=D0=BB=D0=BB=D0=B1=D1=8D=D0=BA=20(UAF=20na->li?= =?UTF-8?q?nk)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routing_layer/nat_detection.c | 13 +++++++++++++ src/routing_layer/route_ping.c | 24 ++++++++++++++++++++++++ src/routing_layer/route_ping.h | 3 +++ 3 files changed, 40 insertions(+) diff --git a/src/routing_layer/nat_detection.c b/src/routing_layer/nat_detection.c index 30f4ed01..886f6c40 100644 --- a/src/routing_layer/nat_detection.c +++ b/src/routing_layer/nat_detection.c @@ -193,6 +193,17 @@ static void nat_detection_on_conn_down(struct ETCP_CONN* conn, int event, void* } } +/* Закрытие ОДНОГО линка (без разрыва conn): etcp_fire_link_status_cbk вызывается + * из etcp_link_close до u_free(link) — здесь link ещё валиден. Гасим NAT-чек этого + * линка, иначе na->link останется висячим указателем. */ +static void nat_detection_on_link_status(struct ETCP_CONN* conn, struct ETCP_LINK* link, + int old_state, int old_status, void* arg) { + (void)conn; (void)old_state; (void)old_status; + struct NAT_DETECTION* nd = (struct NAT_DETECTION*)arg; + if (!nd || !link) return; + if (link->link_status == 0) route_ping_cancel_for_link(nd, link); +} + static void nat_detection_new_conn_cbk(struct ETCP_CONN* conn, void* arg) { if (!conn || !conn->instance) return; struct NAT_DETECTION* nd = (struct NAT_DETECTION*)arg; @@ -273,6 +284,7 @@ struct NAT_DETECTION* nat_detection_create(struct UTUN_INSTANCE* inst) { nd->allow_nat_check_local = 0; etcp_bind(inst, ETCP_ID_NAT_DETECTION, nat_detection_receive_cbk); etcp_add_new_conn_cbk(inst, nat_detection_new_conn_cbk, nd); + etcp_add_link_status_cbk(inst, nat_detection_on_link_status, nd); DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT detection initialized"); return nd; } @@ -281,6 +293,7 @@ void nat_detection_destroy(struct NAT_DETECTION* nd) { if (!nd) return; DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT detection destroy"); etcp_remove_new_conn_cbk(nd->inst, nat_detection_new_conn_cbk, nd); + etcp_remove_link_status_cbk(nd->inst, nat_detection_on_link_status, nd); etcp_unbind(nd->inst, ETCP_ID_NAT_DETECTION); route_ping_destroy_pending(nd); u_free(nd); diff --git a/src/routing_layer/route_ping.c b/src/routing_layer/route_ping.c index 6310e7fc..d40a2619 100644 --- a/src/routing_layer/route_ping.c +++ b/src/routing_layer/route_ping.c @@ -148,6 +148,30 @@ void route_ping_cancel_for_conn(struct NAT_DETECTION* nd, struct ETCP_CONN* conn } } +void route_ping_cancel_for_link(struct NAT_DETECTION* nd, struct ETCP_LINK* link) { + if (!nd || !link) return; + struct route_ping_pending** cur = &nd->ping_pending; + while (*cur) { + struct route_ping_pending* p = *cur; + struct nat_check_arg* na = (struct nat_check_arg*)p->arg; + if (na && na->link == link) { + *cur = p->next; + uint32_t rid = p->request_id; + if (p->timeout_timer) { + uasync_cancel_timeout(nd->inst->ua, p->timeout_timer); + p->timeout_timer = NULL; + } + p->cancelled = 1; + na->link = NULL; + u_free(na); + u_free(p); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "cancel_for_link: cancelled req_id=%08x link=%p", (unsigned)rid, (void*)link); + } else { + cur = &(*cur)->next; + } + } +} + void route_ping_destroy_pending(struct NAT_DETECTION* nd) { if (!nd) return; struct route_ping_pending* p = nd->ping_pending; diff --git a/src/routing_layer/route_ping.h b/src/routing_layer/route_ping.h index f1b83bcc..44ec8f68 100644 --- a/src/routing_layer/route_ping.h +++ b/src/routing_layer/route_ping.h @@ -39,6 +39,9 @@ void route_ping_destroy_pending(struct NAT_DETECTION* nd); /** Отменить pending для conn (при разрыве/реините соединения). */ void route_ping_cancel_for_conn(struct NAT_DETECTION* nd, struct ETCP_CONN* conn); +/** Отменить pending для конкретного линка (при закрытии линка без разрыва conn). */ +void route_ping_cancel_for_link(struct NAT_DETECTION* nd, struct ETCP_LINK* link); + /** Входящий PING_REQ — мы посредник: пингуем цель, шлём PING_RESP. */ void route_ping_handle_req(struct NAT_DETECTION* nd, struct TOPO_GROUP* group, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);