diff --git a/lib/platform_compat.c b/lib/platform_compat.c index d0bf4cb..b815c12 100644 --- a/lib/platform_compat.c +++ b/lib/platform_compat.c @@ -3,16 +3,27 @@ #include "platform_compat.h" #include #include +#include +#include +#include #ifdef _WIN32 #include #include + #include + #pragma comment(lib, "iphlpapi.lib") #ifndef STATUS_SUCCESS #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #endif #else #include #include + #include + #include + #include + #include + #include + #include #endif /* @@ -35,3 +46,93 @@ int random_bytes(uint8_t *buffer, size_t len) { return (ret == (ssize_t)len) ? 0 : -1; #endif } + +#ifndef _WIN32 +static uint32_t get_default_route_ip_linux(void) { + FILE *f = fopen("/proc/net/route", "r"); + if (!f) return 0; + + char line[256]; + char *ifname = NULL; + unsigned int dest, gw; + + if (!fgets(line, sizeof(line), f)) { + fclose(f); + return 0; + } + + while (fgets(line, sizeof(line), f)) { + int items = sscanf(line, "%ms %x %x", &ifname, &dest, &gw); + if (items != 3) { + free(ifname); + continue; + } + + if (dest == 0) { + free(ifname); + break; + } + free(ifname); + ifname = NULL; + } + + fclose(f); + + if (!ifname) return 0; + + struct ifaddrs *ifaddr, *ifa; + if (getifaddrs(&ifaddr) == -1) { + free(ifname); + return 0; + } + + uint32_t result = 0; + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) continue; + if (ifa->ifa_name == NULL) continue; + if (strcmp(ifa->ifa_name, ifname) != 0) continue; + if (ifa->ifa_addr->sa_family != AF_INET) continue; + + struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr; + result = addr->sin_addr.s_addr; + break; + } + + freeifaddrs(ifaddr); + free(ifname); + return result; +} +#else +static uint32_t get_default_route_ip_windows(void) { + SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); + if (s == INVALID_SOCKET) return 0; + + struct sockaddr_in remote; + remote.sin_family = AF_INET; + remote.sin_port = htons(53); + remote.sin_addr.s_addr = inet_addr("8.8.8.8"); + + if (connect(s, (struct sockaddr *)&remote, sizeof(remote)) == SOCKET_ERROR) { + closesocket(s); + return 0; + } + + struct sockaddr_in local; + int len = sizeof(local); + if (getsockname(s, (struct sockaddr *)&local, &len) == SOCKET_ERROR) { + closesocket(s); + return 0; + } + + closesocket(s); + return local.sin_addr.s_addr; +} +#endif + +uint32_t get_default_route_ip(void) { +#ifdef _WIN32 + return get_default_route_ip_windows(); +#else + return get_default_route_ip_linux(); +#endif +} diff --git a/lib/platform_compat.h b/lib/platform_compat.h index 754d4c9..48ee17b 100644 --- a/lib/platform_compat.h +++ b/lib/platform_compat.h @@ -136,8 +136,14 @@ #include #endif +#include + // Generate cryptographically secure random bytes // Returns 0 on success, -1 on error int random_bytes(uint8_t *buffer, size_t len); +// Get IPv4 address of interface with default route (0.0.0.0 destination) +// Returns IPv4 address in network byte order, 0 on error +uint32_t get_default_route_ip(void); + #endif // PLATFORM_COMPAT_H diff --git a/src/config_parser.c b/src/config_parser.c index c9f6c00..22bd363 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -99,6 +99,10 @@ static int parse_key_value(const char *line, char *key, size_t key_len, char *va size_t val_len = strlen(val_start); if (val_len >= value_len) return -1; strcpy(value, val_start); + + char *comment = strchr(value, '#'); + if (comment) *comment = '\0'; + trim(value); return 0; diff --git a/src/etcp_connections.c b/src/etcp_connections.c index e405665..9b2825c 100644 --- a/src/etcp_connections.c +++ b/src/etcp_connections.c @@ -491,6 +491,7 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct socka e_sock->errorcode = 0; e_sock->pkt_format_errors = 0; e_sock->type = type; + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Add Socket type=%d", type); // Add to instance's socket list e_sock->next = instance->etcp_sockets; @@ -1136,7 +1137,24 @@ int init_connections(struct UTUN_INSTANCE* instance) { struct CFG_SERVER* server = config->servers; while (server) { // Create socket for this server + + // Auto-detect local IP for public servers with 0.0.0.0 + uint32_t default_ip = 0; + if (server->type == CFG_SERVER_TYPE_PUBLIC) { + struct sockaddr_in* sin = (struct sockaddr_in*)&server->ip; + if (sin->sin_addr.s_addr == 0) { + default_ip = get_default_route_ip(); + if (default_ip == 0) { + DEBUG_WARN(DEBUG_CATEGORY_ETCP, "Failed to detect default route IP for server %s", server->name); + } + } + } + struct ETCP_SOCKET* e_sock = etcp_socket_add(instance, &server->ip, server->netif_index, server->so_mark, server->type); + if (e_sock && default_ip != 0) { + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Server %s type %d ip=%08x", server->name, server->type, default_ip); + e_sock->local_defaultroute_ip = default_ip; + } if (!e_sock) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create socket for server %s", server->name); server = server->next; diff --git a/src/etcp_connections.h b/src/etcp_connections.h index 1a7e33f..b8be045 100644 --- a/src/etcp_connections.h +++ b/src/etcp_connections.h @@ -44,6 +44,7 @@ struct ETCP_SOCKET { void* socket_id; // Socket ID from uasync_add_socket uint8_t type; // CFG_SERVER_TYPE_PUBLIC/NAT/PRIVATE + uint32_t local_defaultroute_ip; // auto-detected IPv4 for public servers (network byte order) }; // ETCP Link - одно динамическое соединение (один путь) diff --git a/src/route_bgp.c b/src/route_bgp.c index 8dbd5d4..b6e4eca 100644 --- a/src/route_bgp.c +++ b/src/route_bgp.c @@ -383,10 +383,13 @@ static void route_bgp_send_route(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn, // Первый проход - PUBLIC while (link) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine: scanning conn type=%d init=%d", link->conn->type, link->initialized); + if (link->conn && link->conn->type == CFG_SERVER_TYPE_PUBLIC && link->initialized) { struct sockaddr_in* sin = (struct sockaddr_in*)&link->conn->local_addr; uint32_t ip = *(uint32_t*)&sin->sin_addr; uint16_t port = sin->sin_port; + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [public]"); route_bgp_send_route_single(bgp, conn, route, ip, port); sent_any = 1; } @@ -399,6 +402,7 @@ static void route_bgp_send_route(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn, if (link->conn && link->conn->type == CFG_SERVER_TYPE_NAT && link->nat_ip && link->initialized) { uint32_t ip = link->nat_ip; uint16_t port = link->nat_port; + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [nat]"); route_bgp_send_route_single(bgp, conn, route, ip, port); sent_any = 1; } @@ -407,10 +411,12 @@ static void route_bgp_send_route(struct ROUTE_BGP* bgp, struct ETCP_CONN* conn, // Если нет PUBLIC и NAT - отправляем без endpoint (0.0.0.0:0) if (!sent_any) { + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [any]"); route_bgp_send_route_single(bgp, conn, route, 0, 0); } } else { // Для LEARNED маршрутов - используем endpoint из route + DEBUG_INFO(DEBUG_CATEGORY_BGP, "Sending routine [learned]"); route_bgp_send_route_single(bgp, conn, route, htonl(route->endpoint_ip), htons(route->endpoint_port));