Browse Source

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
nodeinfo-routing-update
jeka 1 month ago
parent
commit
3945ff5665
  1. 1
      src/tun_if.h
  2. 57
      src/tun_route.c
  3. 9
      src/tun_route.h
  4. 12
      src/tun_windows.c
  5. 2
      src/utun_instance.c

1
src/tun_if.h

@ -56,6 +56,7 @@ struct tun_if {
HANDLE read_thread;
HANDLE stop_event;
volatile int running; // 1 = поток работает
DWORD ifindex; // Windows: интерфейсный индекс
#endif
};

57
src/tun_route.c

@ -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);

9
src/tun_route.h

@ -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
}

12
src/tun_windows.c

@ -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;
}

2
src/utun_instance.c

@ -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 {

Loading…
Cancel
Save