diff --git a/src/transport_layer/stun_nat.c b/src/transport_layer/stun_nat.c index b91a5af3..9fa18cf2 100644 --- a/src/transport_layer/stun_nat.c +++ b/src/transport_layer/stun_nat.c @@ -744,6 +744,7 @@ static void scan_sources(struct STUN_NAT* mod) { p->ports = u_calloc(1, sizeof(*p->ports)); if (!p->ports) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "STUN port history allocation failed"); u_free(p); continue; } p->ports->key = source.key; p->ports->next = mod->ports; mod->ports = p->ports; + mod->inst->stun_port_history = mod->ports; } p->fd = SOCKET_INVALID; p->next = mod->probes; @@ -790,6 +791,7 @@ int stun_nat_init(struct UTUN_INSTANCE* inst) { struct STUN_NAT* mod = u_calloc(1, sizeof(*mod)); if (!mod) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "STUN module allocation failed"); return -1; } mod->inst = inst; + mod->ports = inst->stun_port_history; inst->stun_nat = mod; DEBUG_INFO(DEBUG_CATEGORY_NAT, "STUN initialized with %d servers; independent test sockets", inst->config->global.stun_server_count); scan_timer(mod); @@ -803,11 +805,19 @@ void stun_nat_destroy(struct UTUN_INSTANCE* inst) { inst->stun_nat = NULL; if (mod->scan_timer) uasync_cancel_timeout(inst->ua, mod->scan_timer); while (mod->probes) { struct stun_probe* next = mod->probes->next; destroy_probe(mod->probes); mod->probes = next; } - while (mod->ports) { struct stun_ports* next = mod->ports->next; u_free(mod->ports); mod->ports = next; } DEBUG_INFO(DEBUG_CATEGORY_NAT, "STUN destroyed; test sockets/DNS/timers released"); u_free(mod); } +void stun_nat_forget_ports(struct UTUN_INSTANCE* inst) { + if (!inst) return; + if (inst->stun_nat) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "STUN port history release requires stopped module"); return; } + while (inst->stun_port_history) { + struct stun_ports* next = inst->stun_port_history->next; + u_free(inst->stun_port_history); inst->stun_port_history = next; + } +} + void stun_nat_recheck(struct UTUN_INSTANCE* inst) { if (!inst || !inst->stun_nat) return; struct STUN_NAT* mod = inst->stun_nat; diff --git a/src/transport_layer/stun_nat.h b/src/transport_layer/stun_nat.h index 87efb3c3..79f7fd9a 100644 --- a/src/transport_layer/stun_nat.h +++ b/src/transport_layer/stun_nat.h @@ -55,6 +55,8 @@ struct stun_nat_result { * destroy отменяет DNS/таймеры и закрывает только собственные UDP-сокеты. */ int stun_nat_init(struct UTUN_INSTANCE* inst); void stun_nat_destroy(struct UTUN_INSTANCE* inst); +/* История портов живёт до destroy ядра, переживает reload STUN. Вызывать после destroy. */ +void stun_nat_forget_ports(struct UTUN_INSTANCE* inst); /* Явно повторяет измерения на свежих тестовых сокетах после изменения сети. */ void stun_nat_recheck(struct UTUN_INSTANCE* inst); /* Копирует результат для имени исходного сокета; -1 если модуль выключен/имя отсутствует. */ diff --git a/src/utun_instance.h b/src/utun_instance.h index d7e827db..ce089d97 100644 --- a/src/utun_instance.h +++ b/src/utun_instance.h @@ -142,6 +142,7 @@ struct UTUN_INSTANCE { sqlite3* topo_sqlite_db; // Shared SQLite DB (nodes/channels/peers) struct NAT_DETECTION* nat_det; // NAT detection module struct STUN_NAT* stun_nat; // независимая локальная STUN-диагностика UDP + struct stun_ports* stun_port_history; // ранее использованные STUN-порты; переживает reload config struct merkle_sync* msync; // Merkle tree sync module (per-instance) // Identification