Browse Source

BGP: 2 addr per socket (remove TOPO_ADDR_REAL), config IP priority, private IPs in SQLite, NAT addr != INTERFACE

topo_upd
Evgeny 3 months ago
parent
commit
ca6a27aadb
  1. 10
      src/conn_mgr.c
  2. 20
      src/route_connectivity.c
  3. 21
      src/topo_node.c
  4. 35
      src/topo_node_sqlite.c

10
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));

20
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--;

21
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) {

35
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);

Loading…
Cancel
Save