From 0c748501c89cee322611a4ad5d994d6f1cf17d5b Mon Sep 17 00:00:00 2001 From: Evgeny Date: Thu, 23 Apr 2026 22:02:42 +0300 Subject: [PATCH] GUI: Add NAT address to socket display in etcpmon --- src/control_server.c | 14 ++++++++++++++ src/etcp_connections.c | 8 ++++++++ src/etcp_connections.h | 1 + tools/etcpmon/etcpmon_gui.c | 22 ++++++++++++++++------ tools/etcpmon/etcpmon_protocol.h | 2 ++ 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/control_server.c b/src/control_server.c index 39d88e5c..d046b001 100644 --- a/src/control_server.c +++ b/src/control_server.c @@ -844,6 +844,20 @@ static void send_socket_list(struct control_server* server, struct control_clien info[i].port = 0; } info[i].nat_type = sock->nat_type; + + /* NAT address from socket (set when INIT_RESPONSE received) */ + info[i].nat_ip[0] = '\0'; + info[i].nat_port = 0; + if (sock->nat_addr.ss_family == AF_INET) { + struct sockaddr_in* sin = (struct sockaddr_in*)&sock->nat_addr; + inet_ntop(AF_INET, &sin->sin_addr, info[i].nat_ip, sizeof(info[i].nat_ip)); + info[i].nat_port = ntohs(sin->sin_port); + } else if (sock->nat_addr.ss_family == AF_INET6) { + struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&sock->nat_addr; + inet_ntop(AF_INET6, &sin6->sin6_addr, info[i].nat_ip, sizeof(info[i].nat_ip)); + info[i].nat_port = ntohs(sin6->sin6_port); + } + sock = sock->next; } diff --git a/src/etcp_connections.c b/src/etcp_connections.c index 4078c622..6786b6ac 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -1569,6 +1569,14 @@ process_decrypted: link->etcp->log_name, ip_to_str(&old_addr.s_addr, AF_INET).str, link->nat_port, ip_to_str(&new_addr.s_addr, AF_INET).str, new_nat_port, link->nat_changes_count); } + + // Update socket NAT address + { + struct sockaddr_in* sin = (struct sockaddr_in*)&e_sock->nat_addr; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = new_nat_ip; + sin->sin_port = htons(new_nat_port); + } } else { // Legacy format without NAT info DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "[%s] Received legacy INIT_RESPONSE without NAT info", diff --git a/src/etcp_connections.h b/src/etcp_connections.h index cd5bad3f..e371fc98 100644 --- a/src/etcp_connections.h +++ b/src/etcp_connections.h @@ -74,6 +74,7 @@ struct ETCP_SOCKET { uint8_t local_defaultroute_ip6[16]; // auto-detected IPv6 for public servers uint8_t only_local; // 1 = only local connections, no forwarding struct sockaddr_storage interface_addr; // адрес интерфейса: если bind на интерфейс - его IP, если 0.0.0.0 без интерфейса - IP интерфейса через который идет default route, иначе - адрес из конфига + struct sockaddr_storage nat_addr; // NAT адрес (network byte order), ss_family=0 = не определён }; // NAT check status diff --git a/tools/etcpmon/etcpmon_gui.c b/tools/etcpmon/etcpmon_gui.c index 84fa2861..1e92961e 100644 --- a/tools/etcpmon/etcpmon_gui.c +++ b/tools/etcpmon/etcpmon_gui.c @@ -1231,14 +1231,24 @@ void etcpmon_gui_update_socket_list(struct etcpmon_app* app, if (list[i].ip[0] == '\0') continue; if (list[i].name[0] == '\0') continue; - char display[128]; + char display[256]; const char* nat_str = nat_type_to_string(list[i].nat_type); - if (list[i].is_ipv6) { - snprintf(display, sizeof(display), "[%s]:%d | NAT: %s", - list[i].ip, list[i].port, nat_str); + if (list[i].nat_ip[0] != '\0') { + if (list[i].is_ipv6) { + snprintf(display, sizeof(display), "[%s]:%d | NAT: %s (%s:%d)", + list[i].ip, list[i].port, nat_str, list[i].nat_ip, list[i].nat_port); + } else { + snprintf(display, sizeof(display), "%s:%d | NAT: %s (%s:%d)", + list[i].ip, list[i].port, nat_str, list[i].nat_ip, list[i].nat_port); + } } else { - snprintf(display, sizeof(display), "%s:%d | NAT: %s", - list[i].ip, list[i].port, nat_str); + if (list[i].is_ipv6) { + snprintf(display, sizeof(display), "[%s]:%d | NAT: %s", + list[i].ip, list[i].port, nat_str); + } else { + snprintf(display, sizeof(display), "%s:%d | NAT: %s", + list[i].ip, list[i].port, nat_str); + } } SendMessageA(app->hListSockets, LB_ADDSTRING, 0, (LPARAM)display); } diff --git a/tools/etcpmon/etcpmon_protocol.h b/tools/etcpmon/etcpmon_protocol.h index 881a550d..85e3fc32 100644 --- a/tools/etcpmon/etcpmon_protocol.h +++ b/tools/etcpmon/etcpmon_protocol.h @@ -118,6 +118,8 @@ struct etcpmon_socket_info { uint16_t port; /* Port number (host byte order) */ uint8_t is_ipv6; /* 1 = IPv6, 0 = IPv4 */ uint8_t nat_type; /* NAT type (NAT_TYPE_*, NAT_VERIFIED_*) */ + char nat_ip[46]; /* Null-terminated NAT IP address string */ + uint16_t nat_port; /* NAT port (host byte order) */ }; struct etcpmon_rsp_socket_list {