Fix: Use netsh for adding routes on Windows (wintun)
- Get wintun interface index directly after adapter creation - Use netsh instead of CreateIpForwardEntry (doesn't work with wintun) - Fallback to CreateIpForwardEntry if netsh fails
This commit is contained in:
1 parent
9d0223d3fa
commit
3945ff5665
5 files changed
+59
-22
No files matched your search
@@ -56,6 +56,7 @@ struct tun_if {
|
||||
HANDLE read_thread;
|
||||
HANDLE stop_event;
|
||||
volatile int running; // 1 = поток работает
|
||||
DWORD ifindex; // Windows: интерфейсный индекс
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
+40
-17
@@ -138,10 +138,9 @@ static int ip_route_cmd(const char *ifname, uint32_t network, uint8_t prefix_len
|
||||
return (ret == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
int ifindex = if_nametoindex(ifname);
|
||||
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
if (ifindex == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface index is 0");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -153,7 +152,9 @@ int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
}
|
||||
|
||||
// Fallback to ip route command
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for %s", ifname);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for ifindex %u", ifindex);
|
||||
char ifname[16];
|
||||
snprintf(ifname, sizeof(ifname), "%u", ifindex);
|
||||
return ip_route_cmd(ifname, ntohl(network), prefix_len, "add");
|
||||
}
|
||||
|
||||
@@ -198,16 +199,36 @@ int tun_route_flush(const char *ifname) {
|
||||
|
||||
// Windows IP Helper API implementation
|
||||
|
||||
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
if (ifindex == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_add: ifindex is 0");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t dest = htonl(network);
|
||||
uint32_t mask = prefix_to_netmask(prefix_len);
|
||||
|
||||
char cmd[256];
|
||||
struct in_addr dest_addr;
|
||||
dest_addr.s_addr = dest;
|
||||
snprintf(cmd, sizeof(cmd), "netsh interface ip add route %s/%d interface=%lu store=active",
|
||||
inet_ntoa(dest_addr), prefix_len, (unsigned long)ifindex);
|
||||
int sys_ret = system(cmd);
|
||||
if (sys_ret == 0) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Added route %s/%d via ifindex=%lu",
|
||||
inet_ntoa(dest_addr), prefix_len, (unsigned long)ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MIB_IPFORWARDROW route;
|
||||
memset(&route, 0, sizeof(route));
|
||||
|
||||
route.dwForwardDest = htonl(network);
|
||||
route.dwForwardMask = prefix_to_netmask(prefix_len);
|
||||
route.dwForwardDest = dest;
|
||||
route.dwForwardMask = mask;
|
||||
route.dwForwardPolicy = 0;
|
||||
route.dwForwardNextHop = 0; // On-link route
|
||||
route.dwForwardIfIndex = if_nametoindex(ifname);
|
||||
route.dwForwardType = MIB_IPROUTE_TYPE_DIRECT;
|
||||
route.dwForwardNextHop = 0;
|
||||
route.dwForwardIfIndex = ifindex;
|
||||
route.dwForwardType = MIB_IPROUTE_TYPE_INDIRECT;
|
||||
route.dwForwardProto = MIB_IPPROTO_NETMGMT;
|
||||
route.dwForwardAge = 0;
|
||||
route.dwForwardNextHopAS = 0;
|
||||
@@ -219,7 +240,8 @@ int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
|
||||
DWORD ret = CreateIpForwardEntry(&route);
|
||||
if (ret != NO_ERROR) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to add route: %lu", ret);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to add route %s/%d: %lu",
|
||||
inet_ntoa(dest_addr), prefix_len, ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -356,10 +378,9 @@ static int route_cmd(const char *ifname, uint32_t network, uint8_t prefix_len, c
|
||||
return (ret == 0) ? 0 : -1;
|
||||
}
|
||||
|
||||
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
int ifindex = if_nametoindex(ifname);
|
||||
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
|
||||
if (ifindex == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface %s not found", ifname);
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface index is 0");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -369,7 +390,9 @@ int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len) {
|
||||
}
|
||||
|
||||
// Fallback to route command
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for %s", ifname);
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for ifindex %u", ifindex);
|
||||
char ifname[16];
|
||||
snprintf(ifname, sizeof(ifname), "%u", ifindex);
|
||||
return route_cmd(ifname, network, prefix_len, "add");
|
||||
}
|
||||
|
||||
@@ -406,14 +429,14 @@ int tun_route_flush(const char *ifname) {
|
||||
|
||||
// Platform-independent functions
|
||||
|
||||
int tun_route_add_all(const char *ifname, struct CFG_ROUTE_ENTRY *routes) {
|
||||
int tun_route_add_all(uint32_t ifindex, const char *ifname, struct CFG_ROUTE_ENTRY *routes) {
|
||||
int count = 0;
|
||||
struct CFG_ROUTE_ENTRY *entry = routes;
|
||||
|
||||
while (entry) {
|
||||
uint32_t network = ntohl(entry->ip.addr.v4.s_addr);
|
||||
if (entry->ip.family == AF_INET) {
|
||||
if (tun_route_add(ifname, network, entry->netmask) == 0) {
|
||||
if (tun_route_add(ifindex, network, entry->netmask) == 0) {
|
||||
struct in_addr addr;
|
||||
addr.s_addr = entry->ip.addr.v4.s_addr;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Added route %s/%d via %s", ip_to_str(&addr, AF_INET).str, entry->netmask, ifname);
|
||||
|
||||
+5
-4
@@ -13,12 +13,12 @@ struct CFG_ROUTE_ENTRY;
|
||||
|
||||
/**
|
||||
* @brief Add system route for a subnet via TUN interface
|
||||
* @param ifname Interface name (e.g., "tun0")
|
||||
* @param ifindex Interface index
|
||||
* @param network Network address in host byte order
|
||||
* @param prefix_len Prefix length (1-32)
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int tun_route_add(const char *ifname, uint32_t network, uint8_t prefix_len);
|
||||
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len);
|
||||
|
||||
/**
|
||||
* @brief Delete system route for a subnet via TUN interface
|
||||
@@ -38,11 +38,12 @@ int tun_route_flush(const char *ifname);
|
||||
|
||||
/**
|
||||
* @brief Add multiple routes from config entries
|
||||
* @param ifname Interface name (e.g., "tun0")
|
||||
* @param ifindex Interface index
|
||||
* @param ifname Interface name (e.g., "tun0") - for logging only
|
||||
* @param routes Linked list of route entries
|
||||
* @return Number of routes added successfully
|
||||
*/
|
||||
int tun_route_add_all(const char *ifname, struct CFG_ROUTE_ENTRY *routes);
|
||||
int tun_route_add_all(uint32_t ifindex, const char *ifname, struct CFG_ROUTE_ENTRY *routes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -172,6 +172,18 @@ int tun_platform_init(struct tun_if* tun, const char* ifname, const char* ip_str
|
||||
tun->platform_handle = session;
|
||||
tun->adapter_handle = adapter;
|
||||
strncpy(tun->ifname, ifname && ifname[0] ? ifname : "utun", sizeof(tun->ifname)-1);
|
||||
|
||||
NET_LUID luid;
|
||||
WintunGetAdapterLUID(adapter, &luid);
|
||||
NET_IFINDEX idx = 0;
|
||||
if (ConvertInterfaceLuidToIndex(&luid, &idx) == NO_ERROR) {
|
||||
tun->ifindex = idx;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Wintun interface index: %lu", (unsigned long)idx);
|
||||
} else {
|
||||
tun->ifindex = 0;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to get interface index from LUID");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
|
||||
|
||||
// Add system routes for route_subnets
|
||||
if (config->route_subnets) {
|
||||
int added = tun_route_add_all(instance->tun->ifname, config->route_subnets);
|
||||
int added = tun_route_add_all(instance->tun->ifindex, instance->tun->ifname, config->route_subnets);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Added %d system routes for TUN interface", added);
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user