diff --git a/src/etcp_connections.c b/src/etcp_connections.c index 5ab2ec96..a61ef13f 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -547,7 +547,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S e_sock->pkt_format_errors = 0; e_sock->type = type; e_sock->sock_id = instance->next_socket_id++; - e_sock->nat_type = NAT_TYPE_UNKNOWN; + e_sock->nat_type = type; // initial type from config, updated after NAT detection e_sock->mtu = mtu; e_sock->loss_rate = loss_rate; DEBUG_INFO(DEBUG_CATEGORY_BGP, "Add Socket type=%d", type); diff --git a/src/etcp_connections.h b/src/etcp_connections.h index a9d3f109..ef2b7eeb 100644 --- a/src/etcp_connections.h +++ b/src/etcp_connections.h @@ -74,6 +74,26 @@ struct ETCP_SOCKET { uint8_t local_defaultroute_ip6[16]; // auto-detected IPv6 for public servers }; +// NAT check status +#define NAT_CHECK_NONE 0 +#define NAT_CHECK_WAITING 1 +#define NAT_CHECK_IN_PROGRESS 2 +#define NAT_CHECK_OPEN 3 +#define NAT_CHECK_RESTRICTED 4 + +// NAT type (detected by server during NAT check) +#define NAT_TYPE_UNKNOWN 0 +#define NAT_TYPE_OPEN 1 +#define NAT_TYPE_RESTRICTED 2 + +// Verified NAT types (published in nodeinfo after server-side NAT detection) +// Values above CFG_SERVER_TYPE_PRIVATE to avoid collision with config types +#define NAT_VERIFIED_UNKNOWN 4 // detection failed or inconclusive +#define NAT_VERIFIED_OPEN 5 // open NAT +#define NAT_VERIFIED_RESTRICTED 6 // restricted NAT +#define NAT_VERIFIED_DIRECT 7 // real public IP, no NAT + + // ETCP Link - одно динамическое соединение (один путь) struct ETCP_LINK { uint32_t ip_port_hash; // crc32 для быстрого поиска @@ -171,6 +191,7 @@ struct ETCP_LINK { uint16_t nat_port; // NAT port (network byte order) uint32_t nat_changes_count; // Counter of NAT address changes uint32_t nat_hits_count; // Counter of NAT address matches (new init response with same IP:port) + uint8_t nat_check_status; // NAT_CHECK_* // Keepalive state void* keepalive_timer; // Таймер для отправки keepalive пакетов diff --git a/src/route_bgp.c b/src/route_bgp.c index c66ada43..a2910fd7 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -113,6 +113,8 @@ static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id // Приём пакетов // ============================================================================ +static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link); + static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) { if (!from_conn || !entry || entry->len < 2) { if (entry) { @@ -156,28 +158,100 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* } else if (subcmd == ROUTE_SUBCMD_PING_RESP) { route_ping_handle_resp(bgp, from_conn, data, entry->len); } else if (subcmd == ROUTE_SUBCMD_NAT_INFO) { - if (entry->len >= sizeof(struct BGP_NAT_INFO)) { + if (entry->len >= sizeof(struct BGP_NAT_INFO) && bgp && bgp->local_node) { const struct BGP_NAT_INFO* info = (const struct BGP_NAT_INFO*)data; uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) | (info->nat_ip[2] << 8) | info->nat_ip[3]; uint16_t nat_port = ((info->nat_port >> 8) & 0xFF) | ((info->nat_port & 0xFF) << 8); - uint16_t nat_port_be = info->nat_port; - // Save nat_type to all links of this connection and their sockets + uint8_t socket_id = info->socket_id; + // Update socket in local_node and ETCP_SOCKET + uint8_t* dynamic = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO); + dynamic += bgp->local_node->node.node_name_len; + struct NODEINFO_IPV4_SOCKET* sockets = (struct NODEINFO_IPV4_SOCKET*)dynamic; + for (int i = 0; i < bgp->local_node->node.local_v4_sockets; i++) { + if (sockets[i].id == socket_id) { + uint8_t old_type = sockets[i].type; + uint32_t old_ip = (sockets[i].addr[0] << 24) | (sockets[i].addr[1] << 16) | + (sockets[i].addr[2] << 8) | sockets[i].addr[3]; + uint16_t old_port = sockets[i].port; + memcpy(sockets[i].addr, info->nat_ip, 4); + sockets[i].port = nat_port; + uint8_t verified_type; + if (info->nat_type == NAT_TYPE_OPEN) { + verified_type = NAT_VERIFIED_OPEN; + } else if (info->nat_type == NAT_TYPE_RESTRICTED) { + verified_type = NAT_VERIFIED_RESTRICTED; + } else { + verified_type = NAT_VERIFIED_UNKNOWN; + } + sockets[i].type = verified_type; + // Update ETCP_SOCKET + struct ETCP_SOCKET* es = bgp->instance->etcp_sockets; + while (es) { + if (es->sock_id == socket_id) { + es->nat_type = verified_type; + break; + } + es = es->next; + } + // Check if NAT actually changed - only update nodeinfo if changed + if (old_ip != nat_ip || old_port != nat_port || old_type != verified_type) { + bgp->local_node->dirty = 1; + bgp->local_node->node.ver = (bgp->local_node->node.ver + 1) % 255 + 1; + // Broadcast updated nodeinfo to all peers immediately + if (bgp->senders_list) { + struct ll_entry* se = bgp->senders_list->head; + while (se) { + struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data; + if (item && item->conn) { + route_bgp_send_nodeinfo(bgp->local_node, item->conn); + } + se = se->next; + } + } + } + break; + } + } + // Save nat_type to all links of this connection struct ETCP_LINK* l = from_conn->links; while (l) { l->nat_type = info->nat_type; - if (l->conn) { - l->conn->nat_type = info->nat_type; - } l = l->next; } - DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO from %s: type=%s ip=%u.%u.%u.%u port=%u", - from_conn->log_name, + DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO from %s: socket_id=%u type=%s ip=%u.%u.%u.%u port=%u", + from_conn->log_name, socket_id, info->nat_type == NAT_TYPE_OPEN ? "OPEN" : "RESTRICTED", (info->nat_ip[0]), (info->nat_ip[1]), (info->nat_ip[2]), (info->nat_ip[3]), (unsigned)nat_port); } + } else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) { + if (entry->len >= sizeof(struct BGP_NAT_CHECK_REQ) && bgp) { + const struct BGP_NAT_CHECK_REQ* req = (const struct BGP_NAT_CHECK_REQ*)data; + uint8_t socket_id = req->socket_id; + // Find link by remote_socket_id in the connection + struct ETCP_LINK* target_link = NULL; + struct ETCP_LINK* l = from_conn->links; + while (l) { + if (l->remote_socket_id == socket_id) { + target_link = l; + break; + } + l = l->next; + } + if (!target_link) { + DEBUG_WARN(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: no link with remote_socket_id=%u", + from_conn->log_name, socket_id); + } else if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) { + DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: check already in progress for socket_id=%u", + from_conn->log_name, socket_id); + } else { + DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: restarting NAT check for socket_id=%u", + from_conn->log_name, socket_id); + route_bgp_start_link_nat_check(bgp, target_link); + } + } } queue_dgram_free(entry); @@ -323,8 +397,6 @@ void route_bgp_destroy(struct UTUN_INSTANCE* instance) { instance->bgp = NULL; } -static void route_bgp_start_nat_check(struct ROUTE_BGP* bgp, struct NODEINFO_Q* node, struct ETCP_CONN* via_conn); - void route_bgp_new_conn(struct ETCP_CONN* conn) { if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_bgp_new_conn: conn is NULL"); @@ -347,16 +419,17 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) { route_bgp_add_to_senders(bgp, conn); - // Try to start NAT checks for nodes waiting for a third node - if (bgp->nodes) { - struct ll_entry* e = bgp->nodes->head; - while (e) { - struct NODEINFO_Q* node = (struct NODEINFO_Q*)e; - if (node->nat_check_status == NAT_CHECK_WAITING) { - route_bgp_start_nat_check(bgp, node, conn); + // Scan ALL connections and ALL links in instance - start NAT check if not started + struct ETCP_CONN* c = conn->instance->connections; + while (c) { + struct ETCP_LINK* l = c->links; + while (l) { + if (l->initialized && l->conn && l->nat_check_status == NAT_CHECK_NONE) { + route_bgp_start_link_nat_check(bgp, l); } - e = e->next; + l = l->next; } + c = c->next; } route_bgp_send_table_request(bgp, conn); @@ -559,29 +632,27 @@ int nodeinfo_dyn_size(struct NODEINFO* node) { // NAT check context struct nat_check_arg { - struct NODEINFO_Q* node; - struct ETCP_CONN* client_conn; + struct ETCP_LINK* link; uint32_t nat_ip; uint16_t nat_port; }; -static void nat_check_cb(int success, uint16_t avg_rtt, uint8_t count_sent, uint8_t count_ok, - uint32_t recv_ip, uint16_t recv_port, void* arg) { +static void nat_link_check_cb(int success, uint16_t avg_rtt, uint8_t count_sent, uint8_t count_ok, + uint32_t recv_ip, uint16_t recv_port, void* arg) { (void)avg_rtt; (void)count_sent; (void)count_ok; (void)recv_ip; (void)recv_port; struct nat_check_arg* na = (struct nat_check_arg*)arg; - if (!na || !na->node) { u_free(na); return; } + if (!na || !na->link) { u_free(na); return; } + struct ETCP_LINK* link = na->link; uint8_t nat_type = success ? NAT_TYPE_OPEN : NAT_TYPE_RESTRICTED; - na->node->nat_type = nat_type; - na->node->nat_check_status = success ? NAT_CHECK_OPEN : NAT_CHECK_RESTRICTED; - // Save nat_type to all links of client connection - if (na->client_conn) { - struct ETCP_LINK* l = na->client_conn->links; - while (l) { l->nat_type = nat_type; l = l->next; } - } - route_bgp_send_nat_info(na->client_conn, na->nat_ip, na->nat_port, nat_type); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "nat_check_cb: node=%016llx type=%s success=%d", - (unsigned long long)na->node->node.node_id, - success ? "OPEN" : "RESTRICTED", success); + link->nat_type = nat_type; + link->nat_check_status = success ? NAT_CHECK_OPEN : NAT_CHECK_RESTRICTED; + // Send NAT_INFO to peer (via their connection) + if (link->etcp) { + uint8_t socket_id = link->remote_socket_id; + route_bgp_send_nat_info(link->etcp, socket_id, na->nat_ip, na->nat_port, nat_type); + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "link=%p type=%s success=%d", + (void*)link, success ? "OPEN" : "RESTRICTED", success); u_free(na); } @@ -610,43 +681,51 @@ static void route_bgp_extract_nat_addr(struct ETCP_CONN* conn, uint32_t* nat_ip, } } -static void route_bgp_start_nat_check(struct ROUTE_BGP* bgp, struct NODEINFO_Q* node, struct ETCP_CONN* via_conn) { - if (!bgp || !node || !via_conn) return; - if (node->nat_check_status != NAT_CHECK_NONE && node->nat_check_status != NAT_CHECK_WAITING) return; - // Find client connection - struct ETCP_CONN* client_conn = NULL; - if (node->paths && node->paths->head) { - struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)node->paths->head; - client_conn = path->conn; - } - if (!client_conn) return; - // Extract NAT address from client connection - uint32_t nat_ip; uint16_t nat_port; - route_bgp_extract_nat_addr(client_conn, &nat_ip, &nat_port); - if (nat_ip == 0 || nat_port == 0) return; - // Save NAT address to node - node->nat_ip = nat_ip; - node->nat_port = nat_port; +static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link) { + if (!bgp || !link || !link->conn || !link->etcp) return; + if (link->nat_check_status == NAT_CHECK_IN_PROGRESS) return; + // Find third node to send ping through + struct ETCP_CONN* third_conn = route_bgp_find_third_node(bgp, link->etcp); + if (!third_conn) { + DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "route_bgp_start_link_nat_check: no third node found for link"); + return; + } + // Get target address - use nat_ip/nat_port if set, otherwise use remote_addr + uint32_t target_ip; + uint16_t target_port; + if (link->nat_ip != 0 && link->nat_port != 0) { + target_ip = link->nat_ip; + target_port = link->nat_port; + } else { + struct sockaddr_in* sin = (struct sockaddr_in*)&link->remote_addr; + target_ip = ntohl(sin->sin_addr.s_addr); + target_port = ntohs(sin->sin_port); + } // Allocate callback arg struct nat_check_arg* arg = u_calloc(1, sizeof(struct nat_check_arg)); if (!arg) return; - arg->node = node; - arg->client_conn = client_conn; - arg->nat_ip = nat_ip; - arg->nat_port = nat_port; - // Send ping request via third node (with embedded pubkey for NAT detection) - int ret = route_ping_send_req_addr(bgp, via_conn, node->node.node_id, nat_ip, nat_port, - 3, 500, 1000, 5000, nat_check_cb, arg, - node->node.public_key); + arg->link = link; + arg->nat_ip = target_ip; + arg->nat_port = target_port; + // Use peer public key from the connection's crypto context + const uint8_t* pubkey = link->etcp->crypto_ctx.peer_key_set ? link->etcp->crypto_ctx.peer_public_key : NULL; + if (!pubkey) { + u_free(arg); + DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "route_bgp_start_link_nat_check: no peer pubkey for link=%p", (void*)link); + return; + } + // Send ping via third node - embed peer pubkey for NAT detection + int ret = route_ping_send_req_addr(bgp, third_conn, link->etcp->peer_node_id, target_ip, target_port, + 3, 500, 1000, 5000, nat_link_check_cb, arg, + pubkey); if (ret == 0) { - node->nat_check_status = NAT_CHECK_IN_PROGRESS; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_start_nat_check: started for node=%016llx via=%s", - (unsigned long long)node->node.node_id, via_conn->log_name); + link->nat_check_status = NAT_CHECK_IN_PROGRESS; + DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_start_link_nat_check: started for link=%p via=%s", + (void*)link, third_conn->log_name); } else { - node->nat_check_status = NAT_CHECK_WAITING; u_free(arg); - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_bgp_start_nat_check: failed to start for node=%016llx", - (unsigned long long)node->node.node_id); + DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_bgp_start_link_nat_check: failed to start for link=%p", + (void*)link); } } @@ -712,18 +791,6 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co route_bgp_remove_path_by_hop(nodeinfo1, from->peer_node_id); route_bgp_add_path(nodeinfo1, from, hop_list, nodeinfo1->node.hop_count); - // Start NAT check for direct peers - if (nodeinfo1->node.hop_count == 1 && nodeinfo1->nat_check_status == NAT_CHECK_NONE) { - struct ETCP_CONN* third = route_bgp_find_third_node(bgp, from); - if (third) { - route_bgp_start_nat_check(bgp, nodeinfo1, third); - } else { - nodeinfo1->nat_check_status = NAT_CHECK_WAITING; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT check queued (no third node yet) for node=%016llx", - (unsigned long long)node_id); - } - } - if (bgp->instance->rt) { route_insert(bgp->instance->rt, nodeinfo1); } @@ -887,12 +954,13 @@ static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CO route_bgp_add_to_senders(bgp, conn); } -void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type) { +void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type) { if (!conn) return; struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO)); if (!pkt) return; pkt->cmd = ETCP_ID_ROUTE_ENTRY; pkt->subcmd = ROUTE_SUBCMD_NAT_INFO; + pkt->socket_id = socket_id; pkt->nat_ip[0] = (nat_ip >> 24) & 0xFF; pkt->nat_ip[1] = (nat_ip >> 16) & 0xFF; pkt->nat_ip[2] = (nat_ip >> 8) & 0xFF; @@ -908,8 +976,28 @@ void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint32_t nat_ip, uint16_t n e->dgram = (uint8_t*)pkt; e->len = sizeof(struct BGP_NAT_INFO); etcp_send(conn, e); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_send_nat_info to %s: type=%s ip=%08x port=%u", - conn->log_name, + DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_send_nat_info to %s: socket_id=%u type=%s ip=%08x port=%u", + conn->log_name, socket_id, nat_type == NAT_TYPE_OPEN ? "OPEN" : "RESTRICTED", (unsigned)nat_ip, (unsigned)nat_port); } + +void route_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) { + if (!conn) return; + struct BGP_NAT_CHECK_REQ* pkt = u_calloc(1, sizeof(struct BGP_NAT_CHECK_REQ)); + if (!pkt) return; + pkt->cmd = ETCP_ID_ROUTE_ENTRY; + pkt->subcmd = ROUTE_SUBCMD_NAT_CHECK_REQ; + pkt->socket_id = socket_id; + + struct ll_entry* e = queue_entry_new(0); + if (!e) { + u_free(pkt); + return; + } + e->dgram = (uint8_t*)pkt; + e->len = sizeof(struct BGP_NAT_CHECK_REQ); + etcp_send(conn, e); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_bgp_send_nat_check_req to %s: socket_id=%u", + conn->log_name, socket_id); +} diff --git a/src/route_bgp.h b/src/route_bgp.h index cd834066..d7278fa9 100644 --- a/src/route_bgp.h +++ b/src/route_bgp.h @@ -17,6 +17,7 @@ #define ROUTE_SUBCMD_REQUEST_TABLE 0x05 // запрос полной таблицы #define ROUTE_SUBCMD_WITHDRAW 0x06 // узел стал недоступен #define ROUTE_SUBCMD_NAT_INFO 0x09 // информация о типе NAT клиента +#define ROUTE_SUBCMD_NAT_CHECK_REQ 0x0A // запрос от клиента на проверку NAT для сокета #define MAX_HOPS 16 #define BGP_NODES_HASH_SIZE 256 @@ -59,11 +60,21 @@ struct ROUTE_BGP_CONN_ITEM { struct BGP_NAT_INFO { uint8_t cmd; uint8_t subcmd; + uint8_t socket_id; // MY socket id (link->conn->sock_id) uint8_t nat_ip[4]; // network byte order uint16_t nat_port; // network byte order uint8_t nat_type; // NAT_TYPE_* } __attribute__((packed)); +/** + * @brief Пакет запроса на проверку NAT от клиента к серверу + */ +struct BGP_NAT_CHECK_REQ { + uint8_t cmd; + uint8_t subcmd; // ROUTE_SUBCMD_NAT_CHECK_REQ + uint8_t socket_id; // ID сокета клиента, который надо проверить +} __attribute__((packed)); + struct route_ping_pending; struct ROUTE_BGP { @@ -165,6 +176,14 @@ int route_bgp_remove_path(struct NODEINFO_Q* nq, struct ETCP_CONN* conn); * @param nat_port порт клиента (network byte order) * @param nat_type NAT_TYPE_OPEN или NAT_TYPE_RESTRICTED */ -void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type); +void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type); + +/** + * @brief Отправляет запрос на проверку NAT для указанного socket_id серверу. + * + * @param conn соединение к серверу + * @param socket_id ID сокета для проверки + */ +void route_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id); #endif // ROUTE_BGP_H diff --git a/src/route_node.c b/src/route_node.c index cf5aa547..ace059b6 100644 --- a/src/route_node.c +++ b/src/route_node.c @@ -167,7 +167,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG if (e_sock->local_addr.ss_family == AF_INET) { struct sockaddr_in* sin = (struct sockaddr_in*)&e_sock->local_addr; if (memcmp(sa->addr, &sin->sin_addr.s_addr, 4) != 0 || sa->port != ntohs(sin->sin_port) || - sa->type != e_sock->type || sa->id != e_sock->sock_id) { + sa->type != e_sock->nat_type || sa->id != e_sock->sock_id) { same = false; break; } @@ -204,7 +204,7 @@ int route_bgp_update_my_nodeinfo(struct UTUN_INSTANCE* instance, struct ROUTE_BG struct sockaddr_in* sin = (struct sockaddr_in*)&e_sock->local_addr; memcpy(sa->addr, &sin->sin_addr.s_addr, 4); sa->port = ntohs(sin->sin_port); - sa->type = e_sock->type; + sa->type = e_sock->nat_type; sa->id = e_sock->sock_id; sa++; } diff --git a/src/route_node.h b/src/route_node.h index f2870e0c..9c880047 100644 --- a/src/route_node.h +++ b/src/route_node.h @@ -60,18 +60,6 @@ struct NODEINFO_PATH { uint8_t hop_count; // hop list: маршрут этого path };// __attribute__((packed)); -// NAT check status -#define NAT_CHECK_NONE 0 -#define NAT_CHECK_WAITING 1 -#define NAT_CHECK_IN_PROGRESS 2 -#define NAT_CHECK_OPEN 3 -#define NAT_CHECK_RESTRICTED 4 - -// NAT type -#define NAT_TYPE_UNKNOWN 0 -#define NAT_TYPE_OPEN 1 -#define NAT_TYPE_RESTRICTED 2 - struct NODEINFO_Q { struct ll_entry ll; struct ll_queue* paths; // сюда помещаем struct NODEINFO_PATH @@ -80,10 +68,6 @@ struct NODEINFO_Q { uint64_t last_ping_time; // время последнего замера в 0.1ms uint16_t last_rtt; // лучший RTT в 0.1ms struct ETCP_SOCKET* best_socket; - uint8_t nat_check_status; // NAT_CHECK_* - uint32_t nat_ip; // IP клиента (network byte order) - uint16_t nat_port; // порт клиента - uint8_t nat_type; // NAT_TYPE_* struct NODEINFO node; // Всегда в конце структуры - динамически расширяемый блок };// __attribute__((packed)); diff --git a/src/route_ping.c b/src/route_ping.c index ecd1202e..8e496787 100644 --- a/src/route_ping.c +++ b/src/route_ping.c @@ -54,6 +54,7 @@ struct route_ping_pending { route_ping_callback_t callback; void* arg; void* timeout_timer; + uint8_t cancelled; }; static void route_ping_send_resp(struct route_ping_req* req, uint16_t avg_rtt); @@ -64,6 +65,10 @@ static void route_ping_pending_timeout(void* arg) { struct route_ping_pending* p = (struct route_ping_pending*)arg; if (!p) return; p->timeout_timer = NULL; + if (p->cancelled) { + u_free(p); + return; + } struct ROUTE_BGP* bgp = p->bgp; struct route_ping_pending** cur = &bgp->ping_pending; while (*cur) { @@ -177,7 +182,7 @@ static void route_ping_finish(struct route_ping_req* req) { req->target_node->last_ping_time = get_time_tb(); req->target_node->last_rtt = best_avg_rtt; req->target_node->best_socket = best_sock; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_finish: node=%016llx best_rtt=%u best_sock=%p metric=%u", + DEBUG_INFO(DEBUG_CATEGORY_BGP, "node=%016llx best_rtt=%u best_sock=%p metric=%u", (unsigned long long)req->target_node->node.node_id, (unsigned)best_avg_rtt, (void*)best_sock, (unsigned)best_metric); } @@ -211,7 +216,7 @@ static void route_ping_send_resp(struct route_ping_req* req, uint16_t avg_rtt) { e->dgram = (uint8_t*)resp; e->len = sizeof(struct BGP_PING_RESPONSE); etcp_send(req->reply_conn, e); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_send_resp: request_id=%016llx sent=%u ok=%u avg_rtt=%u", + DEBUG_INFO(DEBUG_CATEGORY_BGP, "request_id=%016llx sent=%u ok=%u avg_rtt=%u", (unsigned long long)req->request_id, (unsigned)total_sent, (unsigned)total_ok, (unsigned)avg_rtt); } @@ -219,12 +224,12 @@ int route_ping_send_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, uint64 uint8_t count, uint16_t interval_ms, uint16_t timeout_ms, uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg) { if (!bgp || !to_conn || count == 0 || timeout_ms == 0) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req: invalid args"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); return -1; } struct BGP_PING_REQUEST* req_pkt = u_calloc(1, sizeof(struct BGP_PING_REQUEST)); if (!req_pkt) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req: alloc failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "alloc failed"); return -2; } req_pkt->cmd = ETCP_ID_ROUTE_ENTRY; @@ -238,7 +243,7 @@ int route_ping_send_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, uint64 struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(req_pkt); - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req: queue_entry_new failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "queue_entry_new failed"); return -3; } e->dgram = (uint8_t*)req_pkt; @@ -248,13 +253,13 @@ int route_ping_send_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, uint64 if (ret != 0) { u_free(req_pkt); queue_entry_free(e); - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req: etcp_send failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send failed"); return -4; } struct route_ping_pending* pending = u_calloc(1, sizeof(struct route_ping_pending)); if (!pending) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req: pending alloc failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "pending alloc failed"); return -5; } pending->bgp = bgp; @@ -266,7 +271,7 @@ int route_ping_send_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, uint64 pending->timeout_timer = uasync_set_timeout(bgp->instance->ua, wait_timeout_ms * 10, pending, route_ping_pending_timeout); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_send_req: request_id=%016llx node=%016llx count=%u interval=%u timeout=%u wait=%u", + DEBUG_INFO(DEBUG_CATEGORY_BGP, "request_id=%016llx node=%016llx count=%u interval=%u timeout=%u wait=%u", (unsigned long long)pending->request_id, (unsigned long long)node_id, (unsigned)count, (unsigned)interval_ms, (unsigned)timeout_ms, (unsigned)wait_timeout_ms); return 0; @@ -278,13 +283,13 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u uint16_t wait_timeout_ms, route_ping_callback_t cb, void* arg, const uint8_t* pubkey) { if (!bgp || !to_conn || count == 0 || timeout_ms == 0) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: invalid args"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); return -1; } size_t pkt_size = pubkey ? sizeof(struct BGP_PING_REQUEST) : offsetof(struct BGP_PING_REQUEST, pubkey); struct BGP_PING_REQUEST* req_pkt = u_calloc(1, pkt_size); if (!req_pkt) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: alloc failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "alloc failed"); return -2; } req_pkt->cmd = ETCP_ID_ROUTE_ENTRY; @@ -306,7 +311,7 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u struct ll_entry* e = queue_entry_new(0); if (!e) { u_free(req_pkt); - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: queue_entry_new failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "queue_entry_new failed"); return -3; } e->dgram = (uint8_t*)req_pkt; @@ -316,13 +321,13 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u if (ret != 0) { u_free(req_pkt); queue_entry_free(e); - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: etcp_send failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "etcp_send failed"); return -4; } struct route_ping_pending* pending = u_calloc(1, sizeof(struct route_ping_pending)); if (!pending) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: pending alloc failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "pending alloc failed"); return -5; } pending->bgp = bgp; @@ -334,7 +339,7 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u pending->timeout_timer = uasync_set_timeout(bgp->instance->ua, wait_timeout_ms * 10, pending, route_ping_pending_timeout); - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: request_id=%016llx node=%016llx ip=%08x port=%u pubkey=%s", + DEBUG_INFO(DEBUG_CATEGORY_BGP, "request_id=%016llx node=%016llx ip=%08x port=%u pubkey=%s", (unsigned long long)pending->request_id, (unsigned long long)node_id, (unsigned)target_ip, (unsigned)target_port, pubkey ? "yes" : "no"); return 0; @@ -345,11 +350,18 @@ void route_ping_destroy_pending(struct ROUTE_BGP* bgp) { while (bgp->ping_pending) { struct route_ping_pending* p = bgp->ping_pending; bgp->ping_pending = p->next; + p->next = NULL; if (p->timeout_timer) { - uasync_cancel_timeout(bgp->instance->ua, p->timeout_timer); + err_t rc = uasync_cancel_timeout(bgp->instance->ua, p->timeout_timer); p->timeout_timer = NULL; + if (rc == ERR_OK) { + u_free(p); + } else { + p->cancelled = 1; + } + } else { + u_free(p); } - u_free(p); } } @@ -357,7 +369,7 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c const size_t base_len = offsetof(struct BGP_PING_REQUEST, target_ipv4); const size_t addr_len = offsetof(struct BGP_PING_REQUEST, pubkey); if (!bgp || !from_conn || !data || (len != base_len && len != addr_len && len != sizeof(struct BGP_PING_REQUEST))) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_req: invalid args len=%zu", len); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args len=%zu", len); return; } const struct BGP_PING_REQUEST* req_pkt = (const struct BGP_PING_REQUEST*)data; @@ -382,7 +394,7 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c custom_socket.id = 0; sockets_v4 = &custom_socket; sock_count_v4 = 1; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_handle_req: using custom target %d.%d.%d.%d:%u for node %016llx", + DEBUG_INFO(DEBUG_CATEGORY_BGP, "using custom target %d.%d.%d.%d:%u for node %016llx", req_pkt->target_ipv4[0], req_pkt->target_ipv4[1], req_pkt->target_ipv4[2], req_pkt->target_ipv4[3], req_pkt->target_port, (unsigned long long)req_pkt->node_id); // Check if embedded pubkey is non-zero (only when full packet length) @@ -401,7 +413,7 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c // Base packet without custom target - use nodeinfo sockets target = route_bgp_get_node(bgp, req_pkt->node_id); if (!target) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: node %016llx not found", + DEBUG_WARN(DEBUG_CATEGORY_BGP, "node %016llx not found", (unsigned long long)req_pkt->node_id); // отправляем ответ с нулями struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req)); @@ -417,12 +429,12 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c sock_count_v4 = get_node_v4_sockets(target, &sockets_v4); sock_count_v6 = get_node_v6_sockets(target, &sockets_v6); } else { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: unexpected packet size %zu", len); + DEBUG_WARN(DEBUG_CATEGORY_BGP, "unexpected packet size %zu", len); return; } if ((sock_count_v4 <= 0 || !sockets_v4) && (sock_count_v6 <= 0 || !sockets_v6)) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: no sockets for node %016llx", + DEBUG_WARN(DEBUG_CATEGORY_BGP, "no sockets for node %016llx", (unsigned long long)req_pkt->node_id); struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req)); if (req) { @@ -446,7 +458,7 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c } uint8_t local_count = local_v4_count + local_v6_count; if (local_count == 0) { - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: no local sockets"); + DEBUG_WARN(DEBUG_CATEGORY_BGP, "no local sockets"); struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req)); if (req) { req->reply_conn = from_conn; @@ -459,7 +471,7 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c } struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req) + local_count * sizeof(struct route_ping_sock_ctx)); if (!req) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_req: alloc failed"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "alloc failed"); return; } req->reply_conn = from_conn; @@ -521,7 +533,7 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c series->target_addr = target_addr; const uint8_t* pubkey_to_use = target ? target->node.public_key : embedded_pubkey; if (!pubkey_to_use) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_req: no pubkey available for node %016llx", + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "no pubkey available for node %016llx", (unsigned long long)req_pkt->node_id); series->sock_ctx->avg_rtt = req_pkt->timeout_ms * 10; series->sock_ctx->count_sent = req_pkt->count; @@ -561,11 +573,11 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c void route_ping_handle_resp(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) { if (!bgp || !from_conn || !data || len < sizeof(struct BGP_PING_RESPONSE)) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_resp: invalid args"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid args"); return; } const struct BGP_PING_RESPONSE* resp = (const struct BGP_PING_RESPONSE*)data; - DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_handle_resp: from=%s request_id=%016llx sent=%u ok=%u avg_rtt=%u", + DEBUG_INFO(DEBUG_CATEGORY_BGP, "from=%s request_id=%016llx sent=%u ok=%u avg_rtt=%u", from_conn->log_name, (unsigned long long)resp->request_id, (unsigned)resp->count_sent, (unsigned)resp->count_ok, (unsigned)resp->avg_rtt); @@ -590,6 +602,6 @@ void route_ping_handle_resp(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, } cur = &(*cur)->next; } - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_resp: request_id=%016llx not found in pending list", + DEBUG_WARN(DEBUG_CATEGORY_BGP, "request_id=%016llx not found in pending list", (unsigned long long)resp->request_id); } diff --git a/tests/test_nat_detection.c b/tests/test_nat_detection.c index a0324ad9..4841a203 100644 --- a/tests/test_nat_detection.c +++ b/tests/test_nat_detection.c @@ -124,7 +124,7 @@ static int create_temp_configs(void) { "\n" "[server:test_c1]\n" "addr=127.0.0.1:39012\n" - "type=public\n" + "type=nat\n" "\n" "[client:to_s]\n" "keepalive=1\n" @@ -161,6 +161,16 @@ static int has_initialized_link(struct UTUN_INSTANCE* inst) { return 0; } +static struct ETCP_LINK* find_link_to_node(struct UTUN_INSTANCE* inst, uint64_t node_id) { + if (!inst) return NULL; + struct ETCP_CONN* conn = inst->connections; + while (conn) { + if (conn->peer_node_id == node_id) return conn->links; + conn = conn->next; + } + return NULL; +} + static void test_timeout_cb(void* arg) { (void)arg; test_timed_out = 1; @@ -248,32 +258,46 @@ int main(void) { goto cleanup; } - // 3. Wait for NAT detection to complete for C1 on server + // Verify C1 socket has config type before NAT detection + { + struct ETCP_SOCKET* s = inst_c1->etcp_sockets; + if (!s || s->nat_type != CFG_SERVER_TYPE_NAT) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: C1 socket nat_type=%d, expected CFG_SERVER_TYPE_NAT(%d) before detection", + s ? (int)s->nat_type : -1, CFG_SERVER_TYPE_NAT); + goto cleanup; + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "C1 socket has config NAT type before detection"); + } + + // 3. Wait for NAT detection to complete for C1 - check link on server + struct ETCP_LINK* link_sc1 = find_link_to_node(inst_s, NODE_ID_C1); + if (!link_sc1) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "No link to C1 on server"); + goto cleanup; + } DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for NAT detection to complete for C1..."); bgp_wait_cycles = 0; while (!test_timed_out && bgp_wait_cycles < 1500) { - struct NODEINFO_Q* node_c1 = route_bgp_get_node(inst_s->bgp, NODE_ID_C1); - if (node_c1 && node_c1->nat_check_status == NAT_CHECK_OPEN) { + if (link_sc1->nat_check_status == NAT_CHECK_OPEN) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT detection completed for C1: OPEN"); break; } uasync_poll(ua, 10); bgp_wait_cycles++; } - struct NODEINFO_Q* node_c1 = route_bgp_get_node(inst_s->bgp, NODE_ID_C1); - if (!node_c1 || node_c1->nat_check_status != NAT_CHECK_OPEN) { + if (!link_sc1 || link_sc1->nat_check_status != NAT_CHECK_OPEN) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NAT detection did not complete for C1"); goto cleanup; } - // 4. Wait for C1 to receive NAT_INFO + // 4. Wait for C1 to receive NAT_INFO (verified type) DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for C1 to receive NAT_INFO..."); bgp_wait_cycles = 0; while (!test_timed_out && bgp_wait_cycles < 500) { struct ETCP_SOCKET* sock = inst_c1->etcp_sockets; int found = 0; while (sock) { - if (sock->nat_type == NAT_TYPE_OPEN) { found = 1; break; } + if (sock->nat_type == NAT_VERIFIED_OPEN) { found = 1; break; } sock = sock->next; } if (found) { @@ -285,38 +309,32 @@ int main(void) { } // 5. Verify all NAT fields on server - node_c1 = route_bgp_get_node(inst_s->bgp, NODE_ID_C1); + struct NODEINFO_Q* node_c1 = route_bgp_get_node(inst_s->bgp, NODE_ID_C1); if (!node_c1) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "NODEINFO_Q for C1 disappeared"); goto cleanup; } - if (node_c1->nat_check_status != NAT_CHECK_OPEN) { + if (link_sc1->nat_check_status != NAT_CHECK_OPEN) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: nat_check_status=%d, expected OPEN(%d)", - (int)node_c1->nat_check_status, NAT_CHECK_OPEN); + (int)link_sc1->nat_check_status, NAT_CHECK_OPEN); goto cleanup; } - if (node_c1->nat_type != NAT_TYPE_OPEN) { + if (link_sc1->nat_type != NAT_TYPE_OPEN) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: nat_type=%d, expected OPEN(%d)", - (int)node_c1->nat_type, NAT_TYPE_OPEN); + (int)link_sc1->nat_type, NAT_TYPE_OPEN); goto cleanup; } - if (node_c1->nat_ip == 0 || node_c1->nat_port == 0) { + if (link_sc1->nat_ip == 0 || link_sc1->nat_port == 0) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: nat_ip/port not set (ip=%08x port=%u)", - (unsigned)node_c1->nat_ip, (unsigned)node_c1->nat_port); + (unsigned)link_sc1->nat_ip, (unsigned)link_sc1->nat_port); goto cleanup; } // Verify link nat_type on server - struct ETCP_CONN* conn_sc1 = NULL; - struct ETCP_LINK* link_sc1 = NULL; - struct ETCP_CONN* conn = inst_s->connections; - while (conn) { - if (conn->peer_node_id == NODE_ID_C1) { - conn_sc1 = conn; - link_sc1 = conn->links; - break; - } - conn = conn->next; + struct ETCP_CONN* conn_sc1 = inst_s->connections; + while (conn_sc1) { + if (conn_sc1->peer_node_id == NODE_ID_C1) break; + conn_sc1 = conn_sc1->next; } if (!link_sc1 || link_sc1->nat_type != NAT_TYPE_OPEN) { DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: link nat_type not OPEN on server"); @@ -327,21 +345,72 @@ int main(void) { struct ETCP_SOCKET* sock_c1 = NULL; struct ETCP_SOCKET* sock = inst_c1->etcp_sockets; while (sock) { - if (sock->nat_type == NAT_TYPE_OPEN) { + if (sock->nat_type == NAT_VERIFIED_OPEN) { sock_c1 = sock; break; } sock = sock->next; } if (!sock_c1) { - DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: no socket with nat_type OPEN on C1"); + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: no socket with NAT_VERIFIED_OPEN on C1"); goto cleanup; } + // Verify local_node socket update on C1 (received NAT_INFO updated nodeinfo) + if (inst_c1->bgp && inst_c1->bgp->local_node) { + const struct NODEINFO_IPV4_SOCKET* sockets = NULL; + int sock_count = get_node_v4_sockets(inst_c1->bgp->local_node, &sockets); + int found = 0; + for (int i = 0; i < sock_count; i++) { + if (sockets[i].id == sock_c1->sock_id) { + uint32_t s_ip = (sockets[i].addr[0] << 24) | (sockets[i].addr[1] << 16) | + (sockets[i].addr[2] << 8) | sockets[i].addr[3]; + if (s_ip != link_sc1->nat_ip || sockets[i].port != link_sc1->nat_port || + sockets[i].type != NAT_VERIFIED_OPEN) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: local_node socket not updated on C1"); + goto cleanup; + } + found = 1; + break; + } + } + if (!found) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: socket not found in local_node on C1"); + goto cleanup; + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "local_node socket update check PASSED on C1"); + } + + // Wait for C2 to learn updated C1 nodeinfo (with verified NAT type) + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Waiting for C2 to learn updated C1 nodeinfo..."); + bgp_wait_cycles = 0; + int c2_verified_nat = 0; + while (!test_timed_out && bgp_wait_cycles < 500) { + struct NODEINFO_Q* node_c1_on_c2 = inst_c2->bgp ? route_bgp_get_node(inst_c2->bgp, NODE_ID_C1) : NULL; + if (node_c1_on_c2) { + const struct NODEINFO_IPV4_SOCKET* sockets = NULL; + int sock_count = get_node_v4_sockets(node_c1_on_c2, &sockets); + for (int i = 0; i < sock_count; i++) { + if (sockets[i].type == NAT_VERIFIED_OPEN) { + c2_verified_nat = 1; + break; + } + } + if (c2_verified_nat) break; + } + uasync_poll(ua, 10); + bgp_wait_cycles++; + } + if (!c2_verified_nat) { + DEBUG_ERROR(DEBUG_CATEGORY_BGP, "FAIL: C2 did not receive updated C1 nodeinfo with verified NAT"); + goto cleanup; + } + DEBUG_INFO(DEBUG_CATEGORY_BGP, "C2 received updated C1 nodeinfo with verified NAT"); + // 6. Separate STUN check via explicit route_ping_send_req_addr DEBUG_INFO(DEBUG_CATEGORY_BGP, "Performing explicit STUN ping from S via C2 to C1..."); struct ETCP_CONN* conn_sc2 = NULL; - conn = inst_s->connections; + struct ETCP_CONN* conn = inst_s->connections; while (conn) { if (conn->peer_node_id == NODE_ID_C2) { conn_sc2 = conn; break; } conn = conn->next; @@ -353,7 +422,7 @@ int main(void) { memset(&nat_ping_result, 0, sizeof(nat_ping_result)); int ret = route_ping_send_req_addr(inst_s->bgp, conn_sc2, NODE_ID_C1, - node_c1->nat_ip, node_c1->nat_port, + link_sc1->nat_ip, link_sc1->nat_port, 3, 10, 200, 3000, nat_ping_resp_cb, NULL, node_c1->node.public_key); if (ret != 0) { @@ -409,7 +478,7 @@ int main(void) { DEBUG_INFO(DEBUG_CATEGORY_BGP, "Testing route ping without embedded pubkey..."); memset(&nat_ping_result, 0, sizeof(nat_ping_result)); ret = route_ping_send_req_addr(inst_s->bgp, conn_sc2, NODE_ID_C1, - node_c1->nat_ip, node_c1->nat_port, + link_sc1->nat_ip, link_sc1->nat_port, 3, 10, 200, 3000, nat_ping_resp_cb, NULL, NULL); if (ret != 0) {