|
|
|
|
@ -361,7 +361,46 @@ int node_conn_direct_compatible(struct UTUN_INSTANCE* inst, uint64_t node_id) {
|
|
|
|
|
if (conn && conn->state != 2 && !conn->close_requested && conn->links_up) return 1; |
|
|
|
|
struct TOPO_NODE* node = topo_node_registry_find(inst->topo_groups, node_id); |
|
|
|
|
if (!node) { DEBUG_DEBUG(DEBUG_CATEGORY_NCD, "[ncd] compatibility unknown snapshot node=%016llx", (unsigned long long)node_id); return 0; } |
|
|
|
|
return ncd_create_links(NULL, node, NULL, inst) > 0; |
|
|
|
|
if (ncd_create_links(NULL, node, NULL, inst) > 0) return 1; |
|
|
|
|
/* Входящее подключение тоже допустимо: REVERSE_REQ просит пира открыть наш опубликованный адрес.
|
|
|
|
|
* TCP имеет собственный исходящий socket fallback; для UDP нужен известный UDP-сокет пира. |
|
|
|
|
* Это возможность попытки, не подтверждение маршрута/работоспособности скрытых сокетов пира. */ |
|
|
|
|
const struct TOPO_NODE* self = topo_node_registry_find(inst->topo_groups, inst->node_id); |
|
|
|
|
if (!self) return 0; |
|
|
|
|
for (const struct TOPO_ADDR4* a = self->v4_addrs; a; a = a->next) { |
|
|
|
|
uint32_t ip; memcpy(&ip, a->addr, 4); |
|
|
|
|
if (!ip || !a->port) continue; |
|
|
|
|
const struct TOPO_SOCKMETA4* meta = self->v4_sock_meta; |
|
|
|
|
while (meta && meta->id != a->socket_id) meta = meta->next; |
|
|
|
|
uint8_t cfg = meta ? meta->config_type : CFG_SERVER_TYPE_UNKNOWN, nat = meta ? meta->nat_type : NAT_TYPE_UNKNOWN; |
|
|
|
|
if (sock_target_class(a->type, cfg, nat) != SOCK_TC_PUB) continue; |
|
|
|
|
if ((a->protocol & TOPO_PROTO_REALITY) && !topo_node_find_reality_sock(self, a->socket_id)) continue; |
|
|
|
|
if (a->protocol & TOPO_PROTO_TCP) return 1; |
|
|
|
|
if (!(a->protocol & TOPO_PROTO_UDP)) continue; |
|
|
|
|
for (const struct TOPO_ADDR4* remote = node->v4_addrs; remote; remote = remote->next) { |
|
|
|
|
if (!(remote->protocol & TOPO_PROTO_UDP)) continue; |
|
|
|
|
const struct TOPO_SOCKMETA4* rm = node->v4_sock_meta; |
|
|
|
|
while (rm && rm->id != remote->socket_id) rm = rm->next; |
|
|
|
|
struct sock_view view = {.has_inet = 1}; |
|
|
|
|
view.is_eim = rm && (rm->nat_type == NAT_TYPE_EIM || rm->nat_type == NAT_VERIFIED_EIM); |
|
|
|
|
for (const struct TOPO_ADDR4* ra = node->v4_addrs; ra; ra = ra->next) |
|
|
|
|
if (ra->socket_id == remote->socket_id && ra->type == TOPO_ADDR_NAT) memcpy(&view.public_ip4, ra->addr, 4); |
|
|
|
|
if (sock_match(&view, a->type, cfg, nat, ip)) return 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (const struct TOPO_ADDR6* a = self->v6_addrs; a; a = a->next) { |
|
|
|
|
int nonzero = 0; for (unsigned i = 0; i < 16; i++) nonzero |= a->addr[i]; |
|
|
|
|
if (!nonzero || !a->port || (a->addr[0] == 0xfe && (a->addr[1] & 0xc0) == 0x80)) continue; |
|
|
|
|
const struct TOPO_SOCKMETA6* meta = self->v6_sock_meta; |
|
|
|
|
while (meta && meta->id != a->socket_id) meta = meta->next; |
|
|
|
|
if (meta && (meta->config_type == CFG_SERVER_TYPE_PRIVATE || meta->config_type == CFG_SERVER_TYPE_LOCAL)) continue; |
|
|
|
|
if ((a->protocol & TOPO_PROTO_REALITY) && !topo_node_find_reality_sock(self, a->socket_id)) continue; |
|
|
|
|
if (a->protocol & TOPO_PROTO_TCP) return 1; |
|
|
|
|
if (!(a->protocol & TOPO_PROTO_UDP)) continue; |
|
|
|
|
for (const struct TOPO_ADDR6* remote = node->v6_addrs; remote; remote = remote->next) |
|
|
|
|
if (remote->protocol & TOPO_PROTO_UDP) return 1; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int node_conn_direct_update_node(struct UTUN_INSTANCE* inst, uint64_t node_id) { |
|
|
|
|
|