From ca6a27aadb9f35d8c5e7c4040060581fea6c2860 Mon Sep 17 00:00:00 2001 From: Evgeny Date: Sun, 19 Jul 2026 07:00:04 +0300 Subject: [PATCH] BGP: 2 addr per socket (remove TOPO_ADDR_REAL), config IP priority, private IPs in SQLite, NAT addr != INTERFACE --- src/conn_mgr.c | 10 +++++----- src/route_connectivity.c | 20 ++++++++++---------- src/topo_node.c | 21 ++++++++++----------- src/topo_node_sqlite.c | 35 ++++++++++++++++------------------- 4 files changed, 41 insertions(+), 45 deletions(-) diff --git a/src/conn_mgr.c b/src/conn_mgr.c index 4e8ef001..d60d50b2 100644 --- a/src/conn_mgr.c +++ b/src/conn_mgr.c @@ -389,7 +389,7 @@ static int cm_is_rtt_fresh(struct TOPO_NODEQ* nq, uint64_t now_tb) { static int cm_has_direct_ip(struct TOPO_NODEQ* nq) { if (!nq || !nq->node) return 0; for (const struct TOPO_ADDR4* a = nq->node->v4_addrs; a; a = a->next) { - if (a->type == TOPO_ADDR_REAL || a->type == TOPO_ADDR_NAT) { + if (a->type == TOPO_ADDR_NAT || a->type == TOPO_ADDR_INTERFACE) { for (const struct TOPO_SOCKMETA4* m = nq->node->v4_sock_meta; m; m = m->next) { if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PUBLIC || m->config_type == CFG_SERVER_TYPE_UNKNOWN || m->nat_type == NAT_VERIFIED_EIM || m->nat_type == NAT_VERIFIED_DIRECT)) @@ -457,8 +457,8 @@ static void cm_start_phase_direct(struct CONN_MGR_ENTRY* entry) { struct TOPO_GROUP* group = topo_groups_get_default(entry->mgr->instance->topo_groups); struct TOPO_NODEQ* target = topo_node_find_by_id(group, entry->node_id); if (!target || !target->node) { cm_deliver_result(entry, CONN_MGR_ERR_NOT_FOUND); return; } - uint8_t priority_order[] = { TOPO_ADDR_REAL, TOPO_ADDR_NAT, TOPO_ADDR_INTERFACE }; - for (int pri = 0; pri < 3; pri++) { + uint8_t priority_order[] = { TOPO_ADDR_NAT, TOPO_ADDR_INTERFACE }; + for (int pri = 0; pri < 2; pri++) { for (const struct TOPO_ADDR4* a = target->node->v4_addrs; a; a = a->next) { if (a->type != priority_order[pri]) continue; for (const struct TOPO_SOCKMETA4* m = target->node->v4_sock_meta; m; m = m->next) { @@ -562,7 +562,7 @@ static void cm_start_phase_reverse(struct CONN_MGR_ENTRY* entry) { uint8_t direct_count = 0; struct { uint8_t type; uint8_t ip[4]; uint16_t port; uint8_t socket_id; } out_addrs[8]; for (const struct TOPO_ADDR4* a = local->node->v4_addrs; a && direct_count < 8; a = a->next) { - if (a->type != TOPO_ADDR_REAL && a->type != TOPO_ADDR_NAT) continue; + if (a->type != TOPO_ADDR_NAT && a->type != TOPO_ADDR_INTERFACE) continue; for (const struct TOPO_SOCKMETA4* m = local->node->v4_sock_meta; m; m = m->next) { if (m->id == a->socket_id && (m->config_type == CFG_SERVER_TYPE_PUBLIC || m->config_type == CFG_SERVER_TYPE_UNKNOWN || m->nat_type == NAT_VERIFIED_EIM || m->nat_type == NAT_VERIFIED_DIRECT)) { @@ -960,7 +960,7 @@ static void cm_bg_ping_timer_cb(void* arg) { } if (!has_active) { for (const struct TOPO_ADDR4* a = nq->node->v4_addrs; a; a = a->next) { - if (a->type != TOPO_ADDR_REAL && a->type != TOPO_ADDR_NAT) continue; + if (a->type != TOPO_ADDR_NAT && a->type != TOPO_ADDR_INTERFACE) continue; struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; memcpy(&sin.sin_addr.s_addr, a->addr, 4); sin.sin_port = htons(a->port); struct sockaddr_storage sa; memcpy(&sa, &sin, sizeof(sin)); diff --git a/src/route_connectivity.c b/src/route_connectivity.c index ab5706e2..8eb4b71e 100644 --- a/src/route_connectivity.c +++ b/src/route_connectivity.c @@ -116,7 +116,7 @@ static int conn_match_candidate_sockets(struct UTUN_INSTANCE* instance, uint32_t target_ip = ((const struct sockaddr_in*)target_addr)->sin_addr.s_addr; e_sock = instance->etcp_sockets; - // Проход 1: точное совпадение подсети (для INTERFACE) или PUBLIC/NAT_VERIFIED (для NAT/REAL) + // Проход 1: точное совпадение подсети (для INTERFACE) или PUBLIC/NAT_VERIFIED (для NAT) while (e_sock && found < (int)max_count) { if (e_sock->local_addr.ss_family != AF_INET) { e_sock = e_sock->next; continue; } int match = 0; @@ -124,12 +124,13 @@ static int conn_match_candidate_sockets(struct UTUN_INSTANCE* instance, uint32_t if_ip = if_sin->sin_addr.s_addr; if (addr_type == TOPO_ADDR_INTERFACE) { - // предпочитаем PRIVATE/LOCAL сокеты в той же /24 подсети if ((e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) && (if_ip & 0x00FFFFFF) == (target_ip & 0x00FFFFFF)) match = 1; + else if (e_sock->nat_type == NAT_VERIFIED_DIRECT || e_sock->nat_type == NAT_VERIFIED_EIM + || e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) + match = 1; } else { - // NAT или REAL: предпочитаем DIRECT > EIM > PUBLIC/UNKNOWN if (e_sock->nat_type == NAT_VERIFIED_DIRECT) match = 1; else if (e_sock->nat_type == NAT_VERIFIED_EIM) match = 1; else if (e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) match = 1; @@ -151,10 +152,11 @@ static int conn_match_candidate_sockets(struct UTUN_INSTANCE* instance, for (int i = 0; i < found; i++) if (out_sockets[i] == e_sock) { dup = 1; break; } if (!dup) { if (addr_type == TOPO_ADDR_INTERFACE) { - if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL) + if (e_sock->type == CFG_SERVER_TYPE_PRIVATE || e_sock->type == CFG_SERVER_TYPE_LOCAL + || e_sock->nat_type == NAT_VERIFIED_DIRECT || e_sock->nat_type == NAT_VERIFIED_EIM + || e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) out_sockets[found++] = e_sock; } else { - // любой не-private и не-local if (e_sock->type != CFG_SERVER_TYPE_PRIVATE && e_sock->type != CFG_SERVER_TYPE_LOCAL) out_sockets[found++] = e_sock; } @@ -260,17 +262,15 @@ static void conn_probe_finish(struct conn_probe_ctx* ctx, int ok) { c->interface_status = ok ? PROBE_RESULT_REACHABLE : (c->interface_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->interface_status); if (ok && ctx->best_across_sockets < c->interface_min_rtt) c->interface_min_rtt = ctx->best_across_sockets; c->interface_probe_time = get_time_tb(); + c->real_status = ok ? PROBE_RESULT_REACHABLE : (c->real_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->real_status); + if (ok && ctx->best_across_sockets < c->real_min_rtt) c->real_min_rtt = ctx->best_across_sockets; + c->real_probe_time = get_time_tb(); break; case TOPO_ADDR_NAT: c->nat_status = ok ? PROBE_RESULT_REACHABLE : (c->nat_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->nat_status); if (ok && ctx->best_across_sockets < c->nat_min_rtt) c->nat_min_rtt = ctx->best_across_sockets; c->nat_probe_time = get_time_tb(); break; - case TOPO_ADDR_REAL: - c->real_status = ok ? PROBE_RESULT_REACHABLE : (c->real_status == PROBE_RESULT_UNKNOWN ? PROBE_RESULT_UNREACHABLE : c->real_status); - if (ok && ctx->best_across_sockets < c->real_min_rtt) c->real_min_rtt = ctx->best_across_sockets; - c->real_probe_time = get_time_tb(); - break; } if (c->pending_count > 0) c->pending_count--; diff --git a/src/topo_node.c b/src/topo_node.c index cef8433b..017f28ed 100644 --- a/src/topo_node.c +++ b/src/topo_node.c @@ -556,23 +556,22 @@ int topo_group_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct TOPO_GR sm->id = e_sock->sock_id; sm->config_type = e_sock->type; sm->nat_type = e_sock->nat_type; sm->next = ni->v4_sock_meta; ni->v4_sock_meta = sm; } - struct sockaddr_in* if_sin = (struct sockaddr_in*)&e_sock->interface_addr; - struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr; + struct sockaddr_in* local_sin = (struct sockaddr_in*)&e_sock->local_addr; + struct sockaddr_in* if_sin = (struct sockaddr_in*)&e_sock->interface_addr; + struct sockaddr_in* nat_sin = (struct sockaddr_in*)&e_sock->nat_addr; + int use_local = (local_sin->sin_addr.s_addr != 0); { struct TOPO_ADDR4* a = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool); - memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port); + memcpy(a->addr, use_local ? &local_sin->sin_addr.s_addr : &if_sin->sin_addr.s_addr, 4); + a->port = ntohs(use_local ? local_sin->sin_port : if_sin->sin_port); a->type = TOPO_ADDR_INTERFACE; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP; a->next = ni->v4_addrs; ni->v4_addrs = a; } - if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0 && e_sock->nat_type != NAT_VERIFIED_STRICT) { + if (e_sock->nat_addr.ss_family == AF_INET && nat_sin->sin_addr.s_addr != 0 && e_sock->nat_type != NAT_VERIFIED_STRICT + && (nat_sin->sin_addr.s_addr != (use_local ? local_sin->sin_addr.s_addr : if_sin->sin_addr.s_addr) + || nat_sin->sin_port != (use_local ? local_sin->sin_port : if_sin->sin_port))) { struct TOPO_ADDR4* a = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool); memcpy(a->addr, &nat_sin->sin_addr.s_addr, 4); a->port = ntohs(nat_sin->sin_port); - a->type = TOPO_ADDR_NAT; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP; - a->next = ni->v4_addrs; ni->v4_addrs = a; - } - if (e_sock->nat_type == NAT_VERIFIED_DIRECT || ((e_sock->type == CFG_SERVER_TYPE_PUBLIC || e_sock->type == CFG_SERVER_TYPE_UNKNOWN) && e_sock->nat_type < NAT_VERIFIED_UNKNOWN)) { - struct TOPO_ADDR4* a = memory_pool_alloc(group->instance->topo_groups->v4_addr_pool); - memcpy(a->addr, &if_sin->sin_addr.s_addr, 4); a->port = ntohs(if_sin->sin_port); - a->type = TOPO_ADDR_REAL; a->socket_id = e_sock->sock_id; a->protocol = TOPO_PROTO_UDP; + a->type = TOPO_ADDR_NAT; a->socket_id = e_sock->sock_id | 1; a->protocol = TOPO_PROTO_UDP; a->next = ni->v4_addrs; ni->v4_addrs = a; } } else if (e_sock->local_addr.ss_family == AF_INET6) { diff --git a/src/topo_node_sqlite.c b/src/topo_node_sqlite.c index 1ace3856..6baac6ff 100644 --- a/src/topo_node_sqlite.c +++ b/src/topo_node_sqlite.c @@ -97,12 +97,14 @@ static uint8_t collect_socket_ids(struct TOPO_NODE* ni, uint8_t* sock_ids) { while (sm4) { uint8_t i; for (i = 0; i < count; i++) if (sock_ids[i] == sm4->id) break; if (i == count) sock_ids[count++] = sm4->id; + if (count < 510) sock_ids[count++] = sm4->id | 1; /* NAT slave slot, LSB=1 */ sm4 = sm4->next; } struct TOPO_SOCKMETA6* sm6 = ni->v6_sock_meta; while (sm6) { uint8_t i; for (i = 0; i < count; i++) if (sock_ids[i] == sm6->id) break; if (i == count) sock_ids[count++] = sm6->id; + if (count < 510) sock_ids[count++] = sm6->id | 1; sm6 = sm6->next; } return count; @@ -162,26 +164,19 @@ int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_NODEQ* nq) { struct TOPO_ADDR4* a4 = ni->v4_addrs; while (a4) { - /* filter private IPs */ - uint32_t ip; memcpy(&ip, a4->addr, 4); - { - uint8_t b0 = (uint8_t)ip; - if (b0 == 10 || b0 == 127) goto next_a4; - if (b0 == 172 && ((uint8_t)(ip >> 8) & 0xF0) == 16) goto next_a4; - if (b0 == 192 && (uint8_t)(ip >> 8) == 168) goto next_a4; - if (b0 == 169 && (uint8_t)(ip >> 8) == 254) goto next_a4; - } - int at = ADDR_TYPE_NETIF; - if (a4->type == TOPO_ADDR_REAL) { - at = ADDR_TYPE_DIRECT; - } else if (a4->type == TOPO_ADDR_NAT) { + if (a4->type == TOPO_ADDR_NAT) { struct TOPO_SOCKMETA4* sm = ni->v4_sock_meta; - while (sm) { if (sm->id == a4->socket_id) break; sm = sm->next; } + while (sm) { if (sm->id == (a4->socket_id & ~1)) break; sm = sm->next; } if (sm && (sm->nat_type == NAT_TYPE_STRICT || sm->nat_type == NAT_VERIFIED_STRICT)) at = ADDR_TYPE_NAT_STRICT; else at = ADDR_TYPE_NAT_EIM; + } else { + struct TOPO_SOCKMETA4* sm = ni->v4_sock_meta; + while (sm) { if (sm->id == a4->socket_id) break; sm = sm->next; } + if (sm && (sm->nat_type == NAT_TYPE_DIRECT || sm->nat_type == NAT_VERIFIED_DIRECT)) + at = ADDR_TYPE_DIRECT; } sqlite3_bind_int64(addr_stmt, 1, (sqlite3_int64)ni->node_id); @@ -193,7 +188,6 @@ int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_NODEQ* nq) { sqlite3_bind_int(addr_stmt, 7, at); sqlite3_bind_int(addr_stmt, 8, (int)a4->socket_id); sqlite3_step(addr_stmt); sqlite3_reset(addr_stmt); - next_a4: a4 = a4->next; } @@ -203,15 +197,18 @@ int topo_node_sqlite_node_put(sqlite3* db, struct TOPO_NODEQ* nq) { if (a6->addr[0] == 0xFE && (a6->addr[1] & 0xC0) == 0x80) { a6 = a6->next; continue; } int at = ADDR_TYPE_NETIF; - if (a6->type == TOPO_ADDR_REAL) { - at = ADDR_TYPE_DIRECT; - } else if (a6->type == TOPO_ADDR_NAT) { + if (a6->type == TOPO_ADDR_NAT) { struct TOPO_SOCKMETA6* sm = ni->v6_sock_meta; - while (sm) { if (sm->id == a6->socket_id) break; sm = sm->next; } + while (sm) { if (sm->id == (a6->socket_id & ~1)) break; sm = sm->next; } if (sm && (sm->nat_type == NAT_TYPE_STRICT || sm->nat_type == NAT_VERIFIED_STRICT)) at = ADDR_TYPE_NAT_STRICT; else at = ADDR_TYPE_NAT_EIM; + } else { + struct TOPO_SOCKMETA6* sm = ni->v6_sock_meta; + while (sm) { if (sm->id == a6->socket_id) break; sm = sm->next; } + if (sm && (sm->nat_type == NAT_TYPE_DIRECT || sm->nat_type == NAT_VERIFIED_DIRECT)) + at = ADDR_TYPE_DIRECT; } sqlite3_bind_int64(addr_stmt, 1, (sqlite3_int64)ni->node_id);