Диагностика коллизии линков + детектор дубликата node_id + reality-конфиг autogen
This commit is contained in:
1 parent
c2882c533e
commit
d886a2ff84
10 files changed
+487
-24
No files matched your search
+162
-4
@@ -8,6 +8,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -103,6 +104,123 @@ static char* find_option(char *buf, size_t buf_len, const char *option) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Смещение байта сразу после ']' заголовка секции "[name]" (регистронезависимо), -1 если нет.
|
||||
static long find_section_header(const char *buf, size_t buf_len, const char *name) {
|
||||
size_t name_len = strlen(name);
|
||||
size_t i = 0;
|
||||
while (i < buf_len) {
|
||||
if (buf[i] == '[' && i + name_len + 2 <= buf_len &&
|
||||
strncasecmp(buf + i + 1, name, name_len) == 0 && buf[i + name_len + 1] == ']') {
|
||||
return (long)(i + name_len + 2);
|
||||
}
|
||||
const char *nl = memchr(buf + i, '\n', buf_len - i);
|
||||
if (!nl) break;
|
||||
i = (size_t)(nl - buf) + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Смещение строки, начинающейся с "option=", в диапазоне [start, end), -1 если нет.
|
||||
static long find_option_in_range(const char *buf, size_t start, size_t end, const char *option) {
|
||||
size_t olen = strlen(option);
|
||||
size_t i = start;
|
||||
while (i < end) {
|
||||
if (i + olen <= end && strncmp(buf + i, option, olen) == 0 && buf[i + olen] == '=') {
|
||||
return (long)i;
|
||||
}
|
||||
const char *nl = memchr(buf + i, '\n', end - i);
|
||||
if (!nl) break;
|
||||
i = (size_t)(nl - buf) + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Заменить строку option=value внутри секции [section], либо вставить её сразу после
|
||||
// строки заголовка секции (без пустых строк). Возвращает 0 / -1.
|
||||
static int insert_or_replace_in_section(char **buf, size_t *buf_len, size_t *buf_capacity,
|
||||
const char *section, const char *option, const char *value) {
|
||||
if (!buf || !*buf || !buf_len || !buf_capacity || !section || !option || !value) return -1;
|
||||
|
||||
long hdr_off = find_section_header(*buf, *buf_len, section);
|
||||
if (hdr_off < 0) return -1;
|
||||
size_t sec_start = (size_t)hdr_off;
|
||||
|
||||
char *next_sec = memchr(*buf + sec_start, '[', *buf_len - sec_start);
|
||||
size_t sec_end = next_sec ? (size_t)(next_sec - *buf) : *buf_len;
|
||||
|
||||
long opt_off = find_option_in_range(*buf, sec_start, sec_end, option);
|
||||
|
||||
if (opt_off >= 0) {
|
||||
size_t opos = (size_t)opt_off;
|
||||
char *nl = memchr(*buf + opos, '\n', sec_end - opos);
|
||||
int has_trailing_nl = (nl != NULL);
|
||||
size_t line_end = nl ? (size_t)(nl - *buf) + 1 : sec_end;
|
||||
size_t old_len = line_end - opos;
|
||||
|
||||
char new_line[MAX_LINE_LEN];
|
||||
int new_len = snprintf(new_line, sizeof(new_line), "%s=%s%s", option, value, has_trailing_nl ? "\n" : "");
|
||||
if (new_len <= 0 || new_len >= (int)sizeof(new_line)) return -1;
|
||||
|
||||
long len_diff = (long)new_len - (long)old_len;
|
||||
if ((long)*buf_len + len_diff + 1 > (long)*buf_capacity) {
|
||||
*buf_capacity = *buf_len + len_diff + 1024;
|
||||
char *new_buf = u_realloc(*buf, *buf_capacity);
|
||||
if (!new_buf) return -1;
|
||||
*buf = new_buf;
|
||||
hdr_off = find_section_header(*buf, *buf_len, section);
|
||||
if (hdr_off < 0) return -1;
|
||||
sec_start = (size_t)hdr_off;
|
||||
next_sec = memchr(*buf + sec_start, '[', *buf_len - sec_start);
|
||||
sec_end = next_sec ? (size_t)(next_sec - *buf) : *buf_len;
|
||||
opt_off = find_option_in_range(*buf, sec_start, sec_end, option);
|
||||
if (opt_off < 0) return -1;
|
||||
opos = (size_t)opt_off;
|
||||
nl = memchr(*buf + opos, '\n', sec_end - opos);
|
||||
has_trailing_nl = (nl != NULL);
|
||||
line_end = nl ? (size_t)(nl - *buf) + 1 : sec_end;
|
||||
}
|
||||
|
||||
memmove(*buf + opos + new_len, *buf + line_end, *buf_len - line_end + 1);
|
||||
memcpy(*buf + opos, new_line, new_len);
|
||||
*buf_len += len_diff;
|
||||
} else {
|
||||
size_t ins = sec_start;
|
||||
int need_leading_nl = 0;
|
||||
if (ins < *buf_len && (*buf)[ins] == '\n') {
|
||||
ins += 1;
|
||||
} else {
|
||||
need_leading_nl = 1;
|
||||
}
|
||||
|
||||
char new_line[MAX_LINE_LEN];
|
||||
int new_len = snprintf(new_line, sizeof(new_line), "%s%s=%s\n", need_leading_nl ? "\n" : "", option, value);
|
||||
if (new_len <= 0 || new_len >= (int)sizeof(new_line)) return -1;
|
||||
|
||||
if (*buf_len + (size_t)new_len + 1 > *buf_capacity) {
|
||||
*buf_capacity = *buf_len + (size_t)new_len + 1024;
|
||||
char *new_buf = u_realloc(*buf, *buf_capacity);
|
||||
if (!new_buf) return -1;
|
||||
*buf = new_buf;
|
||||
hdr_off = find_section_header(*buf, *buf_len, section);
|
||||
if (hdr_off < 0) return -1;
|
||||
ins = (size_t)hdr_off;
|
||||
need_leading_nl = 0;
|
||||
if (ins < *buf_len && (*buf)[ins] == '\n') {
|
||||
ins += 1;
|
||||
} else {
|
||||
need_leading_nl = 1;
|
||||
}
|
||||
new_len = snprintf(new_line, sizeof(new_line), "%s%s=%s\n", need_leading_nl ? "\n" : "", option, value);
|
||||
if (new_len <= 0 || new_len >= (int)sizeof(new_line)) return -1;
|
||||
}
|
||||
|
||||
memmove(*buf + ins + new_len, *buf + ins, *buf_len - ins + 1);
|
||||
memcpy(*buf + ins, new_line, new_len);
|
||||
*buf_len += new_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int insert_or_replace_option(char **buf, size_t *buf_len, size_t *buf_capacity, const char *option, const char *value) {
|
||||
if (!buf || !*buf || !buf_len || !buf_capacity || !option || !value) return -1;
|
||||
|
||||
@@ -301,10 +419,42 @@ int config_ensure_keys_and_node_id(const char *filename) {
|
||||
(unsigned long long)global->my_node_id, (unsigned long long)new_node_id, filename);
|
||||
}
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CONFIG, "Validation results - need_priv_key=%d, need_pub_key=%d, need_node_id=%d",
|
||||
need_priv_key, need_pub_key, need_node_id);
|
||||
// ── Step 4: reality-камуфляж — private_key и short_ids при enabled=1 ──
|
||||
int need_reality_priv = 0, need_reality_ids = 0;
|
||||
char new_reality_priv_hex[REALITY_AUTH_KEY_SIZE * 2 + 1] = {0};
|
||||
char new_short_ids_str[4 * (REALITY_SHORT_ID_SIZE * 2) + 4] = {0};
|
||||
|
||||
if (!need_priv_key && !need_pub_key && !need_node_id) { free_config(config); u_free(file_buf); return 0; }
|
||||
if (global->reality.enabled) {
|
||||
if (!global->reality.has_private_key) {
|
||||
need_reality_priv = 1;
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Reality private_key missing, generating new one in %s", filename);
|
||||
uint8_t rpriv[REALITY_AUTH_KEY_SIZE], rpub[REALITY_AUTH_KEY_SIZE];
|
||||
if (reality_generate_keypair(rpriv, rpub) != REALITY_OK) { free_config(config); u_free(file_buf); return -1; }
|
||||
bytes_to_hex(rpriv, REALITY_AUTH_KEY_SIZE, new_reality_priv_hex, sizeof(new_reality_priv_hex));
|
||||
}
|
||||
if (global->reality.short_id_count == 0) {
|
||||
need_reality_ids = 1;
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Reality short_ids missing, generating 4 ids in %s", filename);
|
||||
char *p = new_short_ids_str;
|
||||
size_t remain = sizeof(new_short_ids_str);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uint8_t sid[REALITY_SHORT_ID_SIZE];
|
||||
if (random_bytes(sid, sizeof(sid)) != 0) { free_config(config); u_free(file_buf); return -1; }
|
||||
char hex[REALITY_SHORT_ID_SIZE * 2 + 1];
|
||||
bytes_to_hex(sid, REALITY_SHORT_ID_SIZE, hex, sizeof(hex));
|
||||
int w = snprintf(p, remain, "%s%s", i ? "," : "", hex);
|
||||
if (w < 0 || (size_t)w >= remain) { free_config(config); u_free(file_buf); return -1; }
|
||||
p += w; remain -= (size_t)w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CONFIG, "Validation results - need_priv_key=%d, need_pub_key=%d, need_node_id=%d, need_reality_priv=%d, need_reality_ids=%d",
|
||||
need_priv_key, need_pub_key, need_node_id, need_reality_priv, need_reality_ids);
|
||||
|
||||
if (!need_priv_key && !need_pub_key && !need_node_id && !need_reality_priv && !need_reality_ids) {
|
||||
free_config(config); u_free(file_buf); return 0;
|
||||
}
|
||||
|
||||
char cfg_name[MAX_CONN_NAME_LEN]; snprintf(cfg_name, sizeof(cfg_name), "%s", global->name[0] ? global->name : "utun");
|
||||
|
||||
@@ -351,6 +501,14 @@ int config_ensure_keys_and_node_id(const char *filename) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing my_public_key to %s", filename);
|
||||
if (insert_or_replace_option(&work_buf, &work_len, &buf_capacity, "my_public_key", new_pub_key) < 0) ret = -1;
|
||||
}
|
||||
if (need_reality_ids && ret == 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing reality short_ids to %s", filename);
|
||||
if (insert_or_replace_in_section(&work_buf, &work_len, &buf_capacity, "reality", "short_ids", new_short_ids_str) < 0) ret = -1;
|
||||
}
|
||||
if (need_reality_priv && ret == 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Writing reality private_key to %s", filename);
|
||||
if (insert_or_replace_in_section(&work_buf, &work_len, &buf_capacity, "reality", "private_key", new_reality_priv_hex) < 0) ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0 && work_buf) {
|
||||
@@ -358,7 +516,7 @@ int config_ensure_keys_and_node_id(const char *filename) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to write updated config file: %s", filename);
|
||||
ret = -1;
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Config file updated: %s (gen_priv=%d gen_pub=%d gen_nodeid=%d)", filename, need_priv_key, need_pub_key, need_node_id);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "Config file updated: %s (gen_priv=%d gen_pub=%d gen_nodeid=%d gen_reality_priv=%d gen_reality_ids=%d)", filename, need_priv_key, need_pub_key, need_node_id, need_reality_priv, need_reality_ids);
|
||||
}
|
||||
}
|
||||
u_free(work_buf);
|
||||
|
||||
@@ -102,10 +102,21 @@ uint8_t cm_sock_v6_classify(const struct ETCP_SOCKET* s) {
|
||||
return cm_classify_v6_addr(a6);
|
||||
}
|
||||
|
||||
static void cm_warn_addr_busy(struct ETCP_CONN* conn, struct ETCP_SOCKET* s, struct sockaddr_storage* sa) {
|
||||
struct ETCP_LINK* st = etcp_link_find_by_addr(s, sa, 0);
|
||||
if (st && st->etcp != conn) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "conn_mgr: addr %s busy by [%s] state=%d init=%d up=%d (adding for [%s] state=%d)",
|
||||
sockaddr_storage_to_str(sa).str,
|
||||
st->etcp->log_name, st->etcp->state, st->etcp->initialized, st->etcp->links_up,
|
||||
conn->log_name, conn->state);
|
||||
}
|
||||
}
|
||||
|
||||
void cm_add_v4_link(struct ETCP_CONN* conn, const uint8_t* addr, uint16_t port, struct ETCP_SOCKET* s) {
|
||||
struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET;
|
||||
memcpy(&sin.sin_addr.s_addr, addr, 4); sin.sin_port = port;
|
||||
struct sockaddr_storage sa; memcpy(&sa, &sin, sizeof(sin));
|
||||
cm_warn_addr_busy(conn, s, &sa);
|
||||
etcp_link_new(conn, s, &sa, 0);
|
||||
}
|
||||
|
||||
@@ -114,6 +125,7 @@ void cm_add_v6_link(struct ETCP_CONN* conn, const uint8_t addr[16], uint16_t por
|
||||
memcpy(&sin6.sin6_addr, addr, 16); sin6.sin6_port = htons(port);
|
||||
if (cm_classify_v6_addr(addr) == CM_V6_LL) sin6.sin6_scope_id = s->netif_index;
|
||||
struct sockaddr_storage sa; memcpy(&sa, &sin6, sizeof(sin6));
|
||||
cm_warn_addr_busy(conn, s, &sa);
|
||||
etcp_link_new(conn, s, &sa, 0);
|
||||
}
|
||||
|
||||
@@ -555,6 +567,7 @@ static void cm_direct_add_links(struct ETCP_CONN* conn, struct CONN_MGR_ENTRY* e
|
||||
if (m->id != a->socket_id) continue;
|
||||
struct ETCP_SOCKET* s = entry->mgr->instance->etcp_sockets;
|
||||
while (s) { if (cm_nat_compatible(s, m->config_type, m->nat_type) && s->local_addr.ss_family == AF_INET) {
|
||||
cm_warn_addr_busy(conn, s, &sa);
|
||||
if (etcp_link_new(conn, s, &sa, 0)) { any = 1; v4_cnt++; } } s = s->next; }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -689,6 +689,16 @@ void etcp_conn_queue_set_ready(struct ETCP_CONN* conn) {
|
||||
queue_entry_free(conn->conn_queue_entry);
|
||||
}
|
||||
|
||||
struct ll_entry* existing = queue_find_data_by_index(conn->instance->connections, (const uint8_t*)&conn->peer_node_id);
|
||||
if (existing) {
|
||||
struct conn_queue_entry* ece = (struct conn_queue_entry*)existing->data;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP,
|
||||
"[%s] queue_set_ready: DUPLICATE node_id key=0x%016llx already indexed by [%s] conn=%p state=%d (this=%p)",
|
||||
conn->log_name, (unsigned long long)conn->peer_node_id,
|
||||
ece->conn ? ece->conn->log_name : "?", (void*)(ece->conn),
|
||||
ece->conn ? ece->conn->state : -1, (void*)conn);
|
||||
}
|
||||
|
||||
struct ll_entry* qe = queue_entry_new(sizeof(struct conn_queue_entry));
|
||||
if (!qe) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[%s] failed to alloc queue entry for ready", conn->log_name); return; }
|
||||
struct conn_queue_entry* ce = (struct conn_queue_entry*)qe->data;
|
||||
@@ -1282,8 +1292,8 @@ struct ETCP_DGRAM* etcp_request_pkt(struct ETCP_CONN* etcp) {
|
||||
link->last_recv_updated=0;
|
||||
if (dt<1000000) {
|
||||
dgram->data[ptr++]=ETCP_SECTION_TIMESTAMP;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "[%s] KA-TX: ts_section dt=%llu tcp=%d",
|
||||
link->etcp->log_name, (unsigned long long)dt, dgram->link->is_tcp);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_KEEPALIVE, "[%s] KA-TX: ts_section dt=%llu tcp=%d",
|
||||
link->etcp->log_name, (unsigned long long)dt, dgram->link->is_tcp);
|
||||
|
||||
uint16_t t=link->last_recv_timestamp + dt;
|
||||
dgram->data[ptr++]=t;
|
||||
@@ -1574,8 +1584,8 @@ void etcp_conn_input(struct ETCP_DGRAM* pkt) {
|
||||
uint16_t ret_ts=data[1] | (data[2]<<8);// cur_ts=ret_ts = RTT
|
||||
uint16_t new_rtt=cur_ts-ret_ts;
|
||||
pkt->link->rtt_last=new_rtt;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "[%s] KA-RTT: rtt=%u cur=%u ret=%u dlen=%u",
|
||||
etcp->log_name, new_rtt, cur_ts, ret_ts, pkt->data_len);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_KEEPALIVE, "[%s] KA-RTT: rtt=%u cur=%u ret=%u dlen=%u",
|
||||
etcp->log_name, new_rtt, cur_ts, ret_ts, pkt->data_len);
|
||||
|
||||
int recv_dt_tx1=data[3] | (data[4]<<8);// localtime удаленной стороны момента принятия пакета - timestamp этого пакета (на стороне отправителя, т.е. у нас)
|
||||
|
||||
|
||||
@@ -332,12 +332,23 @@ static int insert_link_queue(struct ETCP_SOCKET* e_sock, struct ETCP_LINK* link)
|
||||
if (dup_qe) {
|
||||
struct link_queue_entry* dup_lqe = (struct link_queue_entry*)dup_qe->data;
|
||||
if (dup_lqe->link && dup_lqe->link->etcp != link->etcp) {
|
||||
struct ETCP_CONN* new_c = link->etcp;
|
||||
struct ETCP_CONN* old_c = dup_lqe->link->etcp;
|
||||
uint64_t new_qkey = 0, old_qkey = 0;
|
||||
if (new_c->conn_queue_entry) new_qkey = ((struct conn_queue_entry*)new_c->conn_queue_entry->data)->peer_node_id;
|
||||
if (old_c->conn_queue_entry) old_qkey = ((struct conn_queue_entry*)old_c->conn_queue_entry->data)->peer_node_id;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONNECTION,
|
||||
"!!!!!!!!!!!! LINK ADDR COLLISION !!!!!!!!!!!! "
|
||||
"addr=%s new_conn=%s(peer=0x%016llx) already_used_by=%s(peer=0x%016llx)",
|
||||
"!!!!!!!!!!!! LINK ADDR COLLISION !!!!!!!!!!!! addr=%s "
|
||||
"new: conn=%p [%s] peer=0x%016llx state=%d init=%d up=%d srv=%d tcp=%d qkey=0x%016llx "
|
||||
"old: conn=%p [%s] peer=0x%016llx state=%d init=%d up=%d srv=%d tcp=%d qkey=0x%016llx",
|
||||
sockaddr_storage_to_str(&link->remote_addr).str,
|
||||
link->etcp->log_name, (unsigned long long)link->etcp->peer_node_id,
|
||||
dup_lqe->link->etcp->log_name, (unsigned long long)dup_lqe->link->etcp->peer_node_id);
|
||||
(void*)new_c, new_c->log_name, (unsigned long long)new_c->peer_node_id,
|
||||
new_c->state, new_c->initialized, new_c->links_up, link->is_server, link->is_tcp,
|
||||
(unsigned long long)new_qkey,
|
||||
(void*)old_c, old_c->log_name, (unsigned long long)old_c->peer_node_id,
|
||||
old_c->state, old_c->initialized, old_c->links_up,
|
||||
dup_lqe->link->is_server, dup_lqe->link->is_tcp,
|
||||
(unsigned long long)old_qkey);
|
||||
return -1;
|
||||
}
|
||||
DEBUG_WARN(DEBUG_CATEGORY_CONNECTION, "insert_link_queue: replacing stale DUP addr in [%s] old_link=%p", e_sock->name, dup_lqe->link);
|
||||
@@ -2275,7 +2286,7 @@ int etcp_packet_decrypted(struct ETCP_SOCKET* e_sock, struct ETCP_DGRAM* pkt,
|
||||
pkt->noencrypt_len=0;
|
||||
pkt->link=link;
|
||||
if (pkt->data_len && pkt->data[0] != ETCP_KEEPALIVE) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[%s] decrypt: code=%02x dlen=%u plen=%zu recv=%d sock=%p",
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_CRYPTO, "[%s] decrypt: code=%02x dlen=%u plen=%zu recv=%d sock=%p",
|
||||
link->etcp->log_name, pkt->data[0], pkt->data_len, pkt_len,
|
||||
link->recv_keepalive, (void*)e_sock);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,28 @@ static void ncd_registry_remove(struct UTUN_INSTANCE* inst, struct ncd_entry* en
|
||||
while (*pp) { if (*pp == entry) { *pp = entry->next; return; } pp = &(*pp)->next; }
|
||||
}
|
||||
|
||||
/* TEMP DEBUG: сканирует inst->connections и выводит conn'ы с peer_node_id==node_id,
|
||||
* которые instance_find_conn мог не вернуть (key=0 или дубликат ключа). */
|
||||
static void ncd_debug_scan_conns(struct UTUN_INSTANCE* inst, uint64_t node_id, const char* tag) {
|
||||
struct ll_queue* q = inst->connections;
|
||||
if (!q) { DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] %s node=0x%016llx: connections=NULL", tag, (unsigned long long)node_id); return; }
|
||||
int found = 0;
|
||||
struct ll_entry* e = q->head;
|
||||
while (e) {
|
||||
struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data;
|
||||
if (ce && ce->conn && ce->conn->peer_node_id == node_id) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG,
|
||||
"[ncd] %s node=0x%016llx: conn=%p [%s] state=%d qkey=0x%016llx links=%p up=%d init=%d",
|
||||
tag, (unsigned long long)node_id, (void*)ce->conn, ce->conn->log_name,
|
||||
ce->conn->state, (unsigned long long)ce->peer_node_id, (void*)ce->conn->links,
|
||||
ce->conn->links_up, ce->conn->initialized);
|
||||
found = 1;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
if (!found) DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] %s node=0x%016llx: NO conn in queue", tag, (unsigned long long)node_id);
|
||||
}
|
||||
|
||||
/* ═══════════ поиск узла ═══════════ */
|
||||
/*
|
||||
* Загружает информацию об узле (адреса, pubkey) для создания линков.
|
||||
@@ -145,6 +167,17 @@ static int ncd_add_udp_link(struct ETCP_CONN* conn, struct ETCP_SOCKET* use_sock
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (stale && stale->etcp != conn
|
||||
&& !memcmp(conn->crypto_ctx.peer_public_key, stale->etcp->crypto_ctx.peer_public_key, SC_PUBKEY_SIZE))
|
||||
{
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP,
|
||||
"[ncd] add_udp_link: SAME-PUBKEY DUPLICATE conn at %s — new=%p [%s] state=%d / old=%p [%s] state=%d init=%d up=%d",
|
||||
sockaddr_storage_to_str(sa).str,
|
||||
(void*)conn, conn->log_name, conn->state,
|
||||
(void*)stale->etcp, stale->etcp->log_name, stale->etcp->state,
|
||||
stale->etcp->initialized, stale->etcp->links_up);
|
||||
return 0;
|
||||
}
|
||||
return etcp_link_new(conn, use_sock, sa, 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -602,6 +635,12 @@ int node_conn_direct_open(struct UTUN_INSTANCE* inst, uint64_t node_id,
|
||||
return NCD_REUSED;
|
||||
}
|
||||
|
||||
if (conn) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "[ncd] open node=0x%016llx: instance_find_conn=[%s] state=%d links=%p up=%d — NOT reused (state!=1), creating new",
|
||||
(unsigned long long)node_id, conn->log_name, conn->state, (void*)conn->links, conn->links_up);
|
||||
}
|
||||
ncd_debug_scan_conns(inst, node_id, "open-new");
|
||||
|
||||
/* 3. Новое подключение */
|
||||
struct TOPO_NODE* ni = ncd_lookup_node(inst, node_id);
|
||||
if (!ni) {
|
||||
@@ -756,6 +795,8 @@ int node_conn_direct_open_node(struct UTUN_INSTANCE* inst, uint64_t node_id,
|
||||
return NCD_REUSED;
|
||||
}}
|
||||
|
||||
ncd_debug_scan_conns(inst, node_id, "open_node-new");
|
||||
|
||||
/* 3. Новое подключение — используем переданный ni (временный, не владеем) */
|
||||
{ char conn_name[MAX_CONN_NAME_LEN];
|
||||
if (ni->node_name && ni->node_name[0]) strncpy(conn_name, ni->node_name, MAX_CONN_NAME_LEN - 1);
|
||||
|
||||
Reference in new issue
Block a user