Browse Source

ping

congestion
Evgeny 6 months ago
parent
commit
54982f2dfb
  1. 2
      src/etcp_connections.c
  2. 21
      src/etcp_connections.h
  3. 248
      src/route_bgp.c
  4. 21
      src/route_bgp.h
  5. 4
      src/route_node.c
  6. 16
      src/route_node.h
  7. 66
      src/route_ping.c
  8. 129
      tests/test_nat_detection.c

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

21
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 пакетов

248
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);
}

21
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

4
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++;
}

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

66
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);
}

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

Loading…
Cancel
Save