From 1d34953f2597a83fe03da6e3b3960d42faba5d30 Mon Sep 17 00:00:00 2001 From: DcruBro Date: Thu, 1 Jan 2026 17:08:35 +0100 Subject: [PATCH 1/3] interface on win32 - v1 --- .../common/net/virtual_interface.hpp | 6 ++ src/common/virtual_interface.cpp | 82 ++++++++++++------- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/include/columnlynx/common/net/virtual_interface.hpp b/include/columnlynx/common/net/virtual_interface.hpp index f207b1f..c430ddf 100644 --- a/include/columnlynx/common/net/virtual_interface.hpp +++ b/include/columnlynx/common/net/virtual_interface.hpp @@ -36,6 +36,12 @@ #include #include #include + + #include + #include + + #pragma comment(lib, "iphlpapi.lib") + #pragma comment(lib, "ws2_32.lib") #endif namespace ColumnLynx::Net { diff --git a/src/common/virtual_interface.cpp b/src/common/virtual_interface.cpp index 4e7f0d8..9fd1a27 100644 --- a/src/common/virtual_interface.cpp +++ b/src/common/virtual_interface.cpp @@ -433,41 +433,65 @@ namespace ColumnLynx::Net { uint16_t mtu) { #ifdef _WIN32 - std::string ip = ipv4ToString(clientIP); - std::string gw = ipv4ToString(serverIP); - std::string mask; + // Interface alias → LUID → Index + std::wstring ifAlias(mIfName.begin(), mIfName.end()); - // Convert prefixLen → subnet mask - uint32_t maskInt = (prefixLen == 0) ? 0 : (0xFFFFFFFF << (32 - prefixLen)); - mask = ipv4ToString(maskInt); + NET_LUID luid; + if (ConvertInterfaceAliasToLuid(ifAlias.c_str(), &luid) != NO_ERROR) + return false; - // Calculate network address from IP and mask - uint32_t networkInt = (clientIP & maskInt); - std::string network = ipv4ToString(networkInt); + NET_IFINDEX ifIndex; + if (ConvertInterfaceLuidToIndex(&luid, &ifIndex) != NO_ERROR) + return false; - char cmd[512]; + // ssign IPv4 address + prefix + MIB_UNICASTIPADDRESS_ROW addr; + InitializeUnicastIpAddressEntry(&addr); - // 1. Set the static IP + mask + gateway - snprintf(cmd, sizeof(cmd), - "netsh interface ip set address name=\"%s\" static %s %s %s", - mIfName.c_str(), ip.c_str(), mask.c_str(), gw.c_str() - ); - system(cmd); + addr.InterfaceIndex = ifIndex; + addr.Address.si_family = AF_INET; + addr.Address.Ipv4.sin_addr.s_addr = htonl(clientIP); + addr.OnLinkPrefixLength = prefixLen; + addr.DadState = IpDadStatePreferred; - // 2. Set MTU (separate command) - snprintf(cmd, sizeof(cmd), - "netsh interface ipv4 set subinterface \"%s\" mtu=%u store=persistent", - mIfName.c_str(), mtu - ); - system(cmd); + if (CreateUnicastIpAddressEntry(&addr) != NO_ERROR) + return false; - // 3. Add route for the VPN network to go through the TUN interface - // This is critical: tells Windows to send packets destined for the server/network through the TUN interface - snprintf(cmd, sizeof(cmd), - "netsh routing ip add persistentroute dest=%s/%d name=\"%s\" nexthopcfg=%s", - network.c_str(), prefixLen, mIfName.c_str(), gw.c_str() - ); - system(cmd); + // Set MTU + MIB_IFROW ifRow; + ifRow.dwIndex = ifIndex; + + if (GetIfEntry(&ifRow) != NO_ERROR) + return false; + + ifRow.dwMtu = mtu; + + if (SetIfEntry(&ifRow) != NO_ERROR) + return false; + + // Add persistent route for VPN network via this interface + uint32_t mask = + (prefixLen == 0) ? 0 : (0xFFFFFFFFu << (32 - prefixLen)); + uint32_t network = clientIP & mask; + + MIB_IPFORWARD_ROW2 route; + InitializeIpForwardEntry(&route); + + route.InterfaceIndex = ifIndex; + route.DestinationPrefix.Prefix.si_family = AF_INET; + route.DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr = htonl(network); + route.DestinationPrefix.PrefixLength = prefixLen; + + route.NextHop.si_family = AF_INET; + route.NextHop.Ipv4.sin_addr.s_addr = htonl(serverIP); + + route.Metric = 5; + route.Protocol = MIB_IPPROTO_NETMGMT; + route.ValidLifetime = 0xFFFFFFFF; + route.PreferredLifetime = 0xFFFFFFFF; + + if (CreateIpForwardEntry2(&route) != NO_ERROR) + return false; return true; #else From cf3ec30492f3a3d6b36e1e855c238782f1c7aa16 Mon Sep 17 00:00:00 2001 From: DcruBro Date: Thu, 1 Jan 2026 17:11:02 +0100 Subject: [PATCH 2/3] interface on win32 - v1 --- src/common/virtual_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/virtual_interface.cpp b/src/common/virtual_interface.cpp index 9fd1a27..ff90c45 100644 --- a/src/common/virtual_interface.cpp +++ b/src/common/virtual_interface.cpp @@ -486,7 +486,7 @@ namespace ColumnLynx::Net { route.NextHop.Ipv4.sin_addr.s_addr = htonl(serverIP); route.Metric = 5; - route.Protocol = MIB_IPPROTO_NETMGMT; + route.Protocol = static_cast(MIB_IPPROTO_NETMGMT); route.ValidLifetime = 0xFFFFFFFF; route.PreferredLifetime = 0xFFFFFFFF; From ccbacd118075a6f5db1c827ebbdff2046550905d Mon Sep 17 00:00:00 2001 From: DcruBro Date: Thu, 1 Jan 2026 17:15:58 +0100 Subject: [PATCH 3/3] interface on win32 - v1 --- src/common/virtual_interface.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/common/virtual_interface.cpp b/src/common/virtual_interface.cpp index ff90c45..1e3b573 100644 --- a/src/common/virtual_interface.cpp +++ b/src/common/virtual_interface.cpp @@ -483,14 +483,15 @@ namespace ColumnLynx::Net { route.DestinationPrefix.PrefixLength = prefixLen; route.NextHop.si_family = AF_INET; - route.NextHop.Ipv4.sin_addr.s_addr = htonl(serverIP); + route.NextHop.Ipv4.sin_addr.s_addr = 0; - route.Metric = 5; + route.Metric = 1; route.Protocol = static_cast(MIB_IPPROTO_NETMGMT); route.ValidLifetime = 0xFFFFFFFF; route.PreferredLifetime = 0xFFFFFFFF; - if (CreateIpForwardEntry2(&route) != NO_ERROR) + DWORD r = CreateIpForwardEntry2(&route); + if (r != NO_ERROR && r != ERROR_OBJECT_ALREADY_EXISTS) return false; return true;