From 8bad15b7bbf4269be0d9350b26651f837644b5ce Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 15 Apr 2026 15:15:15 +0300 Subject: [PATCH] 1 --- lib/debug_config.c | 43 ++++++++++++++++++++++++++++++++++++++++++ lib/debug_config.h | 3 ++- lib/socket_compat.c | 15 +++++++++++++++ lib/socket_compat.h | 3 +++ src/etcp_connections.c | 14 ++------------ src/route_bgp.c | 16 ++++++++++------ src/route_bgp.txt | 16 ++++++++++++++++ 7 files changed, 91 insertions(+), 19 deletions(-) diff --git a/lib/debug_config.c b/lib/debug_config.c index f6de38f6..5ec21690 100644 --- a/lib/debug_config.c +++ b/lib/debug_config.c @@ -57,6 +57,49 @@ ip_str_t ip_to_str(const void *addr, int family) { return result; } +ip_str_t sockaddr_storage_to_str(const struct sockaddr_storage *addr) { + ip_str_t result; + result.str[0] = '\0'; + + if (!addr) { + return result; + } + + char ip_buf[INET6_ADDRSTRLEN]; + ip_buf[0] = '\0'; + + uint16_t port = 0; + void *src = NULL; + + if (addr->ss_family == AF_INET) { + const struct sockaddr_in *ipv4 = (const struct sockaddr_in *)addr; + src = (void *)&ipv4->sin_addr; + port = ntohs(ipv4->sin_port); + } + else if (addr->ss_family == AF_INET6) { + const struct sockaddr_in6 *ipv6 = (const struct sockaddr_in6 *)addr; + src = (void *)&ipv6->sin6_addr; + port = ntohs(ipv6->sin6_port); + } + else { + return result; + } + + if (!inet_ntop(addr->ss_family, src, ip_buf, sizeof(ip_buf))) { + return result; + } + + if (addr->ss_family == AF_INET6) { + // IPv6 обязательно в [] + snprintf(result.str, sizeof(result.str), "[%s]:%u", ip_buf, port); + } else { + snprintf(result.str, sizeof(result.str), "%s:%u", ip_buf, port); + } + + return result; +} + + static const struct { const char* name; diff --git a/lib/debug_config.h b/lib/debug_config.h index 4b6f946c..622e4b1e 100644 --- a/lib/debug_config.h +++ b/lib/debug_config.h @@ -111,10 +111,11 @@ void debug_enable_console(int enable); // IP address to string (static buffer, single-threaded) typedef struct { - char str[48]; // INET6_ADDRSTRLEN(45) + \0 + char str[54]; // INET6_ADDRSTRLEN(45) + 6chars (:port) + \0 } ip_str_t; ip_str_t ip_to_str(const void *addr, int family);// big endian addr +ip_str_t sockaddr_storage_to_str(const struct sockaddr_storage *addr);// автоопределение v4 или v6 // hex dump в лог void log_dump(const char* prefix, const uint8_t* data, size_t len); diff --git a/lib/socket_compat.c b/lib/socket_compat.c index f084c34e..d99bdde5 100644 --- a/lib/socket_compat.c +++ b/lib/socket_compat.c @@ -230,3 +230,18 @@ ssize_t socket_recvfrom(socket_t sock, void* buf, size_t len, return recvfrom(sock, buf, len, 0, src, src_len); #endif } + +uint16_t ss_get_port(const struct sockaddr_storage *addr) { + if (!addr) return 0; + + if (addr->ss_family == AF_INET) { + const struct sockaddr_in *ipv4 = (const struct sockaddr_in *)addr; + return ntohs(ipv4->sin_port); + } + else if (addr->ss_family == AF_INET6) { + const struct sockaddr_in6 *ipv6 = (const struct sockaddr_in6 *)addr; + return ntohs(ipv6->sin6_port); + } + + return 0; +} diff --git a/lib/socket_compat.h b/lib/socket_compat.h index 006ec215..d9fb6eae 100644 --- a/lib/socket_compat.h +++ b/lib/socket_compat.h @@ -69,4 +69,7 @@ ssize_t socket_recvfrom(socket_t sock, void* buf, size_t len, // Utility const char* socket_strerror(int err); +// взять порт из sockaddr_storage +uint16_t ss_get_port(const struct sockaddr_storage *addr); + #endif // SOCKET_COMPAT_H diff --git a/src/etcp_connections.c b/src/etcp_connections.c index 3f1fbdaa..b4c35097 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -926,7 +926,7 @@ static int etcp_send_ping_raw(struct ETCP_DGRAM* dgram, socket_t fd, sc_context_ DEBUG_ERROR(DEBUG_CATEGORY_BGP, "sendto failed for ping, err=%d", socket_get_error()); return -1; } - DEBUG_TRACE(DEBUG_CATEGORY_BGP, "ping sendto succeeded, sent=%zd bytes", sent); + DEBUG_TRACE(DEBUG_CATEGORY_BGP, "ping sendto succeeded to %s sent=%zd bytes", sent, sockaddr_storage_to_str(addr).str); return (int)sent; } @@ -1593,18 +1593,8 @@ int init_sockets(struct UTUN_INSTANCE* instance) { } success_count++; - // Convert IP to string for logging - char addr_str[INET6_ADDRSTRLEN + 10]; - if (server->ip.ss_family == AF_INET) { - struct sockaddr_in* sin = (struct sockaddr_in*)&server->ip; - snprintf(addr_str, sizeof(addr_str), "%s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); - } else { - struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&server->ip; - snprintf(addr_str, sizeof(addr_str), "%s:%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port)); - } - DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Initialized server %s on %s (links: %zu)", - server->name, addr_str, e_sock->num_channels); + server->name, sockaddr_storage_to_str(&server->ip).str, e_sock->num_channels); server = server->next; } diff --git a/src/route_bgp.c b/src/route_bgp.c index 421448b2..112ee74f 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -424,7 +424,7 @@ void route_bgp_new_conn(struct ETCP_CONN* conn) { while (c) { struct ETCP_LINK* l = c->links; while (l) { - if (l->initialized && l->conn && l->nat_check_status == NAT_CHECK_NONE) { + if (l->initialized && l->conn && l->nat_check_status < NAT_CHECK_IN_PROGRESS) { route_bgp_start_link_nat_check(bgp, l); } l = l->next; @@ -687,9 +687,10 @@ static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LI // 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"); + DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "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; @@ -701,6 +702,9 @@ static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LI target_ip = ntohl(sin->sin_addr.s_addr); target_port = ntohs(sin->sin_port); } + + if (is_local_subnet(target_ip)) { DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "local ip: %s, skip nat check", ip_to_str(&target_ip, AF_INET).str); return; } + // Allocate callback arg struct nat_check_arg* arg = u_calloc(1, sizeof(struct nat_check_arg)); if (!arg) return; @@ -711,7 +715,7 @@ static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LI 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); + DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "no peer pubkey for link=%p", (void*)link); return; } // Send ping via third node - embed peer pubkey for NAT detection @@ -720,11 +724,11 @@ static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LI pubkey); if (ret == 0) { 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); + DEBUG_INFO(DEBUG_CATEGORY_BGP, "ping remote request via=%s (%s:%d)", + (void*)link, third_conn->log_name, ip_to_str(&target_ip, AF_INET).str, target_port); } else { u_free(arg); - DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_bgp_start_link_nat_check: failed to start for link=%p", + DEBUG_WARN(DEBUG_CATEGORY_BGP, "failed to start for link=%p", (void*)link); } } diff --git a/src/route_bgp.txt b/src/route_bgp.txt index a6142afc..1175869d 100644 --- a/src/route_bgp.txt +++ b/src/route_bgp.txt @@ -24,3 +24,19 @@ bgp_update local nodelist: bgp_withdraw(struct ROUTE_BGP bgp, uint64_t node_to_del, uint64_t wd_source) - wd_source это узел который захотел withdraw. - находим у себя node to del. удаляем если в hoplist найден wd_node (или мы = wd_node) если удалили - распространяем по всем линкам с этими же аргументами + + + +=============================== +определение nat + +определяем что оба узла в локальной сети: + -если обе ноды имеют локальные адреса сокетов пробуем пинг по локальным адресам + +если узел подключился и его сокетовый ip:port отличается от connection ip:port - устанавливаем флаг nat. и инициируем проверку пингом третьим узлом: +проверка считается успешной если по результату пинга ip источника пинга отличается от ip запросившего пинг узла. + +проверка типа nat узла который подключился: +- пингуем узел с целью зафиксировать свой ip (в сокете может быть например 0.0.0.0) +- даём команду третьему узлу пингануть этот узел. +- по результатам двух пингов определяем тип nat